agendash 4.0.0 → 6.0.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.
Files changed (71) hide show
  1. package/LICENSE.md +25 -0
  2. package/README.md +109 -200
  3. package/dist/AgendashController.d.ts +50 -0
  4. package/dist/AgendashController.js +176 -0
  5. package/dist/AgendashController.js.map +1 -0
  6. package/dist/csp.d.ts +1 -0
  7. package/dist/csp.js +15 -0
  8. package/dist/csp.js.map +1 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +16 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/middlewares/express.d.ts +22 -0
  13. package/dist/middlewares/express.js +119 -0
  14. package/dist/middlewares/express.js.map +1 -0
  15. package/dist/middlewares/fastify.d.ts +18 -0
  16. package/dist/middlewares/fastify.js +129 -0
  17. package/dist/middlewares/fastify.js.map +1 -0
  18. package/dist/middlewares/hapi.d.ts +28 -0
  19. package/dist/middlewares/hapi.js +198 -0
  20. package/dist/middlewares/hapi.js.map +1 -0
  21. package/dist/middlewares/koa.d.ts +25 -0
  22. package/dist/middlewares/koa.js +139 -0
  23. package/dist/middlewares/koa.js.map +1 -0
  24. package/dist/types.d.ts +154 -0
  25. package/dist/types.js +2 -0
  26. package/dist/types.js.map +1 -0
  27. package/package.json +77 -62
  28. package/public/assets/index-CIdOb8D1.css +5 -0
  29. package/public/assets/index-Ct6Ovrls.js +17 -0
  30. package/public/index.html +11 -52
  31. package/public/site.webmanifest +8 -1
  32. package/Dockerfile +0 -23
  33. package/History.md +0 -118
  34. package/LICENSE +0 -21
  35. package/all-jobs.png +0 -0
  36. package/app.js +0 -23
  37. package/bin/agendash-standalone-fastify.js +0 -61
  38. package/bin/agendash-standalone-hapi.js +0 -60
  39. package/bin/agendash-standalone-koa.js +0 -56
  40. package/bin/agendash-standalone.js +0 -64
  41. package/create-job.png +0 -0
  42. package/entrypoint.sh +0 -5
  43. package/lib/controllers/agendash.js +0 -341
  44. package/lib/csp.js +0 -28
  45. package/lib/middlewares/README.md +0 -59
  46. package/lib/middlewares/express.js +0 -80
  47. package/lib/middlewares/fastify.js +0 -77
  48. package/lib/middlewares/hapi.js +0 -101
  49. package/lib/middlewares/koa.js +0 -77
  50. package/mobile-ui-sm.png +0 -0
  51. package/mobile-ui-xs.png +0 -0
  52. package/public/android-chrome-192x192.png +0 -0
  53. package/public/android-chrome-512x512.png +0 -0
  54. package/public/app/assets/ArgensdashV2Logo.svg +0 -18
  55. package/public/app/css/styles.css +0 -233
  56. package/public/app/js/confirmDelete.js +0 -40
  57. package/public/app/js/confirmDeleteMulti.js +0 -45
  58. package/public/app/js/confirmRequeue.js +0 -40
  59. package/public/app/js/confirmRequeueMulti.js +0 -45
  60. package/public/app/js/confirms.js +0 -8
  61. package/public/app/js/jobdetail.js +0 -48
  62. package/public/app/js/joblist.js +0 -248
  63. package/public/app/js/main.js +0 -283
  64. package/public/app/js/newJob.js +0 -89
  65. package/public/app/js/sidebar.js +0 -121
  66. package/public/app/js/topbar.js +0 -95
  67. package/public/apple-touch-icon.png +0 -0
  68. package/public/favicon-16x16.png +0 -0
  69. package/public/favicon-32x32.png +0 -0
  70. package/public/favicon.ico +0 -0
  71. package/search.png +0 -0
