zyket 1.0.16 → 1.0.17

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/index.js CHANGED
@@ -4,11 +4,14 @@ const EnvManager = require("./src/utils/EnvManager");
4
4
 
5
5
  const {Route, Middleware} = require("./src/services/express");
6
6
  const { Handler, Guard } = require("./src/services/socketio");
7
+ const Schedule = require("./src/services/scheduler/Schedule");
8
+ const Event = require("./src/services/events/Event");
7
9
 
8
10
 
9
11
  module.exports = {
10
12
  Kernel, Service,
11
13
  Route, Middleware,
12
14
  Handler, Guard,
15
+ Schedule, Event,
13
16
  EnvManager
14
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zyket",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -13,6 +13,7 @@
13
13
  "license": "ISC",
14
14
  "description": "",
15
15
  "dependencies": {
16
+ "bullmq": "^5.61.0",
16
17
  "colors": "^1.4.0",
17
18
  "cors": "^2.8.5",
18
19
  "dotenv": "^16.4.7",
@@ -20,6 +21,7 @@
20
21
  "fast-glob": "^3.3.3",
21
22
  "mariadb": "^3.4.0",
22
23
  "minio": "^8.0.5",
24
+ "node-cron": "^4.2.1",
23
25
  "node-dependency-injection": "^3.2.2",
24
26
  "prompts": "^2.4.2",
25
27
  "redis": "^4.7.0",
@@ -0,0 +1,8 @@
1
+ module.exports = class Worker {
2
+ name;
3
+ queueName = null;
4
+
5
+ constructor(name) {
6
+ this.name = name;
7
+ }
8
+ }
@@ -0,0 +1,75 @@
1
+ const Service = require("../Service");
2
+ const { Queue, QueueEvents, Worker: BullWorker } = require("bullmq");
3
+ const Worker = require("./Worker");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const fg = require('fast-glob');
7
+
8
+ module.exports = class BullMQ extends Service {
9
+ #container
10
+ queues = {};
11
+ queuesEvents = {};
12
+
13
+ constructor(container) {
14
+ super("queues");
15
+ this.#container = container;
16
+ }
17
+
18
+ async boot() {
19
+ const queusConfig = this.#getActivatedQueues();
20
+
21
+ for (const queueName of queusConfig) {
22
+ this.queues[queueName] = new Queue(queueName, this.#connection());
23
+ this.queuesEvents[queueName] = new QueueEvents(queueName, this.#connection());
24
+ await this.#container.loggfer.info(`Queue ${queueName} initialized`);
25
+ }
26
+
27
+ const workers = await this.#loadWorkersFromFolder(path.join(process.cwd(), "src", "workers"));
28
+
29
+ for (const wkr of workers) {
30
+ if(!wkr.queueName) {
31
+ this.#container.get('logger').warn(`Worker ${wkr.name} has no queueName defined, skipping...`);
32
+ continue;
33
+ }
34
+ if (!this.queues[wkr.queueName]) {
35
+ this.#container.get('logger').warn(`Queue ${wkr.queueName} not found for worker ${wkr.name}, skipping...`);
36
+ continue;
37
+ }
38
+ new BullWorker(
39
+ wkr.queueName,
40
+ async (job) => wkr.handle({ container: this.#container, job }),
41
+ this.#connection()
42
+ );
43
+ this.#container.get('logger').info(`Worker ${wkr.name} for queue ${wkr.queueName} initialized`);
44
+ }
45
+ }
46
+
47
+ async #loadWorkersFromFolder(workersFolder) {
48
+ this.#createWorkersFolder(workersFolder);
49
+ const workers = (await fg('**/*.js', { cwd: workersFolder })).map((wkr) => {
50
+ const worker = require(path.join(workersFolder, wkr));
51
+ if(!(worker.prototype instanceof Worker)) throw new Error(`${wkr} is not a valid handler`);
52
+ return new worker(wkr.replace('.js', ''));
53
+ });
54
+ return workers;
55
+ }
56
+
57
+ #createWorkersFolder(workersFolder, overwrite = false) {
58
+ if (fs.existsSync(workersFolder) && !overwrite) return;
59
+ this.#container.get('logger').info(`Creating workers folder at ${workersFolder}`);
60
+ fs.mkdirSync(workersFolder);
61
+ }
62
+
63
+ #getActivatedQueues() {
64
+ const list = process.env.QUEUES || "";
65
+ return list.split(",").map(q => q.trim()).filter(q => q.length);
66
+ }
67
+
68
+ #connection() {
69
+ return {
70
+ connection: {
71
+ url: process.env.REDIS_URL || "redis://localhost:6379"
72
+ }
73
+ };
74
+ }
75
+ }
@@ -0,0 +1,7 @@
1
+ module.exports = class Event {
2
+ name;
3
+
4
+ constructor(name) {
5
+ this.name = name;
6
+ }
7
+ }
@@ -0,0 +1,60 @@
1
+ const Service = require("../Service");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const fg = require('fast-glob');
5
+ const Event = require("./Event");
6
+
7
+ module.exports = class EventService extends Service {
8
+ #container
9
+ events = {};
10
+
11
+ constructor(container) {
12
+ super("events");
13
+ this.#container = container;
14
+ }
15
+
16
+
17
+ emit(eventName, payload) {
18
+ const event = this.events[eventName];
19
+ if (!event) throw new Error(`Event ${eventName} not found`);
20
+ this.#container.get('logger').debug(`Emitting event ${eventName}`);
21
+ return event.handle({ container: this.#container, payload });
22
+ }
23
+
24
+ emitAsync(eventName, payload, timeout = 30000) {
25
+ const event = this.events[eventName];
26
+ if (!event) throw new Error(`Event ${eventName} not found`);
27
+ this.#container.get('logger').debug(`Emitting event ${eventName} asynchronously`);
28
+ return Promise.race([
29
+ event.handle({ container: this.#container, payload }),
30
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`Event ${eventName} timed out after ${timeout}ms`)), timeout))
31
+ ]);
32
+ }
33
+
34
+ async boot() {
35
+ const events = await this.#loadEventsFromFolder(path.join(process.cwd(), "src", "events"));
36
+ this.#container.get('logger').info(`Loaded ${events.length} events`);
37
+ for (const evt of events) {
38
+ this.events[evt.name] = evt;
39
+ this.#container.get('logger').debug(`Event ${evt.name} initialized`);
40
+ }
41
+ }
42
+
43
+ async #loadEventsFromFolder(eventsFolder) {
44
+ this.#createEventsFolder(eventsFolder);
45
+ const events = (await fg('**/*.js', { cwd: eventsFolder })).map((evt) => {
46
+ const event = require(path.join(eventsFolder, evt));
47
+ if(!(event.prototype instanceof Event)) throw new Error(`${evt} is not a valid handler`);
48
+ return new event(evt.replace('.js', ''));
49
+ });
50
+ return events;
51
+ }
52
+
53
+ #createEventsFolder(eventsFolder, overwrite = false) {
54
+ if (fs.existsSync(eventsFolder) && !overwrite) return;
55
+ this.#container.get('logger').info(`Creating schedules folder at ${eventsFolder}`);
56
+ fs.mkdirSync(eventsFolder);
57
+ }
58
+
59
+
60
+ }
@@ -3,13 +3,27 @@ const Cache = require("./cache");
3
3
  const S3 = require("./s3");
