zyket 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,139 @@
1
1
  # ZYKET - Easy Socket.io Framework
2
2
 
3
- Zyket is a framework inspired by Symfony.
3
+ Zyket is a framework inspired by Symfony that simplifies working with Socket.io by providing a structured approach.
4
+
5
+ # Getting Started
6
+
7
+ To use zyket we need to install it into our project:
8
+
9
+ ```javascript
10
+ npm i zyket
11
+ ```
12
+
13
+ Then we just need to import the Kernel and boot it:
14
+
15
+ ```javascript
16
+ const { Kernel } = require("zyket");
17
+ const kernel = new Kernel();
18
+
19
+ kernel.boot().then(() => console.log(`Kernel Booted`));
20
+ ```
21
+
22
+ After boot is done for fist time, project folders/files will be created if doesnt exists.
23
+
24
+ ## Handlers
25
+
26
+ Handlers are the way to interact with user messages on the socket:
27
+ ```javascript
28
+ const { Handler } = require("zyket");
29
+
30
+ module.exports = class MessageHandler extends Handler {
31
+ middlewares = ["default"];
32
+
33
+ async handle({ container, socket, data, io }) {
34
+ container.get("logger").info("Message handler");
35
+ }
36
+ };
37
+ ```
38
+
39
+ - middlewares: An array of middleware names that should be executed before the handler.
40
+
41
+ - handle(): The function that processes the event, receiving container, socket, and data.
42
+
43
+ ## Middlewares
44
+
45
+ Middlewares allow you to process data before it reaches the handler. They can be used for validation, authentication, logging, etc.
46
+
47
+ ```javascript
48
+ const { Middleware } = require("zyket");
49
+
50
+ module.exports = class DefaultMiddleware extends Middleware {
51
+ async handle({ container, socket, io }) {
52
+ container.get("logger").info("Default middleware");
53
+ }
54
+ };
55
+ ```
56
+
57
+ - handle(): The function that processes the event, receiving container, socket, and data.
58
+
59
+
60
+ ## Services
61
+ Services are reusable components specified in the kernel configuration. Each service must include a boot() function that is executed when the kernel starts.
62
+
63
+ ```javascript
64
+ module.exports = class LoggerService {
65
+ this.#container;
66
+
67
+ boot(container, enableLogging = true) {
68
+ this.#container = container;
69
+ console.log("LoggerService Booted");
70
+ }
71
+
72
+ info(message) {
73
+ if(!enableLogging) return;
74
+ console.log(`[INFO]: ${message}`);
75
+ }
76
+ };
77
+ ```
78
+
79
+ Then, when booting the kernel, specify the service:
80
+
81
+ ```javascript
82
+ const { Kernel } = require("zyket");
83
+ const LoggerService = require("./LoggerService");
84
+
85
+ const kernel = new Kernel({
86
+ services: [["logger", LoggerService, ['@service_container', true]],
87
+ });
88
+
89
+ kernel.boot().then(() => console.log(`Kernel Booted`));
90
+ ```
91
+
92
+ ## Default Services
93
+ Zyket includes some default services that provide essential functionality. These services can be overridden or extended if needed.
94
+
95
+ #### Cache Services
96
+ - **Name** `cache`
97
+ - **Description** Provides caching functionality using a Redis adapter.
98
+ - **Configuration** Add `CACHE_URL` in your `.env` file to activate caching.
99
+
100
+ #### Database Service
101
+ - **Name** `database`
102
+ - **Description** Manages database connections using a MariaDB/Sequelize adapter.
103
+ - **Configuration** Add `DATABASE_URL` in your `.env` file to enable the database connection.
104
+
105
+ #### S3 Service
106
+ - **Name** `s3`
107
+ - **Description** Provides S3-compatible object storage using MinIO.
108
+ - **Configuration** Add the following variables in your `.env` file to enable the service
109
+ - `S3_ENDPOINT`
110
+ - `S3_PORT`
111
+ - `S3_USE_SSL`
112
+ - `S3_ACCESS_KEY`
113
+ - `S3_SECRET_KEY`
114
+
115
+ #### Logger Service
116
+ - **Name** `logger`
117
+ - **Description** Handles logging for the application.
118
+ - **Configuration**
119
+ - Change `LOG_DIRECTORY` in `.env` file to set a custom log directory.
120
+ - Set `DEBUG` in `.env` file to enable or disable debug logging.
121
+
122
+ #### Socket.io Service
123
+ - **Name** `socketio`
124
+ - **Description** Manages the WebSocket server.
125
+ - **Configuration** Add `PORT` in your `.env` file to define the listening port for Socket.io.
126
+
127
+
128
+ ## Contributing
129
+
130
+ We welcome contributions from the community! If you'd like to improve Zyket, feel free to:
131
+
132
+ - Report issues and suggest features on GitHub Issues
133
+
134
+ - Submit pull requests with bug fixes or enhancements
135
+
136
+ - Improve the documentation
137
+
138
+ Let's build a better framework together! 🚀
139
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zyket",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -18,7 +18,7 @@ module.exports = class Database extends Service {
18
18
 