package/LICENSE.md ADDED
@@ -0,0 +1,25 @@
1
+ ## License
2
+ (The MIT License)
3
+
4
+ Copyright (c) 2013 Ryan Schmukler <ryan@slingingcode.com>
5
+
6
+ Copyright (c) 2022-2026 Simon Tretter <s.tretter@gmail.com>
7
+
8
+ Contributors: Mikael Korpela, Alexis Tyler, Vasyl Boroviak, Haris Sulaiman, Loris Guignard
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
11
+ this software and associated documentation files (the 'Software'), to deal in
12
+ the Software without restriction, including without limitation the rights to
13
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
14
+ the Software, and to permit persons to whom the Software is furnished to do so,
15
+ subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
23
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,253 +1,162 @@
1
1
  # Agendash
2
2
 
3
- A Dashboard for [Agenda](https://github.com/agenda/agenda).
3
+ A modern dashboard for [Agenda](https://github.com/agenda/agenda) job scheduler.
4
4
 
5
- ---
5
+ ![Agendash Screenshot](https://raw.githubusercontent.com/agenda/agenda/main/packages/agendash/agendash.png)
6
6
 
7
- ### Features
7
+ ![Agendash Status View](https://raw.githubusercontent.com/agenda/agenda/main/packages/agendash/agendash-status.png)
8
8
 
9
- - Job status auto-refreshes: 60-second polling by default.
10
- - Schedule a new job from the UI.
11
- - Dive in to see more details about the job, like the json data.
12
- - Requeue a job. Clone the data and run immediately.
13
- - Delete jobs. Useful for cleaning up old completed jobs.
14
- - Search jobs by name and metadata. Supports querying by Mongo Object Id.
15
- - Pagination
16
- - Responsive UI
9
+ ## Installation
17
10
 
18
- ---
19
-
20
- ### Screenshots
21
-
22
- #### Dashboard
23
-
24
- ![Auto-refresh list of jobs](all-jobs.png)
25
-
26
- ---
27
-
28
- #### Create jobs
29
-
30
- ![See job details, requeue or delete jobs](create-job.png)
31
-
32
- ---
33
-
34
- #### Search by name, metadata, job status
35
-
36
- ![Search for a job by name or metadata ](search.png)
37
-
38
- ---
39
-
40
- #### Responsive UI
41
-
42
- ![Mobile UI small devices](mobile-ui-sm.png)
43
-
44
- ![Mobile UI extra small devices](mobile-ui-xs.png)
45
-
46
- ---
47
-
48
- # Troubleshooting
49
-
50
- ### Index for sorting
51
-
52
- It may be required to create the following index for faster sorting (see [#24](https://github.com/agenda/agendash/issues/24))
53
-
54
- ```
55
- db.agendaJobs.ensureIndex({
56
- "nextRunAt" : -1,
57
- "lastRunAt" : -1,
58
- "lastFinishedAt" : -1
59
- }, "agendash")
60
- ```
61
-
62
- ---
63
-
64
- # Roadmap
65
-
66
- - [ ] Get more test coverage
67
- - [ ] Add middlewares for fastify, and other express-like libraries
68
- - [ ] You decide! Submit a feature request
69
-
70
- ### Install
71
-
72
- ```
73
- npm install --save agendash
11
+ ```bash
12
+ npm install agendash agenda @agendajs/mongo-backend
74
13
  ```
75
14
 
76
- _Note_: `Agendash` requires mongodb version >2.6.0 to perform the needed aggregate queries. This is your mongo database version, not your node package version! To check your database version, connect to mongo and run `db.version()`.
77
-
78
- ### Middleware usage
79
-
80
- #### Express
15
+ ## Quick Start
81
16
 
82
- Agendash provides Express middleware you can use at a specified path, for example this will
83
- make Agendash available on your site at the `/dash` path. Note: Do not try to mount Agendash
84
- at the root level like `app.use('/', Agendash(agenda))`.
17
+ ### Express
85
18
 
86
- ```js
87
- var express = require("express");
88
- var app = express();
19
+ ```typescript
20
+ import express from 'express';
21
+ import { Agenda } from 'agenda';
22
+ import { MongoBackend } from '@agendajs/mongo-backend';
23
+ import { expressMiddleware } from 'agendash';
89
24
 
90
- // ... your other express middleware like body-parser
91
-
92
- var Agenda = require("agenda");
93
- var Agendash = require("agendash");
25
+ const app = express();
26
+ const agenda = new Agenda({
27
+ backend: new MongoBackend({ address: 'mongodb://localhost:27017/agenda' })
28
+ });
94
29
 
95
- var agenda = new Agenda({ db: { address: "mongodb://127.0.0.1/agendaDb" } });
96
- // or provide your own mongo client:
97
- // var agenda = new Agenda({mongo: myMongoClient})
30
+ // Mount agendash at /dash
31
+ app.use('/dash', expressMiddleware(agenda));
98
32
 
99
- app.use("/dash", Agendash(agenda));
33
+ app.listen(3000, () => {
34
+ console.log('Dashboard: http://localhost:3000/dash');
35
+ });
36
+ ```
100
37
 
101
- // ... your other routes
38
+ ### Fastify
102
39
 
103
- // ... start your server
104
- ```
40
+ ```typescript
41
+ import Fastify from 'fastify';
42
+ import { Agenda } from 'agenda';
43
+ import { MongoBackend } from '@agendajs/mongo-backend';
44
+ import { fastifyPlugin } from 'agendash';
105
45
 
106
- By mounting Agendash as middleware on a specific path, you may provide your
107
- own authentication for that path. For example if you have an authenticated
108
- session using passport, you can protect the dashboard path like this:
109
-
110
- ```js
111
- app.use(
112
- "/dash",
113
- function (req, res, next) {
114
- if (!req.user || !req.user.is_admin) {
115
- res.send(401);
116
- } else {
117
- next();
118
- }
119
- },
120
- Agendash(agenda)
121
- );
122
- ```
46
+ const fastify = Fastify();
47
+ const agenda = new Agenda({
48
+ backend: new MongoBackend({ address: 'mongodb://localhost:27017/agenda' })
49
+ });
123
50
 
124
- Other middlewares will come soon in the folder `/lib/middlewares/`.
125
- You'll just have to update the last line to require the middleware you need:
51
+ // Register agendash at /dash
52
+ fastify.register(fastifyPlugin(agenda), { prefix: '/dash' });
126
53
 
127
- ```js
128
- app.use(
129
- "/agendash",
130
- Agendash(agenda, {
131
- middleware: "connect",
132
- })
133
- );
54
+ fastify.listen({ port: 3000 }, () => {
55
+ console.log('Dashboard: http://localhost:3000/dash');
56
+ });
134
57
  ```
135
58
 
136
- Note that if you use a CSRF protection middleware like [`csurf`](https://www.npmjs.com/package/csurf), you might need to [configure it off](https://github.com/agenda/agendash/issues/23#issuecomment-270917949) for Agendash-routes.
59
+ ### Koa
137
60
 
138
- #### Hapi
61
+ ```typescript
62
+ import Koa from 'koa';
63
+ import Router from 'koa-router';
64
+ import { Agenda } from 'agenda';
65
+ import { MongoBackend } from '@agendajs/mongo-backend';
66
+ import { koaMiddleware } from 'agendash';
139
67
 
140
- A minimum Node.js version 12 is required for `@hapi/hapi` dependency.
141
-
142
- ```shell
143
- npm i @hapi/inert @hapi/hapi
144
- ```
68
+ const app = new Koa();
69
+ const agenda = new Agenda({
70
+ backend: new MongoBackend({ address: 'mongodb://localhost:27017/agenda' })
71
+ });
145
72
 
146
- ```js
147
- const agenda = new Agenda().database(
148
- "mongodb://127.0.0.1/agendaDb",
149
- "agendaJobs"
150
- );
73
+ // Mount agendash at /dash
74
+ const { router, middleware } = koaMiddleware(agenda, '/dash');
75
+ app.use(middleware);
76
+ app.use(router.routes());
77
+ app.use(router.allowedMethods());
151
78
 
152
- const server = require("@hapi/hapi").server({
153
- port: 3002,
154
- host: "localhost",
79
+ app.listen(3000, () => {
80
+ console.log('Dashboard: http://localhost:3000/dash');
155
81
  });
156
- await server.register(require("@hapi/inert"));
157
- await server.register(
158
- Agendash(agenda, {
159
- middleware: "hapi",
160
- })
161
- );
162
-
163
- await server.start();
164
82
  ```
165
83
 
166
- Then browse to `http://localhost:3002/`.
84
+ ### Hapi
167
85
 
168
- #### Koa
86
+ ```typescript
87
+ import Hapi from '@hapi/hapi';
88
+ import { Agenda } from 'agenda';
89
+ import { MongoBackend } from '@agendajs/mongo-backend';
90
+ import { hapiPlugin } from 'agendash';
169
91
 
170
- ```shell
171
- npm i koa koa-bodyparser koa-router koa-static
172
- ```
92
+ const agenda = new Agenda({
93
+ backend: new MongoBackend({ address: 'mongodb://localhost:27017/agenda' })
94
+ });
173
95
 
174
- ```js
175
- const agenda = new Agenda().database(
176
- "mongodb://127.0.0.1/agendaDb",
177
- "agendaJobs"
178
- );
96
+ const server = Hapi.server({ port: 3000 });
179
97
 
180
- const Koa = require("koa");
181
- const app = new Koa();
182
- const middlewares = Agendash(agenda, {
183
- middleware: "koa",
98
+ await server.register({
99
+ plugin: hapiPlugin(agenda),
100
+ options: { basePath: '/dash' }
184
101
  });
185
- for (const middleware of middlewares) {
186
- app.use(middleware);
187
- }
188
102
 
189
- await app.listen(3002);
103
+ await server.start();
104
+ console.log('Dashboard: http://localhost:3000/dash');
190
105
  ```
191
106
 
192
- Then browse to `http://localhost:3002/`.
107
+ ## Security
193
108
 
194
- #### Fastify
109
+ **Important:** The Agendash dashboard provides full access to view, create, requeue, and delete jobs. You should **always protect it with authentication** before deploying to production.
195
110
 
196
- ```shell
197
- npm i fastify
198
- ```
111
+ Example with basic auth (Express):
199
112
 
200
- ```js
201
- const agenda = new Agenda().database(
202
- "mongodb://127.0.0.1/agendaDb",
203
- "agendaJobs"
204
- );
113
+ ```typescript
114
+ import basicAuth from 'express-basic-auth';
205
115
 
206
- const Fastify = require("fastify");
207
- const fastify = new Fastify();
116
+ // Protect the dashboard with basic auth
117
+ app.use('/dash', basicAuth({
118
+ users: { 'admin': 'secure-password' },
119
+ challenge: true
120
+ }));
208
121
 
209
- fastify.register(
210
- Agendash(
211
- agenda,
212
- { middleware: "fastify" }
213
- );
214
- );
215
-
216
- await fastify.listen(3002);
122
+ // Then mount agendash
123
+ app.use('/dash', expressMiddleware(agenda));
217
124
  ```
218
125
 
219
- Then browse to `http://localhost:3002/`.
220
-
221
- ### Standalone usage
126
+ For production environments, consider using:
127
+ - Session-based authentication with your existing auth system
128
+ - OAuth/SSO integration
129
+ - IP-based access control (e.g., only accessible from internal network)
130
+ - A reverse proxy with authentication (e.g., nginx with auth_basic)
222
131
 
223
- Agendash comes with a standalone Express app which you can use like this:
132
+ **Never expose the dashboard to the public internet without authentication.**
224
133
 
225
- ```bash
226
- ./node_modules/.bin/agendash --db=mongodb://localhost/agendaDb --collection=agendaCollection --port=3002
227
- ```
134
+ ## Features
228
135
 
229
- or like this, for default collection `agendaJobs` and default port `3000`:
136
+ - **Job Overview**: View all jobs organized by name with status counts
137
+ - **Job States**: See jobs by state (scheduled, queued, running, completed, failed, repeating)
138
+ - **Agenda Status**: Live view of running/queued/locked jobs and configuration
139
+ - **Filtering**: Filter jobs by name, state, or search within job data
140
+ - **Job Management**: Create, requeue, and delete jobs
141
+ - **Bulk Operations**: Multi-select jobs for bulk requeue or delete
142
+ - **Job Details**: View job data, timestamps, and failure information
143
+ - **Auto-refresh**: Dashboard refreshes automatically with countdown indicator
144
+ - **Mobile Responsive**: Works on desktop and mobile devices
230
145
 
231
- ```bash
232
- ./node_modules/.bin/agendash --db=mongodb://localhost/agendaDb
233
- ```
146
+ ## Development
234
147
 
235
- If you are using npm >= 5.2, then you can use [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b):
148
+ To run agendash in development mode with hot reloading:
236
149
 
237
150
  ```bash
238
- npx agendash --db=mongodb://localhost/agendaDb --collection=agendaCollection --port=3002
151
+ # From the agendash package directory
152
+ pnpm dev
239
153
  ```
240
154
 
241
- Then browse to `http://localhost:3002/`.
242
-
243
- ### Docker usage
155
+ This starts a development server with:
156
+ - Vite dev server for frontend hot reloading
157
+ - Express API server
158
+ - In-memory MongoDB (no external database required)
244
159
 
245
- Agendash can also be run within a Docker container like this:
246
-
247
- ```bash
248
- docker run -p 3000:3000 \
249
- --env MONGODB_URI=mongo://myUser:myPass@myHost/myDb \
250
- --env COLLECTION=myAgendaCollection agenda/agendash
251
- ```
160
+ ## License
252
161
 
253
- Then browse to `http://localhost:3000/`.
162
+ MIT
@@ -0,0 +1,50 @@
1
+ import type { Agenda, AgendaStatus } from 'agenda';
2
+ import type { AgendashController as IAgendashController, ApiQueryParams, ApiResponse, CreateJobRequest, CreateJobResponse, DeleteResponse, RequeueResponse, PauseResponse, ResumeResponse } from './types.js';
3
+ /**
4
+ * Agendash Controller - Core logic for dashboard operations
5
+ *
6
+ * Uses the database-agnostic Agenda API (v6) for all operations:
7
+ * - agenda.queryJobs() for filtering, pagination, state computation
8
+ * - agenda.getJobsOverview() for statistics
9
+ * - agenda.cancel() for deletion
10
+ */
11
+ export declare class AgendashController implements IAgendashController {
12
+ private agenda;
13
+ constructor(agenda: Agenda);
14
+ /**
15
+ * Transform a job from the new API format to the frontend format
16
+ */
17
+ private transformJob;
18
+ /**
19
+ * Transform overview from new API format to frontend format
20
+ */
21
+ private transformOverview;
22
+ /**
23
+ * Get jobs with overview and filtering
24
+ */
25
+ getJobs(params: ApiQueryParams): Promise<ApiResponse>;
26
+ /**
27
+ * Requeue jobs by creating new instances
28
+ */
29
+ requeueJobs(ids: string[]): Promise<RequeueResponse>;
30
+ /**
31
+ * Delete jobs by ID
32
+ */
33
+ deleteJobs(ids: string[]): Promise<DeleteResponse>;
34
+ /**
35
+ * Create a new job
36
+ */
37
+ createJob(options: CreateJobRequest): Promise<CreateJobResponse>;
38
+ /**
39
+ * Get running stats from the Agenda processor
40
+ */
41
+ getStats(fullDetails?: boolean): Promise<AgendaStatus>;
42
+ /**
43
+ * Pause jobs by ID (disables them so they won't run)
44
+ */
45
+ pauseJobs(ids: string[]): Promise<PauseResponse>;
46
+ /**
47
+ * Resume jobs by ID (re-enables them so they can run)
48
+ */
49
+ resumeJobs(ids: string[]): Promise<ResumeResponse>;
50
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Agendash Controller - Core logic for dashboard operations
3
+ *
4
+ * Uses the database-agnostic Agenda API (v6) for all operations:
5
+ * - agenda.queryJobs() for filtering, pagination, state computation
6
+ * - agenda.getJobsOverview() for statistics
7
+ * - agenda.cancel() for deletion
8
+ */
9
+ export class AgendashController {
10
+ agenda;
11
+ constructor(agenda) {
12
+ this.agenda = agenda;
13
+ }
14
+ /**
15
+ * Transform a job from the new API format to the frontend format
16
+ */
17
+ transformJob(job) {
18
+ return {
19
+ job: {
20
+ _id: String(job._id),
21
+ name: job.name,
22
+ data: job.data,
23
+ priority: job.priority,
24
+ nextRunAt: job.nextRunAt,
25
+ lastRunAt: job.lastRunAt,
26
+ lastFinishedAt: job.lastFinishedAt,
27
+ lockedAt: job.lockedAt,
28
+ failedAt: job.failedAt,
29
+ failCount: job.failCount,
30
+ failReason: job.failReason,
31
+ repeatInterval: job.repeatInterval,
32
+ repeatTimezone: job.repeatTimezone,
33
+ disabled: job.disabled
34
+ },
35
+ running: job.state === 'running',
36
+ scheduled: job.state === 'scheduled',
37
+ queued: job.state === 'queued',
38
+ completed: job.state === 'completed',
39
+ failed: job.state === 'failed',
40
+ repeating: job.state === 'repeating',
41
+ paused: job.disabled === true
42
+ };
43
+ }
44
+ /**
45
+ * Transform overview from new API format to frontend format
46
+ */
47
+ transformOverview(overviews) {
48
+ // Calculate totals for "All Jobs" entry
49
+ const totals = overviews.reduce((acc, o) => ({
50
+ total: acc.total + o.total,
51
+ running: acc.running + o.running,
52
+ scheduled: acc.scheduled + o.scheduled,
53
+ queued: acc.queued + o.queued,
54
+ completed: acc.completed + o.completed,
55
+ failed: acc.failed + o.failed,
56
+ repeating: acc.repeating + o.repeating,
57
+ paused: acc.paused + o.paused
58
+ }), { total: 0, running: 0, scheduled: 0, queued: 0, completed: 0, failed: 0, repeating: 0, paused: 0 });
59
+ const allJobsEntry = {
60
+ displayName: 'All Jobs',
61
+ ...totals
62
+ };
63
+ const jobOverviews = overviews.map((o) => ({
64
+ displayName: o.name,
65
+ total: o.total,
66
+ running: o.running,
67
+ scheduled: o.scheduled,
68
+ queued: o.queued,
69
+ completed: o.completed,
70
+ failed: o.failed,
71
+ repeating: o.repeating,
72
+ paused: o.paused
73
+ }));
74
+ return [allJobsEntry, ...jobOverviews];
75
+ }
76
+ /**
77
+ * Get jobs with overview and filtering
78
+ */
79
+ async getJobs(params) {
80
+ const { name, state, search, skip = 0, limit = 50 } = params;
81
+ const [overview, result] = await Promise.all([
82
+ this.agenda.getJobsOverview(),
83
+ this.agenda.queryJobs({
84
+ name: name || undefined,
85
+ state: state,
86
+ search: search || undefined,
87
+ skip,
88
+ limit,
89
+ sort: { nextRunAt: 'desc' }
90
+ })
91
+ ]);
92
+ const transformedJobs = result.jobs.map((job) => this.transformJob(job));
93
+ const transformedOverview = this.transformOverview(overview);
94
+ const totalPages = Math.ceil(result.total / limit) || 1;
95
+ return {
96
+ overview: transformedOverview,
97
+ jobs: transformedJobs,
98
+ total: result.total,
99
+ totalPages
100
+ };
101
+ }
102
+ /**
103
+ * Requeue jobs by creating new instances
104
+ */
105
+ async requeueJobs(ids) {
106
+ if (!ids || ids.length === 0) {
107
+ return { requeuedCount: 0 };
108
+ }
109
+ const { jobs } = await this.agenda.queryJobs({ ids });
110
+ let requeuedCount = 0;
111
+ for (const job of jobs) {
112
+ await this.agenda.now(job.name, job.data);
113
+ requeuedCount++;
114
+ }
115
+ return { requeuedCount };
116
+ }
117
+ /**
118
+ * Delete jobs by ID
119
+ */
120
+ async deleteJobs(ids) {
121
+ if (!ids || ids.length === 0) {
122
+ return { deleted: false, deletedCount: 0 };
123
+ }
124
+ const deletedCount = await this.agenda.cancel({ ids });
125
+ return {
126
+ deleted: deletedCount > 0,
127
+ deletedCount
128
+ };
129
+ }
130
+ /**
131
+ * Create a new job
132
+ */
133
+ async createJob(options) {
134
+ const { jobName, jobSchedule, jobRepeatEvery, jobData } = options;
135
+ if (!jobName) {
136
+ throw new Error('jobName is required');
137
+ }
138
+ if (jobRepeatEvery) {
139
+ await this.agenda.every(jobRepeatEvery, jobName, jobData);
140
+ }
141
+ else if (jobSchedule) {
142
+ await this.agenda.schedule(jobSchedule, jobName, jobData);
143
+ }
144
+ else {
145
+ await this.agenda.now(jobName, jobData);
146
+ }
147
+ return { created: true };
148
+ }
149
+ /**
150
+ * Get running stats from the Agenda processor
151
+ */
152
+ async getStats(fullDetails = false) {
153
+ return this.agenda.getRunningStats(fullDetails);
154
+ }
155
+ /**
156
+ * Pause jobs by ID (disables them so they won't run)
157
+ */
158
+ async pauseJobs(ids) {
159
+ if (!ids || ids.length === 0) {
160
+ return { pausedCount: 0 };
161
+ }
162
+ const pausedCount = await this.agenda.disable({ ids });
163
+ return { pausedCount };
164
+ }
165
+ /**
166
+ * Resume jobs by ID (re-enables them so they can run)
167
+ */
168
+ async resumeJobs(ids) {
169
+ if (!ids || ids.length === 0) {
170
+ return { resumedCount: 0 };
171
+ }
172
+ const resumedCount = await this.agenda.enable({ ids });
173
+ return { resumedCount };
174
+ }
175
+ }
176
+ //# sourceMappingURL=AgendashController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgendashController.js","sourceRoot":"","sources":["../src/AgendashController.ts"],"names":[],"mappings":"AAeA;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IACV;IAApB,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC;;OAEG;IACK,YAAY,CAAC,GAAiB;QACrC,OAAO;YACN,GAAG,EAAE;gBACJ,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,cAAc,EAAE,GAAG,CAAC,cAAc;gBAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,cAAc,EAAE,GAAG,CAAC,cAAc;gBAClC,cAAc,EAAE,GAAG,CAAC,cAAc;gBAClC,QAAQ,EAAE,GAAG,CAAC,QAAQ;aACtB;YACD,OAAO,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS;YAChC,SAAS,EAAE,GAAG,CAAC,KAAK,KAAK,WAAW;YACpC,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,QAAQ;YAC9B,SAAS,EAAE,GAAG,CAAC,KAAK,KAAK,WAAW;YACpC,MAAM,EAAE,GAAG,CAAC,KAAK,KAAK,QAAQ;YAC9B,SAAS,EAAE,GAAG,CAAC,KAAK,KAAK,WAAW;YACpC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,IAAI;SAC7B,CAAC;IACH,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,SAAyB;QAClD,wCAAwC;QACxC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACZ,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;YAC1B,OAAO,EAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO;YAChC,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;YACtC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;YAC7B,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;YACtC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;YAC7B,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;YACtC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;SAC7B,CAAC,EACF,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CACnG,CAAC;QAEF,MAAM,YAAY,GAAqB;YACtC,WAAW,EAAE,UAAU;YACvB,GAAG,MAAM;SACT,CAAC;QAEF,MAAM,YAAY,GAAuB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9D,WAAW,EAAE,CAAC,CAAC,IAAI;YACnB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM;SAChB,CAAC,CAAC,CAAC;QAEJ,OAAO,CAAC,YAAY,EAAE,GAAG,YAAY,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAsB;QACnC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC;QAE7D,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;gBACrB,IAAI,EAAE,IAAI,IAAI,SAAS;gBACvB,KAAK,EAAE,KAA6B;gBACpC,MAAM,EAAE,MAAM,IAAI,SAAS;gBAC3B,IAAI;gBACJ,KAAK;gBACL,IAAI,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;aAC3B,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE,MAAM,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAExD,OAAO;YACN,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,UAAU;SACV,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,GAAa;QAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;QAC7B,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACtD,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1C,aAAa,EAAE,CAAC;QACjB,CAAC;QAED,OAAO,EAAE,aAAa,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,GAAa;QAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC5C,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO;YACN,OAAO,EAAE,YAAY,GAAG,CAAC;YACzB,YAAY;SACZ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,OAAyB;QACxC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAElE,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;aAAM,IAAI,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,WAAW,GAAG,KAAK;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,GAAa;QAC5B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO,EAAE,WAAW,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,GAAa;QAC7B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;QAC5B,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,OAAO,EAAE,YAAY,EAAE,CAAC;IACzB,CAAC;CACD"}
package/dist/csp.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const cspHeader: string;
package/dist/csp.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Content Security Policy configuration for Agendash
3
+ * Since we now bundle all frontend assets with Vite, we only need 'self'
4
+ */
5
+ const CSP = {
6
+ 'default-src': ["'self'"],
7
+ 'script-src': ["'self'"],
8
+ 'style-src': ["'self'", "'unsafe-inline'"],
9
+ 'font-src': ["'self'"],
10
+ 'img-src': ["'self'", 'data:']
11
+ };
12
+ export const cspHeader = Object.entries(CSP)
13
+ .map(([type, values]) => `${type} ${values.join(' ')}`)
14
+ .join('; ');
15
+ //# sourceMappingURL=csp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csp.js","sourceRoot":"","sources":["../src/csp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,GAAG,GAA6B;IACrC,aAAa,EAAE,CAAC,QAAQ,CAAC;IACzB,YAAY,EAAE,CAAC,QAAQ,CAAC;IACxB,WAAW,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IAC1C,UAAU,EAAE,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;KAC1C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;KACtD,IAAI,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Agendash - Dashboard for Agenda job scheduler
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { AgendashController } from './AgendashController.js';
7
+ export * from './types.js';
8
+ export { cspHeader } from './csp.js';
9
+ export { createExpressMiddleware } from './middlewares/express.js';
10
+ export { createKoaMiddleware, createKoaMiddlewareAsync } from './middlewares/koa.js';
11
+ export { createFastifyPlugin } from './middlewares/fastify.js';
12
+ export { createHapiPlugin } from './middlewares/hapi.js';