@gnar-engine/cli 1.0.5 → 1.0.7
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 +13 -1
- package/src/dev/commands.js +7 -3
- package/src/dev/dev.service.js +192 -128
- 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/src/services/docker.js +173 -0
- 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
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
|
|
3
|
+
export const authorise = {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Authorise get single notification
|
|
7
|
+
*/
|
|
8
|
+
getSingle: async (request, reply) => {
|
|
9
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
10
|
+
reply.code(403).send({error: 'not authorised'});
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Authorise get many notifications
|
|
16
|
+
*/
|
|
17
|
+
getMany: async (request, reply) => {
|
|
18
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
19
|
+
reply.code(403).send({error: 'not authorised'});
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Authorise create notifications
|
|
25
|
+
*/
|
|
26
|
+
create: async (request, reply) => {
|
|
27
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
28
|
+
reply.code(403).send({error: 'not authorised'});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Authorise update notification
|
|
34
|
+
*/
|
|
35
|
+
update: async (request, reply) => {
|
|
36
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
37
|
+
reply.code(403).send({error: 'not authorised'});
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Authorise delete notification
|
|
43
|
+
*/
|
|
44
|
+
delete: async (request, reply) => {
|
|
45
|
+
if (!request.user || request.user.role !== 'service_admin') {
|
|
46
|
+
reply.code(403).send({error: 'not authorised'});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { schema } from '@gnar-engine/core';
|
|
2
|
+
import { config } from '../config.js';
|
|
3
|
+
|
|
4
|
+
export const notificationSchema = {
|
|
5
|
+
schemaName: 'notificationService.notificationSchema',
|
|
6
|
+
schema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
// Add your properties here
|
|
10
|
+
|
|
11
|
+
},
|
|
12
|
+
required: [],
|
|
13
|
+
additionalProperties: false
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const validateNotification = schema.compile(notificationSchema);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { db } from '@gnar-engine/core';
|
|
2
|
+
|
|
3
|
+
export const notification = {
|
|
4
|
+
async getById({ id }) {
|
|
5
|
+
const [result] = await db.query('SELECT * FROM notifications WHERE id = ?', [id]);
|
|
6
|
+
return result || null;
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
async getByEmail({ email }) {
|
|
10
|
+
// Placeholder: implement if your service uses email
|
|
11
|
+
return null;
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
async getAll() {
|
|
15
|
+
return await db.query('SELECT * FROM notifications');
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
async create(data) {
|
|
19
|
+
const { insertId } = await db.query('INSERT INTO notifications (created_at, updated_at) VALUES (CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)');
|
|
20
|
+
return await this.getById({ id: insertId });
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async update({ id, ...data }) {
|
|
24
|
+
await db.query('UPDATE notifications SET updated_at = CURRENT_TIMESTAMP WHERE id = ?', [id]);
|
|
25
|
+
return await this.getById({ id });
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
async delete({ id }) {
|
|
29
|
+
await db.query('DELETE FROM notifications WHERE id = ?', [id]);
|
|
30
|
+
return true;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
@@ -121,31 +121,48 @@ commands.register('userService.getManyUsers', async ({}) => {
|
|
|
121
121
|
* Creat users with random password
|
|
122
122
|
*
|
|
123
123
|
* @param {Object} params
|
|
124
|
-
* @param {
|
|
124
|
+
* @param {Array} params.users - New user data
|
|
125
125
|
*/
|
|
126
|
-
commands.register('userService.createUserWithRandomPassword', async ({
|
|
126
|
+
commands.register('userService.createUserWithRandomPassword', async ({users}) => {
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const userData = {
|
|
131
|
-
...user,
|
|
132
|
-
password: password
|
|
133
|
-
};
|
|
128
|
+
const validationErrors = [];
|
|
129
|
+
let createdNewUsers = [];
|
|
134
130
|
|
|
135
|
-
|
|
131
|
+
// validate user data
|
|
132
|
+
for (const newUserData of users) {
|
|
136
133
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
// create random password
|
|
135
|
+
const password = Math.random().toString(36);
|
|
136
|
+
newUserData.password = password;
|
|
140
137
|
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
const { errors } = validateUser(newUserData);
|
|
139
|
+
|
|
140
|
+
if (errors?.length) {
|
|
141
|
+
validationErrors.push(errors);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!newUserData.role || newUserData.role !== 'service_admin') {
|
|
146
|
+
// ensure emails are unique
|
|
147
|
+
const existingUser = await user.getByEmail({email: newUserData.email});
|
|
148
|
+
|
|
149
|
+
if (existingUser) {
|
|
150
|
+
validationErrors.push(`User with email ${newUserData.email} already exists`);
|
|
151
|
+
}
|
|
143
152
|
}
|
|
144
|
-
|
|
145
|
-
return newUsers[0];
|
|
146
|
-
} catch (error) {
|
|
147
|
-
throw new error.badRequest('User creation failed: ' + error);
|
|
148
153
|
}
|
|
154
|
+
|
|
155
|
+
if (validationErrors.length) {
|
|
156
|
+
throw new error.badRequest(`Invalid user data: ${validationErrors}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// add users
|
|
160
|
+
for (const newUserData of users) {
|
|
161
|
+
const newUser = await user.create(newUserData);
|
|
162
|
+
createdNewUsers.push(newUser);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return createdNewUsers;
|
|
149
166
|
});
|
|
150
167
|
|
|
151
168
|
/**
|
|
@@ -8,15 +8,24 @@ test.prep(async () => {
|
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
// Test create user command
|
|
11
|
-
test.run('Create
|
|
12
|
-
const users = await commands.execute('createUsers', [
|
|
11
|
+
test.run('Create user command', async () => {
|
|
12
|
+
const users = await commands.execute('createUsers', { users: [
|
|
13
13
|
{
|
|
14
|
-
email: 'test@gnar.co.uk'
|
|
14
|
+
email: 'test@gnar.co.uk',
|
|
15
|
+
password: 'p4ssw0rd987'
|
|
15
16
|
}
|
|
16
|
-
]);
|
|
17
|
-
|
|
17
|
+
]});
|
|
18
18
|
test.assert(users.length === 1, 'User was not created successfully');
|
|
19
19
|
test.assert(users[0].email === 'test@gnar.co.uk', 'User email does not match');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// Test create user with random password command
|
|
23
|
+
test.run('Create user with random password command', async () => {
|
|
24
|
+
const users = await commands.execute('createUserWithRandomPassword', { users: [
|
|
25
|
+
{
|
|
26
|
+
email: 'test2@gnar.co.uk'
|
|
27
|
+
}
|
|
28
|
+
]});
|
|
29
|
+
test.assert(users.length === 1, 'User was not created successfully');
|
|
30
|
+
test.assert(users[0].email === 'test3@gnar.co.uk', 'User email does not match');
|
|
31
|
+
});
|
package/install-from-clone.sh
CHANGED
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -30,9 +30,3 @@ G n a r E n g i n e - A powerful, AI ready microservice framework for modern a
|
|
|
30
30
|
// Parse CLI input
|
|
31
31
|
program.parse(process.argv);
|
|
32
32
|
|
|
33
|
-
// Consts
|
|
34
|
-
export const directories = {
|
|
35
|
-
scaffolderTemplates: path.join(import.meta.dirname, '../templates/service'),
|
|
36
|
-
bootstrap: path.join(import.meta.dirname, '../bootstrap'),
|
|
37
|
-
provisioner: path.join(import.meta.dirname, './provisioner')
|
|
38
|
-
}
|
package/src/config.js
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
1
3
|
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
2
6
|
export const gnarEngineCliConfig = {
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
9
|
* The path the Gnar Engine service core should be found in the service containers
|
|
6
10
|
*/
|
|
7
|
-
corePath: '/usr/gnar_engine/app/node_modules/@gnar-engine/core'
|
|
11
|
+
corePath: '/usr/gnar_engine/app/node_modules/@gnar-engine/core',
|
|
12
|
+
coreDevPath: path.join(__dirname, '../../core'),
|
|
8
13
|
|
|
9
14
|
}
|
|
15
|
+
|
|
16
|
+
export const directories = {
|
|
17
|
+
scaffolderServiceTemplates: path.join(import.meta.dirname, '../templates/service'),
|
|
18
|
+
scaffolderEntityTemplates: path.join(import.meta.dirname, '../templates/entity'),
|
|
19
|
+
bootstrap: path.join(import.meta.dirname, '../bootstrap'),
|
|
20
|
+
provisioner: path.join(import.meta.dirname, './provisioner')
|
|
21
|
+
};
|
package/src/dev/commands.js
CHANGED
|
@@ -10,11 +10,13 @@ export function registerDevCommands(program) {
|
|
|
10
10
|
devCmd
|
|
11
11
|
.command('up')
|
|
12
12
|
.description('🛠️ Up Development Containers')
|
|
13
|
-
.option('-b, --build', '
|
|
13
|
+
.option('-b, --build', 'Build without cache')
|
|
14
14
|
.option('-d, --detach', 'Run containers in background')
|
|
15
|
+
.option('-a, --attach-all', 'Attach all services including database and message queues for debugging')
|
|
15
16
|
.option('-t --test', 'Run the tests with ephemeral databases')
|
|
16
|
-
.option('--test-service <service>', 'Run the tests for the specified service with ephemeral databases')
|
|
17
|
+
.option('--test-service <service>', 'Run the tests for the specified service with ephemeral databases (e.g. --test-service user)')
|
|
17
18
|
.addOption(new Option('--core-dev').hideHelp())
|
|
19
|
+
.addOption(new Option('--bootstrap-dev').hideHelp())
|
|
18
20
|
.action(async (options) => {
|
|
19
21
|
let response = {};
|
|
20
22
|
|
|
@@ -39,8 +41,10 @@ export function registerDevCommands(program) {
|
|
|
39
41
|
build: options.build || false,
|
|
40
42
|
detach: options.detach || false,
|
|
41
43
|
coreDev: options.coreDev || false,
|
|
44
|
+
bootstrapDev: options.bootstrapDev || false,
|
|
42
45
|
test: options.test || false,
|
|
43
|
-
testService: options.testService || ''
|
|
46
|
+
testService: options.testService || '',
|
|
47
|
+
attachAll: options.attachAll || false
|
|
44
48
|
});
|
|
45
49
|
} catch (err) {
|
|
46
50
|
console.error("❌ Error running containers:", err.message);
|