19
19
  async boot() {
20
20
  this.#createModelsFolder();
21
- this.sequelize = new Sequelize(process.env.DATABASE_URL, {
21
+ this.sequelize = new Sequelize(this.#databaseUrl, {
22
22
  dialect: process.env.DATABASE_DIALECT || 'mariadb',
23
23
  logging: (msg) => this.#container.get('logger').debug(msg),
24
24
  operatorsAliases: 0,
@@ -1,10 +1,11 @@
1
- const Database = require("./Database");
2
- const Cache = require("./Cache");
3
- const S3 = require("./S3");
1
+ const Database = require("./database");
2
+ const Cache = require("./cache");
3
+ const S3 = require("./s3");
4
4
  const { SocketIO } = require("./socketio");
5
5
 
6
6
  module.exports = [
7
7
  ["logger", require("./Logger"), ["@service_container", process.env.LOG_DIRECTORY || `${process.cwd()}/logs`, process.env.DEBUG === "true"]],
8
+ ["template-manager", require("./template-manager"), ["@service_container"]],
8
9
  process.env.DATABASE_URL ? ["database", Database, ["@service_container", process.env.DATABASE_URL]] : null,
9
10
  process.env.CACHE_URL ? ["cache", Cache, ["@service_container", process.env.CACHE_URL]] : null,
10
11
  (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,
@@ -40,9 +40,9 @@ module.exports = class SocketIO extends Service {
40
40
  this.#container.get('logger').warn(`You are using a middleware that does not exist`);
41
41
  continue;
42
42
  }
43
- middleware.handle({ container: this.#container, socket });
43
+ middleware.handle({ container: this.#container, socket, io: this.io });
44
44
  }
45
- connectionHandler.handle({ container: this.#container, socket });
45
+ connectionHandler.handle({ container: this.#container, socket, io: this.io });
46
46
  handlers.forEach((handler) => {
47
47
  const handlerMiddlewares = (handler?.middlewares || []).map(mdl => this.middlewares[mdl])
48
48
  socket.on(handler.event, async (data) => {
@@ -52,9 +52,9 @@ module.exports = class SocketIO extends Service {
52
52
  this.#container.get('logger').warn(`You are using a middleware that does not exist`);
53
53
  continue;
54
54
  }
55
- await middleware.handle({ container: this.#container, socket });
55
+ await middleware.handle({ container: this.#container, socket, io: this.io });
56
56
  }
57
- return await handler.handle({ container: this.#container, socket, data });
57
+ return await handler.handle({ container: this.#container, socket, data, io: this.io });
58
58
  });
59
59
  });
60
60
  });
@@ -65,15 +65,8 @@ module.exports = class SocketIO extends Service {
65
65
 
66
66
  async #loadConnectionHandler() {
67
67
  const connectionHandlerExists = fs.existsSync(path.join(process.cwd(), "src", "handlers", "connection.js"));
68
- /* if exists require, otherwise create a default one */
69
68
  if(!connectionHandlerExists) {
70
- fs.writeFileSync(path.join(process.cwd(), "src", "handlers", "connection.js"), `const { Handler } = require("zyket");
71
-
72
- module.exports = class ConnectionHandler extends Handler {
73
- async handle({ container, socket }) {
74
- container.get("logger").info("New connection");
75
- }
76
- };`);
69
+ this.#container.get('template-manager').installFile('default/src/handlers/connection', path.join(process.cwd(), "src", "handlers", "connection.js"));
77
70
  }
78
71
  return require(path.join(process.cwd(), "src", "handlers", "connection.js"));
79
72
  }
@@ -94,16 +87,7 @@ module.exports = class ConnectionHandler extends Handler {
94
87
  if (fs.existsSync(handlersFolder) && !overwrite) return;
95
88
  this.#container.get('logger').info(`Creating handlers folder at ${handlersFolder}`);
96
89
  fs.mkdirSync(handlersFolder);
97
- // create a default handler
98
- fs.writeFileSync(path.join(handlersFolder, "message.js"), `const { Handler } = require("zyket");
99
- module.exports = class MessageHandler extends Handler {
100
- event = "message";
101
- middlewares = ["default"];
102
-
103
- async handle({ container, socket, data }) {
104
- container.get("logger").info("Message handler");
105
- }
106
- };`);
90
+ this.#container.get('template-manager').installFile('default/src/handlers/message', path.join(handlersFolder, "message.js"));
107
91
  }
108
92
 
109
93
  async #loadMiddlewaresFromFolder(middlewaresFolder) {
@@ -123,13 +107,7 @@ module.exports = class MessageHandler extends Handler {
123
107
  if (fs.existsSync(middlewaresFolder) && !overwrite) return;
124
108
  this.#container.get('logger').info(`Creating middlewares folder at ${middlewaresFolder}`);
125
109
  fs.mkdirSync(middlewaresFolder);
126
- // create a default middleware
127
- fs.writeFileSync(path.join(middlewaresFolder, "default.js"), `const { Middleware } = require("zyket");
128
- module.exports = class DefaultMiddleware extends Middleware {
129
- async handle({ container, socket }) {
130
- container.get("logger").info("Default middleware");
131
- }
132
- };`);
110
+ this.#container.get('template-manager').installFile('default/src/middlewares/default', path.join(middlewaresFolder, "default.js"));
133
111
  }
134
112
 
135
113
  stop() {
@@ -0,0 +1,67 @@
1
+ const fg = require('fast-glob');
2
+ const Service = require('../Service');
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+
6
+ module.exports = class TemplateManager extends Service {
7
+ #container;
8
+ templates = {}
9
+
10
+ constructor(container) {
11
+ super('template-manager');
12
+ this.#container = container;
13
+ }
14
+
15
+ async boot() {
16
+ const zyketTemplates = await fg(['**/*.js'], {
17
+ cwd: path.join(__dirname, '../../templates'),
18
+ });
19
+ for (const template of zyketTemplates) {
20
+ // need to copy full file and relation with the name on templates variable
21
+ const templatePath = path.join(__dirname, '../../templates', template);
22
+ const templateContent = fs.readFileSync(templatePath, 'utf-8');
23
+ this.templates[template.replace('.js', '')] = templateContent;
24
+ }
25
+
26
+ this.#container.get('logger').info(`Loaded ${this.templates.length} templates`);
27
+ }
28
+
29
+ installFile(fileName, location) {
30
+ const template = this.templates[fileName];
31
+ if (!template) throw new Error(`Template ${fileName} not found`);
32
+ return fs.writeFileSync(location, template);
33
+ }
34
+
35
+ installTemplate(templateName) {
36
+ const template = this.getTemplates().find((t) => t === templateName);
37
+ if (!template) throw new Error(`Template ${templateName} not found`);
38
+ const files = this.getTemplate(templateName);
39
+
40
+ for (const file of files) {
41
+ const fileName = file.split('/').slice(1).join('/');
42
+ const fileLocation = path.join(process.cwd(), fileName);
43
+ if (fs.existsSync(fileLocation)) throw new Error(`File ${file} already exists`);
44
+ }
45
+
46
+ for (const file of files) {
47
+ const fileName = file.split('/').slice(1).join('/');
48
+ const template = this.templates[file];
49
+ const fileLocation = path.join(process.cwd(), fileName);
50
+ fs.writeFileSync(fileLocation, template);
51
+ }
52
+ }
53
+
54
+ getTemplates() {
55
+ const uniqueTemplates = new Set();
56
+ for (const template of Object.keys(this.templates)) {
57
+ uniqueTemplates.add(template.split('/')[0]);
58
+ }
59
+ return Array.from(uniqueTemplates);
60
+ }
61
+
62
+ getTemplate(templateName) {
63
+ const files = Object.keys(this.templates).filter((t) => t.startsWith(templateName));
64
+ if (files.length === 0) throw new Error(`Template ${templateName} not found`);
65
+ return files
66
+ }
67
+ }
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ const { Handler } = require("zyket");
2
+
3
+ module.exports = class ConnectionHandler extends Handler {
4
+ async handle({ container, socket, io }) {
5
+ container.get("logger").info("New connection");
6
+ }
7
+ };
@@ -0,0 +1,9 @@
1
+ const { Handler } = require("zyket");
2
+
3
+ module.exports = class MessageHandler extends Handler {
4
+ middlewares = ["default"];
5
+
6
+ async handle({ container, socket, data, io }) {
7
+ container.get("logger").info("Message handler");
8
+ }
9
+ };
@@ -0,0 +1,6 @@
1
+ const { Middleware } = require("zyket");
2
+ module.exports = class DefaultMiddleware extends Middleware {
3
+ async handle({ container, socket, io }) {
4
+ container.get("logger").info("Default middleware");
5
+ }
6
+ };