agendash 3.1.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 (70) 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/LICENSE +0 -21
  34. package/all-jobs.png +0 -0
  35. package/app.js +0 -23
  36. package/bin/agendash-standalone-fastify.js +0 -61
  37. package/bin/agendash-standalone-hapi.js +0 -60
  38. package/bin/agendash-standalone-koa.js +0 -56
  39. package/bin/agendash-standalone.js +0 -64
  40. package/create-job.png +0 -0
  41. package/entrypoint.sh +0 -5
  42. package/lib/controllers/agendash.js +0 -340
  43. package/lib/csp.js +0 -28
  44. package/lib/middlewares/README.md +0 -59
  45. package/lib/middlewares/express.js +0 -80
  46. package/lib/middlewares/fastify.js +0 -77
  47. package/lib/middlewares/hapi.js +0 -101
  48. package/lib/middlewares/koa.js +0 -77
  49. package/mobile-ui-sm.png +0 -0
  50. package/mobile-ui-xs.png +0 -0
  51. package/public/android-chrome-192x192.png +0 -0
  52. package/public/android-chrome-512x512.png +0 -0
  53. package/public/app/assets/ArgensdashV2Logo.svg +0 -18
  54. package/public/app/css/styles.css +0 -221
  55. package/public/app/js/confirmDelete.js +0 -40
  56. package/public/app/js/confirmDeleteMulti.js +0 -45
  57. package/public/app/js/confirmRequeue.js +0 -40
  58. package/public/app/js/confirmRequeueMulti.js +0 -45
  59. package/public/app/js/confirms.js +0 -8
  60. package/public/app/js/jobdetail.js +0 -48
  61. package/public/app/js/joblist.js +0 -239
  62. package/public/app/js/main.js +0 -275
  63. package/public/app/js/newJob.js +0 -89
  64. package/public/app/js/sidebar.js +0 -121
  65. package/public/app/js/topbar.js +0 -95
  66. package/public/apple-touch-icon.png +0 -0
  67. package/public/favicon-16x16.png +0 -0
  68. package/public/favicon-32x32.png +0 -0
  69. package/public/favicon.ico +0 -0
  70. package/search.png +0 -0
