@gnar-engine/cli 1.0.5 → 1.0.6
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/bootstrap/deploy.localdev.yml +14 -0
- package/bootstrap/secrets.localdev.yml +7 -3
- package/bootstrap/services/notification/Dockerfile +2 -2
- package/bootstrap/services/notification/package.json +14 -32
- package/bootstrap/services/notification/src/app.js +50 -48
- package/bootstrap/services/notification/src/commands/notification.handler.js +96 -0
- package/bootstrap/services/notification/src/config.js +55 -12
- package/bootstrap/services/notification/src/controllers/http.controller.js +87 -0
- package/bootstrap/services/notification/src/controllers/message.controller.js +39 -70
- package/bootstrap/services/notification/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/notification/src/db/migrations/02-notification-service-init.js +23 -0
- package/bootstrap/services/notification/src/policies/notification.policy.js +49 -0
- package/bootstrap/services/notification/src/schema/notification.schema.js +17 -0
- package/bootstrap/services/notification/src/services/notification.service.js +32 -0
- package/bootstrap/services/portal/src/services/client.js +3 -0
- package/bootstrap/services/user/src/commands/user.handler.js +35 -18
- package/bootstrap/services/user/src/tests/commands/user.test.js +15 -6
- package/install-from-clone.sh +1 -1
- package/package.json +1 -1
- package/src/cli.js +0 -6
- package/src/config.js +8 -0
- package/src/dev/commands.js +2 -2
- package/src/dev/dev.service.js +19 -6
- package/src/helpers/helpers.js +24 -0
- package/src/profiles/command.js +41 -0
- package/src/profiles/profiles.client.js +23 -0
- package/src/scaffolder/commands.js +57 -1
- package/src/scaffolder/scaffolder.handler.js +127 -60
- package/templates/entity/src/commands/{{entityName}}.handler.js.hbs +94 -0
- package/templates/entity/src/controllers/{{entityName}}.http.controller.js.hbs +87 -0
- package/templates/entity/src/mysql.db/migrations/03-{{entityName}}-entity-init.js.hbs +23 -0
- package/templates/entity/src/policies/{{entityName}}.policy.js.hbs +49 -0
- package/templates/entity/src/schema/{{entityName}}.schema.js.hbs +17 -0
- package/templates/entity/src/services/mongodb.{{entityName}}.service.js.hbs +70 -0
- package/templates/entity/src/services/mysql.{{entityName}}.service.js.hbs +27 -0
- package/bootstrap/services/notification/Dockerfile.prod +0 -37
- package/bootstrap/services/notification/README.md +0 -3
- package/bootstrap/services/notification/src/commands/command-bus.js +0 -20
- package/bootstrap/services/notification/src/commands/handlers/control.handler.js +0 -18
- package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +0 -157
- package/bootstrap/services/notification/src/services/logger.service.js +0 -16
- package/bootstrap/services/notification/src/services/ses.service.js +0 -23
- package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +0 -136
- package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +0 -87
- package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +0 -132
- package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +0 -77
- package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
|
@@ -63,3 +63,17 @@ config:
|
|
|
63
63
|
- '4004:3000'
|
|
64
64
|
depends_on:
|
|
65
65
|
- db-mongo
|
|
66
|
+
- name: notification
|
|
67
|
+
listener_rules:
|
|
68
|
+
paths:
|
|
69
|
+
- /notification
|
|
70
|
+
min_tasks: 1
|
|
71
|
+
max_tasks: 1
|
|
72
|
+
command:
|
|
73
|
+
- npm
|
|
74
|
+
- run
|
|
75
|
+
- start:dev
|
|
76
|
+
ports:
|
|
77
|
+
- '4005:3000'
|
|
78
|
+
depends_on:
|
|
79
|
+
- db-mysql
|
|
@@ -8,8 +8,8 @@ global:
|
|
|
8
8
|
UPLOADS_URL: https://gnar-engine-test.s3.eu-west-2.amazonaws.com
|
|
9
9
|
S3_BUCKET: gnar-engine-test
|
|
10
10
|
AWS_REGION: eu-west-2
|
|
11
|
-
AWS_ACCESS_KEY_ID:
|
|
12
|
-
AWS_SECRET_ACCESS_KEY:
|
|
11
|
+
AWS_ACCESS_KEY_ID: null
|
|
12
|
+
AWS_SECRET_ACCESS_KEY: null
|
|
13
13
|
services:
|
|
14
14
|
control:
|
|
15
15
|
MYSQL_HOST: db-mysql
|
|
@@ -30,4 +30,8 @@ services:
|
|
|
30
30
|
MONGO_DATABASE: page_db
|
|
31
31
|
MONGO_USER: page_user
|
|
32
32
|
MONGO_PASSWORD: Q2atGxh21VqNIrZO
|
|
33
|
-
|
|
33
|
+
notification:
|
|
34
|
+
MYSQL_USER: notification_user
|
|
35
|
+
MYSQL_PASSWORD: hmubUB5FBVf4V7dF
|
|
36
|
+
MYSQL_DATABASE: notification_db
|
|
37
|
+
MYSQL_HOST: db-mysql
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Dockerfile for Notification Service
|
|
2
|
-
FROM node:20-alpine
|
|
2
|
+
FROM node:20-alpine
|
|
3
3
|
|
|
4
4
|
# Set the working directory
|
|
5
5
|
WORKDIR /usr/gnar_engine/app
|
|
@@ -17,7 +17,7 @@ RUN npm install -g nodemon
|
|
|
17
17
|
RUN npm install
|
|
18
18
|
|
|
19
19
|
# Expose the port the service will run on
|
|
20
|
-
EXPOSE
|
|
20
|
+
EXPOSE 3000
|
|
21
21
|
|
|
22
22
|
# Start the application
|
|
23
23
|
CMD ["nodemon", "--watch", "./gnar_engine", "./gnar_engine/app.js"]
|
|
@@ -1,34 +1,16 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"ajv-formats": "^3.0.1",
|
|
17
|
-
"dotenv": "^16.4.7",
|
|
18
|
-
"nodemailer": "^7.0.3",
|
|
19
|
-
"path": "^0.12.7",
|
|
20
|
-
"pino": "^9.6.0",
|
|
21
|
-
"pino-pretty": "^13.0.0",
|
|
22
|
-
"uuid": "^11.1.0",
|
|
23
|
-
"handlebars": "^4.7.8"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@babel/preset-env": "^7.22.20",
|
|
27
|
-
"jest": "^29.7.0",
|
|
28
|
-
"nodemon": "^3.1.9",
|
|
29
|
-
"supertest": "^6.3.3"
|
|
30
|
-
},
|
|
31
|
-
"workspaces": [
|
|
32
|
-
"./Lib/*"
|
|
33
|
-
]
|
|
2
|
+
"name": "notification-service",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Notification microservice for Gnar Engine",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node ./src/app.js",
|
|
8
|
+
"start:dev": "nodemon --watch ./src ./src/app.js",
|
|
9
|
+
"test": "jest --watchAll --verbose"
|
|
10
|
+
},
|
|
11
|
+
"author": "Gnar Software Ltd.",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@gnar-engine/core": "^1.0.1"
|
|
15
|
+
}
|
|
34
16
|
}
|
|
@@ -1,51 +1,53 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { messageAwaitResponse } from '@gnar-engine/message-client';
|
|
6
|
-
import { internalHealthCheck } from './commands/handlers/control.handler.js';
|
|
7
|
-
import { sendNotification } from './commands/handlers/notification.handler.js';
|
|
8
|
-
|
|
9
|
-
dotenv.config({ path: '.env' });
|
|
10
|
-
|
|
11
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
12
|
-
console.error('🚨 Unhandled Rejection at:', promise, '\nReason:', reason);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
process.on('uncaughtException', (err) => {
|
|
17
|
-
console.error('🚨 Uncaught Exception:', err);
|
|
18
|
-
process.exit(1);
|
|
19
|
-
});
|
|
1
|
+
import { message, http, logger, db, registerService, webSockets, test } from '@gnar-engine/core';
|
|
2
|
+
import { config } from './config.js';
|
|
3
|
+
import { messageHandlers } from './controllers/message.controller.js';
|
|
4
|
+
import { httpController as notificationPlatformHttpController } from './controllers/http.controller.js';
|
|
20
5
|
|
|
21
6
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @description Initializes and starts the Fastify server.
|
|
7
|
+
* Initialise service
|
|
24
8
|
*/
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
9
|
+
export const initService = async () => {
|
|
10
|
+
|
|
11
|
+
// Run migrations
|
|
12
|
+
if (config.db.type == 'mysql') {
|
|
13
|
+
db.migrations.runMigrations({config});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Run seeders
|
|
17
|
+
db.seeders.runSeeders({config});
|
|
18
|
+
|
|
19
|
+
// Import command handlers after the command bus is initialised
|
|
20
|
+
await import('./commands/notification.handler.js');
|
|
21
|
+
// Add more handlers as needed
|
|
22
|
+
|
|
23
|
+
// Initialise and register message handlers
|
|
24
|
+
await message.init({
|
|
25
|
+
config: config.message,
|
|
26
|
+
handlers: messageHandlers
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Initialise websocket client & server
|
|
30
|
+
await webSockets.init(config.webSockets, config.serviceName);
|
|
31
|
+
|
|
32
|
+
// Register http routes
|
|
33
|
+
await http.registerRoutes({
|
|
34
|
+
controllers: [
|
|
35
|
+
notificationPlatformHttpController,
|
|
36
|
+
]
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Start the HTTP server
|
|
40
|
+
await http.start();
|
|
41
|
+
|
|
42
|
+
// Register service with control service
|
|
43
|
+
await registerService();
|
|
44
|
+
|
|
45
|
+
logger.info('G n a r E n g i n e | Notification Service initialised successfully.');
|
|
46
|
+
|
|
47
|
+
// Tests
|
|
48
|
+
if (config.environment === 'test' && config.runTests) {
|
|
49
|
+
test.runCommandTests({config});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
initService();
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { commands, logger, error } from '@gnar-engine/core';
|
|
2
|
+
import { notification } from '../services/notification.service.js';
|
|
3
|
+
import { config } from '../config.js';
|
|
4
|
+
import { validateNotification } from '../schema/notification.schema.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get single notification
|
|
9
|
+
*/
|
|
10
|
+
commands.register('notificationService.getSingleNotification', async ({id}) => {
|
|
11
|
+
if (id) {
|
|
12
|
+
return await notification.getById({id: id});
|
|
13
|
+
} else {
|
|
14
|
+
throw new error.badRequest('Notification email or id required');
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get many notifications
|
|
20
|
+
*/
|
|
21
|
+
commands.register('notificationService.getManyNotifications', async ({}) => {
|
|
22
|
+
return await notification.getAll();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create notifications
|
|
27
|
+
*/
|
|
28
|
+
commands.register('notificationService.createNotifications', async ({ notifications }) => {
|
|
29
|
+
const validationErrors = [];
|
|
30
|
+
let createdNewNotifications = [];
|
|
31
|
+
|
|
32
|
+
for (const newData of notifications) {
|
|
33
|
+
const { errors } = validateNotification(newData);
|
|
34
|
+
if (errors?.length) {
|
|
35
|
+
validationErrors.push(errors);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const created = await notification.create(newData);
|
|
40
|
+
createdNewNotifications.push(created);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (validationErrors.length) {
|
|
44
|
+
throw new error.badRequest(`Invalid notification data: ${validationErrors}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return createdNewNotifications;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update notification
|
|
52
|
+
*/
|
|
53
|
+
commands.register('notificationService.updateNotification', async ({id, newNotificationData}) => {
|
|
54
|
+
|
|
55
|
+
const validationErrors = [];
|
|
56
|
+
|
|
57
|
+
if (!id) {
|
|
58
|
+
throw new error.badRequest('Notification ID required');
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const obj = await notification.getById({id: id});
|
|
63
|
+
|
|
64
|
+
if (!obj) {
|
|
65
|
+
throw new error.notFound('Notification not found');
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
delete newNotificationData.id;
|
|
70
|
+
|
|
71
|
+
const { errors } = validateNotificationUpdate(newNotificationData);
|
|
72
|
+
|
|
73
|
+
if (errors?.length) {
|
|
74
|
+
validationErrors.push(errors);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (validationErrors.length) {
|
|
78
|
+
throw new error.badRequest(`Invalid notification data: ${validationErrors}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return await notification.update({
|
|
82
|
+
id: id,
|
|
83
|
+
updatedData: newNotificationData
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Delete notification
|
|
89
|
+
*/
|
|
90
|
+
commands.register('notificationService.deleteNotification', async ({id}) => {
|
|
91
|
+
const obj = await notification.getById({id: id});
|
|
92
|
+
if (!obj) {
|
|
93
|
+
throw new error.notFound('Notification not found');
|
|
94
|
+
}
|
|
95
|
+
return await notification.delete({id: id});
|
|
96
|
+
});
|
|
@@ -1,15 +1,58 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* - Values:
|
|
6
|
-
* - SES (not implemented yet)
|
|
7
|
-
* - SMTP
|
|
8
|
-
* - Direct (not implemented yet)
|
|
2
|
+
* Gnar Engine Service Config
|
|
9
3
|
*/
|
|
10
|
-
export const
|
|
4
|
+
export const config = {
|
|
5
|
+
// service name
|
|
6
|
+
serviceName: 'notificationService',
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
// environment
|
|
9
|
+
environment: process.env.NOTIFICATION_NODE_ENV || 'dev',
|
|
10
|
+
runTests: process.env.NOTIFICATION_RUN_TESTS || false,
|
|
11
|
+
|
|
12
|
+
// microservice | modular-monolith
|
|
13
|
+
architecture: process.env.GLOBAL_ARCHITECTURE || 'microservice',
|
|
14
|
+
|
|
15
|
+
// web server
|
|
16
|
+
http: {
|
|
17
|
+
allowedOrigins: [],
|
|
18
|
+
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
19
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
20
|
+
rateLimiting: {
|
|
21
|
+
max: 5,
|
|
22
|
+
timeWindow: '1 minute',
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// database
|
|
27
|
+
db: {
|
|
28
|
+
// type: mongodb | mysql
|
|
29
|
+
type: 'mysql',
|
|
30
|
+
|
|
31
|
+
// MongoDB
|
|
32
|
+
connectionUrl: process.env.NOTIFICATION_MONGO_URL,
|
|
33
|
+
connectionArgs: {},
|
|
34
|
+
|
|
35
|
+
// MySQL
|
|
36
|
+
host: process.env.NOTIFICATION_MYSQL_HOST,
|
|
37
|
+
user: process.env.NOTIFICATION_MYSQL_USER,
|
|
38
|
+
password: process.env.NOTIFICATION_MYSQL_PASSWORD,
|
|
39
|
+
database: process.env.NOTIFICATION_MYSQL_DATABASE,
|
|
40
|
+
connectionLimit: 10,
|
|
41
|
+
queueLimit: 20,
|
|
42
|
+
maxRetries: 5
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// message broker
|
|
46
|
+
message: {
|
|
47
|
+
url: process.env.RABBITMQ_URL,
|
|
48
|
+
queueName: 'notificationServiceQueue',
|
|
49
|
+
prefetch: 20
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
webSockets: {
|
|
53
|
+
reconnectInterval: 5000,
|
|
54
|
+
maxInitialConnectionAttempts: 5
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
hashNameSpace: '',
|
|
58
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { commands } from '@gnar-engine/core';
|
|
2
|
+
import { authorise } from '../policies/notification.policy.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HTTP controller
|
|
6
|
+
*/
|
|
7
|
+
export const httpController = {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get single notification
|
|
11
|
+
*/
|
|
12
|
+
getSingle: {
|
|
13
|
+
method: 'GET',
|
|
14
|
+
url: '/notifications/:id',
|
|
15
|
+
preHandler: async (request, reply) => authorise.getSingle(request, reply),
|
|
16
|
+
handler: async (request, reply) => {
|
|
17
|
+
const params = {
|
|
18
|
+
id: request.params.id
|
|
19
|
+
};
|
|
20
|
+
const result = await commands.execute('getSingleNotification', params);
|
|
21
|
+
reply.code(200).send({ notification: result });
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get multiple notifications
|
|
27
|
+
*/
|
|
28
|
+
getMany: {
|
|
29
|
+
method: 'GET',
|
|
30
|
+
url: '/notifications/',
|
|
31
|
+
preHandler: async (request, reply) => authorise.getMany(request, reply),
|
|
32
|
+
handler: async (request, reply) => {
|
|
33
|
+
const params = {};
|
|
34
|
+
const results = await commands.execute('getManyNotifications', params);
|
|
35
|
+
reply.code(200).send({ notifications: results });
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create new notification
|
|
41
|
+
*/
|
|
42
|
+
create: {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
url: '/notifications/',
|
|
45
|
+
preHandler: async (request, reply) => authorise.create(request, reply),
|
|
46
|
+
handler: async (request, reply) => {
|
|
47
|
+
const params = {
|
|
48
|
+
notifications: [request.body.notification]
|
|
49
|
+
};
|
|
50
|
+
const results = await commands.execute('createNotifications', params);
|
|
51
|
+
reply.code(200).send({ notifications: results });
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Update notification
|
|
57
|
+
*/
|
|
58
|
+
update: {
|
|
59
|
+
method: 'POST',
|
|
60
|
+
url: '/notifications/:id',
|
|
61
|
+
preHandler: async (request, reply) => authorise.update(request, reply),
|
|
62
|
+
handler: async (request, reply) => {
|
|
63
|
+
const params = {
|
|
64
|
+
id: request.params.id,
|
|
65
|
+
newNotificationData: request.body
|
|
66
|
+
};
|
|
67
|
+
const result = await commands.execute('updateNotification', params);
|
|
68
|
+
reply.code(200).send({ notification: result });
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Delete notification
|
|
74
|
+
*/
|
|
75
|
+
delete: {
|
|
76
|
+
method: 'DELETE',
|
|
77
|
+
url: '/notifications/:id',
|
|
78
|
+
preHandler: async (request, reply) => authorise.delete(request, reply),
|
|
79
|
+
handler: async (request, reply) => {
|
|
80
|
+
const params = {
|
|
81
|
+
id: request.params.id
|
|
82
|
+
};
|
|
83
|
+
await commands.execute('deleteNotification', params);
|
|
84
|
+
reply.code(200).send({ message: 'Notification deleted' });
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
}
|
|
@@ -1,82 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { logger } from '../services/logger.service.js';
|
|
3
|
-
import { initializeRabbitMQ } from '@gnar-engine/message-client';
|
|
1
|
+
import { commands } from '@gnar-engine/core';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
const queueName = 'notificationServiceQueue';
|
|
7
|
-
const prefetch = 3;
|
|
3
|
+
export const messageHandlers = {
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!payload.method) {
|
|
16
|
-
return channel.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify({ error: 'Method not found' })), {
|
|
17
|
-
correlationId: msg.properties.correlationId,
|
|
5
|
+
getNotification: async (payload) => {
|
|
6
|
+
let result;
|
|
7
|
+
if (payload.data?.id) {
|
|
8
|
+
result = await commands.execute('getSingleNotification', {
|
|
9
|
+
id: payload.data.id
|
|
18
10
|
});
|
|
11
|
+
} else if (payload.data?.email) {
|
|
12
|
+
result = await commands.execute('getSingleNotification', {
|
|
13
|
+
email: payload.data.email
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
throw new Error('No notification ID or email provided');
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
case 'sendNotification':
|
|
23
|
-
try {
|
|
24
|
-
const { templateName, to, params, subject } = payload.data;
|
|
25
|
-
await commandBus.execute('sendNotification', { templateName, to, params, subject });
|
|
26
|
-
channel.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify({ status: 'ok' })), {
|
|
27
|
-
correlationId: msg.properties.correlationId,
|
|
28
|
-
});
|
|
29
|
-
} catch (error) {
|
|
30
|
-
logger.error("Error sending notification: " + error);
|
|
31
|
-
channel.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify({ error: 'Failed to send notification' })), {
|
|
32
|
-
correlationId: msg.properties.correlationId,
|
|
33
|
-
});
|
|
34
|
-
} finally {
|
|
35
|
-
channel.ack(msg);
|
|
36
|
-
}
|
|
37
|
-
break;
|
|
38
|
-
|
|
39
|
-
case 'healthCheck':
|
|
40
|
-
await this.handleHealthCheck(msg, channel);
|
|
41
|
-
break;
|
|
42
|
-
|
|
43
|
-
default:
|
|
44
|
-
await this.handleMethodNotFound(msg, channel);
|
|
18
|
+
if (!result) {
|
|
19
|
+
throw new Error('Notification not found');
|
|
45
20
|
}
|
|
21
|
+
return { notification: result };
|
|
46
22
|
},
|
|
47
23
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
channel.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify({ status: 'ok' })), {
|
|
52
|
-
correlationId: msg.properties.correlationId,
|
|
53
|
-
});
|
|
54
|
-
} catch (error) {
|
|
55
|
-
logger.error("Error running health check:", error);
|
|
56
|
-
} finally {
|
|
57
|
-
channel.ack(msg);
|
|
58
|
-
}
|
|
24
|
+
getManyNotifications: async (payload) => {
|
|
25
|
+
const results = await commands.execute('getManyNotifications', {});
|
|
26
|
+
return { notifications: results };
|
|
59
27
|
},
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
});
|
|
67
|
-
} catch (error) {
|
|
68
|
-
logger.error("Error handling method not found:", error);
|
|
69
|
-
} finally {
|
|
70
|
-
channel.ack(msg);
|
|
71
|
-
}
|
|
29
|
+
createNotification: async (payload) => {
|
|
30
|
+
const results = await commands.execute('createNotifications', {
|
|
31
|
+
notifications: [payload.data.notification]
|
|
32
|
+
});
|
|
33
|
+
return { notifications: results };
|
|
72
34
|
},
|
|
73
35
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
36
|
+
updateNotification: async (payload) => {
|
|
37
|
+
const result = await commands.execute('updateNotification', {
|
|
38
|
+
id: payload.data.id,
|
|
39
|
+
newNotificationData: payload.data
|
|
40
|
+
});
|
|
41
|
+
return { notification: result };
|
|
81
42
|
},
|
|
82
|
-
|
|
43
|
+
|
|
44
|
+
deleteNotification: async (payload) => {
|
|
45
|
+
await commands.execute('deleteNotification', {
|
|
46
|
+
id: payload.data.id
|
|
47
|
+
});
|
|
48
|
+
return { message: 'Notification deleted' };
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { logger, db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Up
|
|
5
|
+
*/
|
|
6
|
+
export const up = async () => {
|
|
7
|
+
await initDatabaseTables();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Down
|
|
12
|
+
*/
|
|
13
|
+
export const down = async () => {
|
|
14
|
+
await dropDatabaseTables();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create all tables
|
|
19
|
+
*/
|
|
20
|
+
export const initDatabaseTables = async () => {
|
|
21
|
+
|
|
22
|
+
// Migrations table
|
|
23
|
+
logger.info("Creating migrations table");
|
|
24
|
+
const createMigrationsTableQuery = `
|
|
25
|
+
CREATE TABLE migrations (
|
|
26
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
27
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
28
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
29
|
+
)`;
|
|
30
|
+
await db.query(createMigrationsTableQuery);
|
|
31
|
+
|
|
32
|
+
// Seeders table
|
|
33
|
+
logger.info("Creating seeders table");
|
|
34
|
+
const createSeedersTableQuery = `
|
|
35
|
+
CREATE TABLE seeders (
|
|
36
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
37
|
+
name VARCHAR(255) NOT NULL UNIQUE,
|
|
38
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
39
|
+
)`;
|
|
40
|
+
await db.query(createSeedersTableQuery);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Drop all tables
|
|
45
|
+
*/
|
|
46
|
+
export const dropDatabaseTables = async () => {
|
|
47
|
+
logger.info('Dropping tables');
|
|
48
|
+
await db.query('DROP TABLE IF EXISTS migrations');
|
|
49
|
+
await db.query('DROP TABLE IF EXISTS seeders');
|
|
50
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { logger, db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Up
|
|
5
|
+
*/
|
|
6
|
+
export const up = async () => {
|
|
7
|
+
logger.info('Creating table: notifications');
|
|
8
|
+
await db.query(`
|
|
9
|
+
CREATE TABLE notifications (
|
|
10
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
11
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
13
|
+
)
|
|
14
|
+
`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Down
|
|
19
|
+
*/
|
|
20
|
+
export const down = async () => {
|
|
21
|
+
logger.info('Dropping table: notifications');
|
|
22
|
+
await db.query('DROP TABLE IF EXISTS notifications');
|
|
23
|
+
}
|