4
4
  const { SocketIO } = require("./socketio");
5
5
  const { Express } = require("./express");
6
+ const Scheduler = require("./scheduler");
7
+ const EventService = require("./events");
8
+
9
+ const eventsActivated = process.env.DISABLE_EVENTS !== 'true';
10
+ const databaseActivated = !!process.env.DATABASE_URL;
11
+ const cacheActivated = !!process.env.CACHE_URL;
12
+ const bullmqActivated = !!process.env.CACHE_URL && process.env.DISABLE_BULLMQ !== 'true';
13
+ const s3Activated = process.env.S3_ENDPOINT && process.env.S3_ACCESS_KEY && process.env.S3_SECRET_KEY;
14
+ const schedulerActivated = process.env.DISABLE_SCHEDULER !== 'true';
15
+ const socketActivated = process.env.DISABLE_SOCKET !== 'true';
16
+ const expressActivated = process.env.DISABLE_EXPRESS !== 'true';
6
17
 
7
18
  module.exports = [
8
19
  ["logger", require("./logger"), ["@service_container", process.env.LOG_DIRECTORY || `${process.cwd()}/logs`, process.env.DEBUG === "true"]],
9
20
  ["template-manager", require("./template-manager"), []],
10
- process.env.DATABASE_URL ? ["database", Database, ["@service_container", process.env.DATABASE_URL]] : null,
11
- process.env.CACHE_URL ? ["cache", Cache, ["@service_container", process.env.CACHE_URL]] : null,
12
- (process.env.S3_ENDPOINT && process.env.S3_ACCESS_KEY && process.env.S3_SECRET_KEY) ? ["s3", S3, ["@service_container", process.env.S3_ENDPOINT, process.env.S3_PORT, process.env.S3_USE_SSL === "true", process.env.S3_ACCESS_KEY, process.env.S3_SECRET_KEY]] : null,
13
- process.env.DISABLE_SOCKET !== 'true' ? ["socketio", SocketIO, ["@service_container"]] : null,
14
- process.env.DISABLE_EXPRESS !== 'true' ? ["express", Express, ["@service_container"]] : null
21
+ eventsActivated ? ["events", EventService, ["@service_container"]] : null,
22
+ databaseActivated ? ["database", Database, ["@service_container", process.env.DATABASE_URL]] : null,
23
+ cacheActivated ? ["cache", Cache, ["@service_container", process.env.CACHE_URL]] : null,
24
+ s3Activated ? ["s3", S3, ["@service_container", process.env.S3_ENDPOINT, process.env.S3_PORT, process.env.S3_USE_SSL === "true", process.env.S3_ACCESS_KEY, process.env.S3_SECRET_KEY]] : null,
25
+ schedulerActivated ? ["scheduler", Scheduler, ["@service_container"]] : null,
26
+ bullmqActivated ? ["bullmq", require("./bullmq"), ["@service_container"]] : null,
27
+ socketActivated ? ["socketio", SocketIO, ["@service_container"]] : null,
28
+ expressActivated ? ["express", Express, ["@service_container"]] : null
15
29
  ].filter(Boolean);