@@ -1,61 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- const Agenda = require("agenda");
4
- const agendash = require("../app");
5
- const Fastify = require("fastify");
6
- const program = require("commander");
7
-
8
- program
9
- .option(
10
- "-d, --db <db>",
11
- "[required] Mongo connection string, same as Agenda connection string"
12
- )
13
- .option(
14
- "-c, --collection <collection>",
15
- "[optional] Mongo collection, same as Agenda collection name, default agendaJobs",
16
- "agendaJobs"
17
- )
18
- .option(
19
- "-p, --port <port>",
20
- "[optional] Server port, default 3000",
21
- (n, d) => Number(n) || d,
22
- 3000
23
- )
24
- .option(
25
- "-t, --title <title>",
26
- "[optional] Page title, default Agendash",
27
- "Agendash"
28
- )
29
- .option(
30
- "-p, --path <path>",
31
- "[optional] Path to bind Agendash to, default /",
32
- "/"
33
- )
34
- .parse(process.argv);
35
-
36
- if (!program.db) {
37
- console.error("--db required");
38
- process.exit(1);
39
- }
40
-
41
- if (!program.path.startsWith("/")) {
42
- console.error("--path must begin with /");
43
- process.exit(1);
44
- }
45
-
46
- const fastify = Fastify();
47
-
48
- const agenda = new Agenda().database(program.db, program.collection);
49
-
50
- fastify.register(
51
- agendash(agenda, {
52
- middleware: "fastify",
53
- title: program.title,
54
- })
55
- );
56
-
57
- fastify.listen(program.port, function () {
58
- console.log(
59
- `Agendash started http://localhost:${program.port}${program.path}`
60
- );
61
- });
@@ -1,60 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- const { Agenda } = require("agenda");
4
- const agendash = require("../app");
5
- const Hapi = require("@hapi/hapi");
6
- const program = require("commander");
7
-
8
- program
9
- .option(
10
- "-d, --db <db>",
11
- "[required] Mongo connection string, same as Agenda connection string"
12
- )
13
- .option(
14
- "-c, --collection <collection>",
15
- "[optional] Mongo collection, same as Agenda collection name, default agendaJobs",
16
- "agendaJobs"
17
- )
18
- .option(
19
- "-p, --port <port>",
20
- "[optional] Server port, default 3000",
21
- (n, d) => Number(n) || d,
22
- 3000
23
- )
24
- .option(
25
- "-t, --title <title>",
26
- "[optional] Page title, default Agendash",
27
- "Agendash"
28
- )
29
- .parse(process.argv);
30
-
31
- if (!program.db) {
32
- console.error("--db required");
33
- process.exit(1);
34
- }
35
-
36
- const init = async () => {
37
- const server = Hapi.server({
38
- port: 3002,
39
- host: "localhost",
40
- });
41
-
42
- const agenda = new Agenda().database(program.db, program.collection);
43
-
44
- await server.register(require("@hapi/inert"));
45
- await server.register(
46
- agendash(agenda, {
47
- middleware: "hapi",
48
- })
49
- );
50
-
51
- await server.start();
52
- console.log("Server running on %s", server.info.uri);
53
- };
54
-
55
- process.on("unhandledRejection", (error) => {
56
- console.log(error);
57
- process.exit(1);
58
- });
59
-
60
- init();
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- const { Agenda } = require("agenda");
4
- const agendash = require("../app");
5
- const Koa = require("koa");
6
- const program = require("commander");
7
-
8
- program
9
- .option(
10
- "-d, --db <db>",
11
- "[required] Mongo connection string, same as Agenda connection string"
12
- )
13
- .option(
14
- "-c, --collection <collection>",
15
- "[optional] Mongo collection, same as Agenda collection name, default agendaJobs",
16
- "agendaJobs"
17
- )
18
- .option(
19
- "-p, --port <port>",
20
- "[optional] Server port, default 3000",
21
- (n, d) => Number(n) || d,
22
- 3000
23
- )
24
- .option(
25
- "-t, --title <title>",
26
- "[optional] Page title, default Agendash",
27
- "Agendash"
28
- )
29
- .parse(process.argv);
30
-
31
- if (!program.db) {
32
- console.error("--db required");
33
- process.exit(1);
34
- }
35
-
36
- const init = async () => {
37
- const agenda = new Agenda().database(program.db, program.collection);
38
-
39
- const app = new Koa();
40
- const middlewares = agendash(agenda, {
41
- middleware: "koa",
42
- });
43
- for (const middleware of middlewares) {
44
- app.use(middleware);
45
- }
46
-
47
- await app.listen(program.port);
48
- console.log("Server running on port %s", program.port);
49
- };
50
-
51
- process.on("unhandledRejection", (error) => {
52
- console.log(error);
53
- process.exit(1);
54
- });
55
-
56
- init();
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- const http = require("http");
4
- const { Agenda } = require("agenda");
5
- const agendash = require("../app");
6
- const express = require("express");
7
- const program = require("commander");
8
-
9
- program
10
- .option(
11
- "-d, --db <db>",
12
- "[required] Mongo connection string, same as Agenda connection string"
13
- )
14
- .option(
15
- "-c, --collection <collection>",
16
- "[optional] Mongo collection, same as Agenda collection name, default agendaJobs",
17
- "agendaJobs"
18
- )
19
- .option(
20
- "-p, --port <port>",
21
- "[optional] Server port, default 3000",
22
- (n, d) => Number(n) || d,
23
- 3000
24
- )
25
- .option(
26
- "-t, --title <title>",
27
- "[optional] Page title, default Agendash",
28
- "Agendash"
29
- )
30
- .option(
31
- "-p, --path <path>",
32
- "[optional] Path to bind Agendash to, default /",
33
- "/"
34
- )
35
- .parse(process.argv);
36
-
37
- if (!program.db) {
38
- console.error("--db required");
39
- process.exit(1);
40
- }
41
-
42
- if (!program.path.startsWith("/")) {
43
- console.error("--path must begin with /");
44
- process.exit(1);
45
- }
46
-
47
- const app = express();
48
-
49
- const agenda = new Agenda().database(program.db, program.collection);
50
- app.use(
51
- program.path,
52
- agendash(agenda, {
53
- title: program.title,
54
- })
55
- );
56
-
57
- app.set("port", program.port);
58
-
59
- const server = http.createServer(app);
60
- server.listen(program.port, () => {
61
- console.log(
62
- `Agendash started http://localhost:${program.port}${program.path}`
63
- );
64
- });
package/create-job.png DELETED
Binary file
package/entrypoint.sh DELETED
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env sh
2
-
3
- set +e
4
-
5
- exec node ./bin/agendash-standalone.js --db=$MONGODB_URI --collection=$COLLECTION --path=$BASE_PATH
@@ -1,340 +0,0 @@
1
- "use strict";
2
- const semver = require("semver");
3
- const { ObjectId } = require("mongodb"); // We rely on the Agenda's "mongodb", thus our package.json lists "*" as required version
4
-
5
- module.exports = function (agenda, options) {
6
- options = options || {};
7
-
8
- agenda.on("ready", () => {
9
- const collection = agenda._collection.collection || agenda._collection;
10
- collection.createIndexes(
11
- [
12
- { key: { nextRunAt: -1, lastRunAt: -1, lastFinishedAt: -1 } },
13
- { key: { name: 1, nextRunAt: -1, lastRunAt: -1, lastFinishedAt: -1 } },
14
- ],
15
- (error) => {
16
- if (error) {
17
- // Ignoring for now
18
- }
19
- }
20
- );
21
-
22
- // Mongoose internals changed at some point. This will fix crash for older versions.
23
- const mdb = agenda._mdb.admin ? agenda._mdb : agenda._mdb.db;
24
-
25
- mdb.admin().serverInfo((error, serverInfo) => {
26
- if (error) {
27
- throw error;
28
- }
29
-
30
- if (!semver.satisfies(semver.coerce(serverInfo.version), ">=3.6.0")) {
31
- throw new Error("MongoDB version not supported");
32
- }
33
- });
34
- });
35
-
36
- // Options = {query = '', property = '', isObjectId = false, limit, skip}
37
- const getJobs = function (job, state, options) {
38
- const preMatch = {};
39
- if (job) {
40
- preMatch.name = job;
41
- }
42
-
43
- if (options.query && options.property) {
44
- if (options.isObjectId) {
45
- preMatch[options.property] = ObjectId(options.query);
46
- } else if (/^\d+$/.test(options.query)) {
47
- preMatch[options.property] = Number.parseInt(options.query, 10);
48
- } else {
49
- preMatch[options.property] = { $regex: options.query, $options: "i" };
50
- }
51
- }
52
-
53
- const postMatch = {};
54
- if (state) {
55
- postMatch[state] = true;
56
- }
57
-
58
- const collection = agenda._collection.collection || agenda._collection;
59
- return collection
60
- .aggregate([
61
- { $match: preMatch },
62
- {
63
- $sort: {
64
- nextRunAt: -1,
65
- lastRunAt: -1,
66
- lastFinishedAt: -1,
67
- },
68
- },
69
- {
70
- $project: {
71
- job: "$$ROOT",
72
- _id: "$$ROOT._id",
73
- running: {
74
- $and: ["$lastRunAt", { $gt: ["$lastRunAt", "$lastFinishedAt"] }],
75
- },
76
- scheduled: {
77
- $and: ["$nextRunAt", { $gte: ["$nextRunAt", new Date()] }],
78
- },
79
- queued: {
80
- $and: [
81
- "$nextRunAt",
82
- { $gte: [new Date(), "$nextRunAt"] },
83
- { $gte: ["$nextRunAt", "$lastFinishedAt"] },
84
- ],
85
- },
86
- completed: {
87
- $and: [
88
- "$lastFinishedAt",
89
- { $gt: ["$lastFinishedAt", "$failedAt"] },
90
- ],
91
- },
92
- failed: {
93
- $and: [
94
- "$lastFinishedAt",
95
- "$failedAt",
96
- { $eq: ["$lastFinishedAt", "$failedAt"] },
97
- ],
98
- },
99
- repeating: {
100
- $and: ["$repeatInterval", { $ne: ["$repeatInterval", null] }],
101
- },
102
- },
103
- },
104
- { $match: postMatch },
105
- {
106
- $facet: {
107
- pages: [
108
- { $count: "totalMatchs" },
109
- {
110
- $project: {
111
- totalPages: {
112
- $ceil: { $divide: ["$totalMatchs", options.limit] },
113
- },
114
- },
115
- },
116
- ],
117
- filtered: [{ $skip: options.skip }, { $limit: options.limit }],
118
- },
119
- },
120
- ])
121
- .toArray();
122
- };
123
-
124
- const getOverview = async () => {
125
- const collection = agenda._collection.collection || agenda._collection;
126
- const results = await collection
127
- .aggregate([
128
- {
129
- $group: {
130
- _id: "$name",
131
- displayName: { $first: "$name" },
132
- meta: {
133
- $addToSet: {
134
- type: "$type",
135
- priority: "$priority",
136
- repeatInterval: "$repeatInterval",
137
- repeatTimezone: "$repeatTimezone",
138
- },
139
- },
140
- total: { $sum: 1 },
141
- running: {
142
- $sum: {
143
- $cond: [
144
- {
145
- $and: [
146
- "$lastRunAt",
147
- { $gt: ["$lastRunAt", "$lastFinishedAt"] },
148
- ],
149
- },
150
- 1,
151
- 0,
152
- ],
153
- },
154
- },
155
- scheduled: {
156
- $sum: {
157
- $cond: [
158
- {
159
- $and: ["$nextRunAt", { $gte: ["$nextRunAt", new Date()] }],
160
- },
161
- 1,
162
- 0,
163
- ],
164
- },
165
- },
166
- queued: {
167
- $sum: {
168
- $cond: [
169
- {
170
- $and: [
171
- "$nextRunAt",
172
- { $gte: [new Date(), "$nextRunAt"] },
173
- { $gte: ["$nextRunAt", "$lastFinishedAt"] },
174
- ],
175
- },
176
- 1,
177
- 0,
178
- ],
179
- },
180
- },
181
- completed: {
182
- $sum: {
183
- $cond: [
184
- {
185
- $and: [
186
- "$lastFinishedAt",
187
- { $gt: ["$lastFinishedAt", "$failedAt"] },
188
- ],
189
- },
190
- 1,
191
- 0,
192
- ],
193
- },
194
- },
195
- failed: {
196
- $sum: {
197
- $cond: [
198
- {
199
- $and: [
200
- "$lastFinishedAt",
201
- "$failedAt",
202
- { $eq: ["$lastFinishedAt", "$failedAt"] },
203
- ],
204
- },
205
- 1,
206
- 0,
207
- ],
208
- },
209
- },
210
- repeating: {
211
- $sum: {
212
- $cond: [
213
- {
214
- $and: [
215
- "$repeatInterval",
216
- { $ne: ["$repeatInterval", null] },
217
- ],
218
- },
219
- 1,
220
- 0,
221
- ],
222
- },
223
- },
224
- },
225
- },
226
- ])
227
- .toArray();
228
- const states = {
229
- total: 0,
230
- running: 0,
231
- scheduled: 0,
232
- queued: 0,
233
- completed: 0,
234
- failed: 0,
235
- repeating: 0,
236
- };
237
- const totals = { displayName: "All Jobs", ...states };
238
-
239
- for (const job of results) {
240
- for (const state of Object.keys(states)) {
241
- totals[state] += job[state];
242
- }
243
- }
244
-
245
- results.unshift(totals);
246
- return results;
247
- };
248
-
249
- const api = async function (
250
- job,
251
- state,
252
- { query: q, property, isObjectId, skip, limit }
253
- ) {
254
- if (!agenda) {
255
- return Promise.reject(new Error("Agenda instance is not ready"));
256
- }
257
-
258
- limit = Number.parseInt(limit, 10) || 200;
259
- skip = Number.parseInt(skip, 10) || 0;
260
-
261
- const [overview, jobs] = await Promise.all([
262
- getOverview(),
263
- getJobs(job, state, { query: q, property, isObjectId, skip, limit }),
264
- ]);
265
- const apiResponse = {
266
- overview,
267
- jobs: jobs[0].filtered,
268
- totalPages: jobs[0].pages[0] ? jobs[0].pages[0].totalPages : 0,
269
- };
270
- apiResponse.title = options.title || "Agendash";
271
- apiResponse.currentRequest = {
272
- title: options.title || "Agendash",
273
- job: job || "All Jobs",
274
- state,
275
- };
276
- return apiResponse;
277
- };
278
-
279
- const requeueJobs = async (jobIds) => {
280
- if (!agenda) {
281
- return Promise.reject(new Error("Agenda instance is not ready"));
282
- }
283
-
284
- const collection = agenda._collection.collection || agenda._collection;
285
- const jobs = await collection
286
- .find({
287
- _id: { $in: jobIds.map((jobId) => ObjectId(jobId)) },
288
- })
289
- .toArray();
290
- if (jobs.length === 0) {
291
- throw new Error("Job not found");
292
- }
293
-
294
- for (const job of jobs) {
295
- const newJob = agenda.create(job.name, job.data);
296
- // eslint-disable-next-line no-await-in-loop
297
- await newJob.save();
298
- }
299
-
300
- return "Jobs create successfully";
301
- };
302
-
303
- const deleteJobs = (jobIds) => {
304
- if (!agenda) {
305
- return Promise.reject(new Error("Agenda instance is not ready"));
306
- }
307
-
308
- return agenda.cancel({
309
- _id: { $in: jobIds.map((jobId) => ObjectId(jobId)) },
310
- });
311
- };
312
-
313
- const createJob = (jobName, jobSchedule, jobRepeatEvery, jobData) => {
314
- if (!agenda) {
315
- return Promise.reject(new Error("Agenda instance is not ready"));
316
- }
317
-
318
- // @TODO: Need to validate user input.
319
- const job = agenda.create(jobName, jobData);
320
- if (jobSchedule && jobRepeatEvery) {
321
- job.repeatAt(jobSchedule);
322
- job.repeatEvery(jobRepeatEvery);
323
- } else if (jobSchedule) {
324
- job.schedule(jobSchedule);
325
- } else if (jobRepeatEvery) {
326
- job.repeatEvery(jobRepeatEvery);
327
- } else {
328
- return Promise.reject(new Error("Jobs not created"));
329
- }
330
-
331
- return job.save();
332
- };
333
-
334
- return {
335
- api,
336
- requeueJobs,
337
- deleteJobs,
338
- createJob,
339
- };
340
- };
package/lib/csp.js DELETED
@@ -1,28 +0,0 @@
1
- const CSP = {
2
- "default-src": [
3
- "'self'",
4
- ],
5
- "script-src": [
6
- "https://code.jquery.com",
7
- "https://cdn.jsdelivr.net",
8
- "https://cdnjs.cloudflare.com",
9
- "https://stackpath.bootstrapcdn.com",
10
- "'unsafe-inline'",
11
- "'unsafe-eval'",
12
- "'self'",
13
- ],
14
- "style-src": [
15
- "https://cdn.jsdelivr.net",
16
- "https://stackpath.bootstrapcdn.com",
17
- "https://fonts.googleapis.com",
18
- "https://unpkg.com",
19
- "'self'",
20
- ],
21
- "font-src": [
22
- "https://fonts.gstatic.com",
23
- ],
24
- };
25
-
26
- module.exports = Object.entries(CSP)
27
- .map(([type, values]) => `${type} ${values.join(" ")}`)
28
- .join("; ")
@@ -1,59 +0,0 @@
1
- # Middlewares
2
-
3
- ## Hapi
4
-
5
- Works with [Hapijs](https://hapijs.com/) >= v18
6
-
7
- ### usage
8
-
9
- First install the dependencies in your app:
10
-
11
- ```bash
12
- npm install @hapi/hapi @hapi/inert agenda agendash
13
- ```
14
-
15
- Then use it as follows:
16
-
17
- ```javascript
18
- 'use strict';
19
-
20
- const Hapi = require('hapi');
21
- const { Agenda } = require('agenda');
22
- const Agendash = require('agendash');
23
-
24
- var agenda = new Agenda({
25
- db: { address: '<mongoUrl>'
26
- });
27
-
28
- const server = Hapi.server({
29
- port: 3000,
30
- host: 'localhost'
31
- });
32
-
33
- const init = async () => {
34
-
35
- await server.register(
36
- require('@hapi/inert'),
37
- {
38
- plugin: Agendash(agenda, {
39
- middleware: 'hapi'
40
- // can place other options (e.g. title) here
41
- }),
42
- options: {},
43
- routes: {
44
- prefix: '/agendash'
45
- }
46
- }
47
- );
48
-
49
- await server.start();
50
- console.log(`Server running at: ${server.info.uri}`);
51
- };
52
-
53
- process.on('unhandledRejection', (err) => {
54
- console.log(err);
55
- process.exit(1);
56
- });
57
-
58
- init();
59
- ```