@@ -0,0 +1,7 @@
1
+ module.exports = class Schedule {
2
+ name;
3
+
4
+ constructor(name) {
5
+ this.name = name;
6
+ }
7
+ }
@@ -0,0 +1,42 @@
1
+ const Service = require("../Service");
2
+ const Schedule = require("./Schedule");
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const fg = require('fast-glob');
6
+ const cron = require('node-cron');
7
+
8
+ module.exports = class Scheduler extends Service {
9
+ #container
10
+
11
+ constructor(container) {
12
+ super("scheduler");
13
+ this.#container = container;
14
+ }
15
+
16
+ async boot() {
17
+ const schedulers = await this.#loadSchedulersFromFolder(path.join(process.cwd(), "src", "schedulers"));
18
+ await this.#container.get('logger').info(`Loaded ${schedulers.length} schedulers`);
19
+ for (const schd of schedulers) {
20
+ cron.schedule(schd.time, () => schd.handle({ container: this.#container }));
21
+ this.#container.get('logger').info(`Scheduler ${schd.name}, ${schd.time} initialized`);
22
+ }
23
+ }
24
+
25
+ async #loadSchedulersFromFolder(schedulersFolder) {
26
+ this.#createSchedulersFolder(schedulersFolder);
27
+ const schedulers = (await fg('**/*.js', { cwd: schedulersFolder })).map((schd) => {
28
+ const schedule = require(path.join(schedulersFolder, schd));
29
+ if(!(schedule.prototype instanceof Schedule)) throw new Error(`${schd} is not a valid handler`);
30
+ return new schedule(schd.replace('.js', ''));
31
+ });
32
+ return schedulers;
33
+ }
34
+
35
+ #createSchedulersFolder(schedulersFolder, overwrite = false) {
36
+ if (fs.existsSync(schedulersFolder) && !overwrite) return;
37
+ this.#container.get('logger').info(`Creating schedules folder at ${schedulersFolder}`);
38
+ fs.mkdirSync(schedulersFolder);
39
+ }
40
+
41
+
42
+ }
@@ -24,7 +24,8 @@ module.exports = class EnvManager {
24
24
  S3_USE_SSL: true,
25
25
  S3_ACCESS_KEY: '',
26
26
  S3_SECRET_KEY: '',
27
- LOG_DIRECTORY: "./logs"
27
+ LOG_DIRECTORY: "./logs",
28
+ QUEUES: '',
28
29
  }
29
30
 
30
31
  return Object.entries(envsToCreate).reduce((acc, [key, value]) => {