@gnar-engine/cli 1.0.0 → 1.0.1
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/assets/gnar-engine-logo-white.svg +9 -0
- package/bootstrap/deploy.localdev.yml +51 -0
- package/bootstrap/secrets.localdev.yml +27 -0
- package/bootstrap/services/agent/Dockerfile +23 -0
- package/bootstrap/services/agent/notes.md +28 -0
- package/bootstrap/services/agent/package.json +16 -0
- package/bootstrap/services/agent/src/app.js +52 -0
- package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
- package/bootstrap/services/agent/src/config.js +52 -0
- package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
- package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
- package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
- package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
- package/bootstrap/services/agent/src/services/agent.service.js +259 -0
- package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
- package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
- package/bootstrap/services/control/Dockerfile +23 -0
- package/bootstrap/services/control/Dockerfile.prod +37 -0
- package/bootstrap/services/control/README.md +25 -0
- package/bootstrap/services/control/package.json +16 -0
- package/bootstrap/services/control/src/app.js +45 -0
- package/bootstrap/services/control/src/commands/control.handler.js +231 -0
- package/bootstrap/services/control/src/commands/service.handler.js +81 -0
- package/bootstrap/services/control/src/commands/task.handler.js +247 -0
- package/bootstrap/services/control/src/config.js +55 -0
- package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
- package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
- package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
- package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
- package/bootstrap/services/control/src/policies/task.policy.js +53 -0
- package/bootstrap/services/control/src/schema/control.schema.js +42 -0
- package/bootstrap/services/control/src/services/registry.service.js +83 -0
- package/bootstrap/services/control/src/services/reset.service.js +28 -0
- package/bootstrap/services/control/src/services/task.service.js +153 -0
- package/bootstrap/services/control/src/tests/control.test.js +50 -0
- package/bootstrap/services/notification/Dockerfile +23 -0
- package/bootstrap/services/notification/Dockerfile.prod +37 -0
- package/bootstrap/services/notification/README.md +3 -0
- package/bootstrap/services/notification/package.json +34 -0
- package/bootstrap/services/notification/src/app.js +51 -0
- package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
- package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
- package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
- package/bootstrap/services/notification/src/config.js +15 -0
- package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
- package/bootstrap/services/notification/src/services/logger.service.js +16 -0
- package/bootstrap/services/notification/src/services/ses.service.js +23 -0
- package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
- package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
- package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
- package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
- package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
- package/bootstrap/services/portal/Dockerfile +23 -0
- package/bootstrap/services/portal/Dockerfile.remote +40 -0
- package/bootstrap/services/portal/README.md +22 -0
- package/bootstrap/services/portal/nginx.conf +12 -0
- package/bootstrap/services/portal/package.json +59 -0
- package/bootstrap/services/portal/public/favicon.ico +0 -0
- package/bootstrap/services/portal/public/gnar-white.png +0 -0
- package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/public/index.html +43 -0
- package/bootstrap/services/portal/public/logo192.png +0 -0
- package/bootstrap/services/portal/public/logo512.png +0 -0
- package/bootstrap/services/portal/public/manifest.json +25 -0
- package/bootstrap/services/portal/public/robots.txt +3 -0
- package/bootstrap/services/portal/src/App.js +56 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
- package/bootstrap/services/portal/src/assets/activity.svg +3 -0
- package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
- package/bootstrap/services/portal/src/assets/bin.svg +3 -0
- package/bootstrap/services/portal/src/assets/check.svg +3 -0
- package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
- package/bootstrap/services/portal/src/assets/contact.svg +3 -0
- package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
- package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
- package/bootstrap/services/portal/src/assets/eye.svg +4 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
- package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
- package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/src/assets/home.svg +3 -0
- package/bootstrap/services/portal/src/assets/link.svg +3 -0
- package/bootstrap/services/portal/src/assets/lock.svg +3 -0
- package/bootstrap/services/portal/src/assets/package.svg +4 -0
- package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
- package/bootstrap/services/portal/src/assets/settings.svg +4 -0
- package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
- package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
- package/bootstrap/services/portal/src/assets/user.svg +3 -0
- package/bootstrap/services/portal/src/assets/users.svg +3 -0
- package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
- package/bootstrap/services/portal/src/css/style.css +1007 -0
- package/bootstrap/services/portal/src/data/data.js +70 -0
- package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
- package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
- package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
- package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
- package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
- package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
- package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
- package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
- package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
- package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
- package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
- package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
- package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
- package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
- package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
- package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
- package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
- package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
- package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
- package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
- package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
- package/bootstrap/services/portal/src/features/user/user.less +57 -0
- package/bootstrap/services/portal/src/includes/utilities.js +259 -0
- package/bootstrap/services/portal/src/index.js +14 -0
- package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
- package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
- package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
- package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
- package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
- package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
- package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
- package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
- package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
- package/bootstrap/services/portal/src/pages/login/login.less +10 -0
- package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
- package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
- package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
- package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
- package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
- package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
- package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
- package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
- package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
- package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
- package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
- package/bootstrap/services/portal/src/pages/users/users.less +25 -0
- package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
- package/bootstrap/services/portal/src/store/configureStore.js +12 -0
- package/bootstrap/services/portal/src/styles/global.less +159 -0
- package/bootstrap/services/portal/src/styles/inputs.less +157 -0
- package/bootstrap/services/portal/src/styles/main.less +26 -0
- package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
- package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
- package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
- package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
- package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
- package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
- package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
- package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
- package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
- package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
- package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
- package/bootstrap/services/user/Dockerfile +23 -0
- package/bootstrap/services/user/Dockerfile.prod +37 -0
- package/bootstrap/services/user/README.md +8 -0
- package/bootstrap/services/user/package.json +16 -0
- package/bootstrap/services/user/src/app.js +45 -0
- package/bootstrap/services/user/src/commands/session.handler.js +23 -0
- package/bootstrap/services/user/src/commands/user.handler.js +286 -0
- package/bootstrap/services/user/src/config.js +73 -0
- package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
- package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
- package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
- package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
- package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
- package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
- package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
- package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
- package/bootstrap/services/user/src/policies/user.policy.js +81 -0
- package/bootstrap/services/user/src/schema/user.schema.js +69 -0
- package/bootstrap/services/user/src/services/authentication.service.js +127 -0
- package/bootstrap/services/user/src/services/session.service.js +58 -0
- package/bootstrap/services/user/src/services/user.service.js +130 -0
- package/bootstrap/services/user/src/tests/user.test.js +126 -0
- package/package.json +3 -7
- package/src/agent/agent.client.js +28 -0
- package/src/agent/commands.js +48 -0
- package/src/cli.js +30 -0
- package/src/config.js +8 -0
- package/src/control/commands.js +156 -0
- package/src/control/control.client.js +127 -0
- package/src/dev/commands.js +71 -0
- package/src/dev/dev.service.js +320 -0
- package/src/engine/infra.js +142 -0
- package/src/helpers/helpers.js +63 -0
- package/src/profiles/command.js +170 -0
- package/src/profiles/profiles.client.js +101 -0
- package/src/scaffolder/commands.js +123 -0
- package/src/scaffolder/scaffolder.handler.js +252 -0
- package/src/services/client.js +174 -0
- package/templates/service/Dockerfile.hbs +20 -0
- package/templates/service/app.js.hbs +38 -0
- package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
- package/templates/service/config.js.hbs +48 -0
- package/templates/service/controllers/http.controller.js.hbs +87 -0
- package/templates/service/controllers/message.controller.js.hbs +51 -0
- package/templates/service/db/migrations/01-init.js.hbs +50 -0
- package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
- package/templates/service/package.json.hbs +18 -0
- package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
- package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
- package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
- package/dist/cli.js +0 -18
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { profiles } from '../profiles/profiles.client.js';
|
|
5
|
+
import { helpers } from '../helpers/helpers.js';
|
|
6
|
+
import Handlebars from 'handlebars';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Gnar Engine Scaffolder
|
|
10
|
+
*/
|
|
11
|
+
export const scaffolder = {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a new service
|
|
15
|
+
*
|
|
16
|
+
* @param {object} param
|
|
17
|
+
* @param {string} param.serviceName - The name of the service to create
|
|
18
|
+
* @param {string} param.database - The database type (e.g., 'mysql', 'mongodb')
|
|
19
|
+
* @param {string} param.projectDir - The project directory where the service will be created
|
|
20
|
+
* @returns {object} - An object containing a success message and the service path
|
|
21
|
+
*/
|
|
22
|
+
createNewService: function ({serviceName, database, projectDir}) {
|
|
23
|
+
const serviceDir = projectDir + 'services/' + serviceName;
|
|
24
|
+
console.log('Service directory:', serviceDir);
|
|
25
|
+
|
|
26
|
+
// Check if the service directory already exists
|
|
27
|
+
if (fs.existsSync(serviceDir)) {
|
|
28
|
+
throw new Error(`Service "${serviceName}" already exists at ${serviceDir}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Create the service directory
|
|
32
|
+
fs.mkdirSync(serviceDir, { recursive: true });
|
|
33
|
+
|
|
34
|
+
// Get all files in the templates directory
|
|
35
|
+
const templatesDir = path.join(import.meta.dirname, '../../templates/service');
|
|
36
|
+
const templateFiles = scaffolder.getAllTemplateFiles({
|
|
37
|
+
dir: templatesDir,
|
|
38
|
+
baseDir: templatesDir
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log('Template files:', templateFiles);
|
|
42
|
+
|
|
43
|
+
// Register Handlebars helpers
|
|
44
|
+
Object.entries(helpers).forEach(([name, fn]) => {
|
|
45
|
+
Handlebars.registerHelper(name, fn);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Write the files to the service directory
|
|
49
|
+
templateFiles.forEach(file => {
|
|
50
|
+
let sourcePath;
|
|
51
|
+
let targetPath;
|
|
52
|
+
const templateArgs = {
|
|
53
|
+
serviceName,
|
|
54
|
+
database
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
switch (file.extension) {
|
|
58
|
+
case '.hbs':
|
|
59
|
+
// Compile the Handlebars template for content
|
|
60
|
+
const templateContent = fs.readFileSync(file.fullPath, 'utf8');
|
|
61
|
+
const compiledTemplate = Handlebars.compile(templateContent);
|
|
62
|
+
const renderedContent = compiledTemplate(templateArgs);
|
|
63
|
+
|
|
64
|
+
// Compile the Handlebars template for the filename (excluding .hbs)
|
|
65
|
+
const filenameTemplate = Handlebars.compile(file.relativePath.replace(/\.hbs$/, ''));
|
|
66
|
+
const renderedFilename = filenameTemplate(templateArgs);
|
|
67
|
+
targetPath = path.join(serviceDir, renderedFilename);
|
|
68
|
+
|
|
69
|
+
// Ensure directory exists
|
|
70
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
71
|
+
fs.writeFileSync(targetPath, renderedContent, 'utf8');
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
// By default, copy the file to the service directory
|
|
75
|
+
sourcePath = file.fullPath;
|
|
76
|
+
targetPath = path.join(serviceDir, file.relativePath);
|
|
77
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
78
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
message: `Service "${serviceName}" created successfully at ${serviceDir}`,
|
|
85
|
+
servicePath: serviceDir
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create new front-end service
|
|
91
|
+
*
|
|
92
|
+
* @param {object} param
|
|
93
|
+
* @param {string} param.serviceName - The name of the service to create
|
|
94
|
+
* @param {string} param.projectDir - The project directory where the service will be created
|
|
95
|
+
* @returns {object} - An object containing a success message and the service path
|
|
96
|
+
*/
|
|
97
|
+
createNewFrontEndService: function ({serviceName, projectDir}) {
|
|
98
|
+
const serviceDir = projectDir + 'services/' + serviceName;
|
|
99
|
+
console.log('Service directory:', serviceDir);
|
|
100
|
+
|
|
101
|
+
// Check if the service directory already exists
|
|
102
|
+
if (fs.existsSync(serviceDir)) {
|
|
103
|
+
throw new Error(`Service "${serviceName}" already exists at ${serviceDir}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Create the service directory
|
|
107
|
+
fs.mkdirSync(serviceDir, { recursive: true });
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Recursively get all template files in a directory
|
|
112
|
+
*
|
|
113
|
+
* @param {object} params
|
|
114
|
+
* @param {string} params.dir - The directory to search for template files
|
|
115
|
+
* @param {string} [params.baseDir=dir] - The base directory for relative paths
|
|
116
|
+
* @param {Array} [params.fileList=[]] - The list to store found files
|
|
117
|
+
* @returns {Array} - An array of objects containing full and relative paths of template files
|
|
118
|
+
*/
|
|
119
|
+
getAllTemplateFiles: function ({dir, baseDir = dir, fileList = []}) {
|
|
120
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
121
|
+
|
|
122
|
+
entries.forEach(entry => {
|
|
123
|
+
const fullPath = path.join(dir, entry.name);
|
|
124
|
+
if (entry.isDirectory()) {
|
|
125
|
+
if (entry.name !== 'node_modules' && entry.name !== 'data') {
|
|
126
|
+
if (!entry.name.startsWith('.') || entry.name == '.gnarengine') {
|
|
127
|
+
scaffolder.getAllTemplateFiles({
|
|
128
|
+
dir: fullPath,
|
|
129
|
+
baseDir,
|
|
130
|
+
fileList
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
136
|
+
|
|
137
|
+
if (entry.name !== 'docker-compose.dev.yml') {
|
|
138
|
+
fileList.push({ fullPath, relativePath, extension: path.extname(entry.name) });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return fileList;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create a new project
|
|
148
|
+
*
|
|
149
|
+
* @param {object} param
|
|
150
|
+
* @param {string} param.projectName - The name of the project to create
|
|
151
|
+
* @param {string} param.projectDir - The directory where the project will be created
|
|
152
|
+
* @param {string} param.rootAdminEmail - The email for the root admin user
|
|
153
|
+
*/
|
|
154
|
+
createNewProject: function ({projectName, projectDir, rootAdminEmail}) {
|
|
155
|
+
projectName = projectName.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9\-]/g, '');
|
|
156
|
+
|
|
157
|
+
const fullProjectPath = path.join(projectDir, projectName);
|
|
158
|
+
console.log('Creating project in:', fullProjectPath);
|
|
159
|
+
|
|
160
|
+
// Check to make sure there isn't already a profile with this project name
|
|
161
|
+
const profileName = projectName + ':local';
|
|
162
|
+
const allProfiles = profiles.getAllProfiles();
|
|
163
|
+
|
|
164
|
+
if (allProfiles && allProfiles.profiles) {
|
|
165
|
+
if (allProfiles.profiles[profileName]) {
|
|
166
|
+
throw new Error(`A profile with the name "${projectName}:local" already exists. Please choose a different project name or delete the existing profile.`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Create the project directory
|
|
171
|
+
if (!fs.existsSync(fullProjectPath)) {
|
|
172
|
+
fs.mkdirSync(fullProjectPath, { recursive: true });
|
|
173
|
+
fs.mkdirSync(path.join(fullProjectPath, 'data'), { recursive: true });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Copy bootstrap
|
|
177
|
+
const bootstrapDir = path.join(import.meta.dirname, '../../bootstrap');
|
|
178
|
+
const bootstrapFiles = scaffolder.getAllTemplateFiles({
|
|
179
|
+
dir: path.join(bootstrapDir),
|
|
180
|
+
baseDir: path.join(bootstrapDir)
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
let cliApiKey = '';
|
|
184
|
+
|
|
185
|
+
console.log('Copying bootstrap');
|
|
186
|
+
|
|
187
|
+
if (!bootstrapFiles || bootstrapFiles.length === 0) {
|
|
188
|
+
throw new Error('No bootstrap files found');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
bootstrapFiles.forEach(file => {
|
|
192
|
+
let sourcePath;
|
|
193
|
+
let targetPath;
|
|
194
|
+
|
|
195
|
+
sourcePath = file.fullPath;
|
|
196
|
+
targetPath = path.join(fullProjectPath, file.relativePath);
|
|
197
|
+
|
|
198
|
+
// create random secrets
|
|
199
|
+
if (file.relativePath === 'secrets.localdev.yml') {
|
|
200
|
+
console.log('Creating random secrets: secrets.localdev.yml');
|
|
201
|
+
const secretsPath = path.join(bootstrapDir, 'secrets.localdev.yml');
|
|
202
|
+
const rawSecrets = fs.readFileSync(secretsPath, 'utf8');
|
|
203
|
+
const parsedSecrets = yaml.load(rawSecrets);
|
|
204
|
+
|
|
205
|
+
// generate random passwords
|
|
206
|
+
Object.keys(parsedSecrets.services).forEach(serviceName => {
|
|
207
|
+
Object.keys(parsedSecrets.services[serviceName]).forEach(key => {
|
|
208
|
+
if (key.toLowerCase().includes('pass')) {
|
|
209
|
+
parsedSecrets.services[serviceName][key] = helpers.generateRandomString(16);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// set random root api key
|
|
215
|
+
cliApiKey = helpers.generateRandomString(32);
|
|
216
|
+
parsedSecrets.services.user.ROOT_ADMIN_API_KEY = cliApiKey;
|
|
217
|
+
parsedSecrets.services.user.ROOT_ADMIN_EMAIL = rootAdminEmail || 'admin@' + projectName + '.local';
|
|
218
|
+
|
|
219
|
+
// save updated secrets file
|
|
220
|
+
const newSecretsContent = yaml.dump(parsedSecrets);
|
|
221
|
+
fs.writeFileSync(secretsPath, newSecretsContent, 'utf8');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
225
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Create the profile
|
|
229
|
+
console.log('Creating new CLI profile: ' + profileName);
|
|
230
|
+
const config = {
|
|
231
|
+
CLI_API_URL: 'http://localhost',
|
|
232
|
+
CLI_API_USERNAME: 'gnarlyroot',
|
|
233
|
+
CLI_API_KEY: cliApiKey,
|
|
234
|
+
PROJECT_DIR: fullProjectPath
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// save profile to config file
|
|
238
|
+
profiles.createProfile({
|
|
239
|
+
profileName: profileName,
|
|
240
|
+
config: config
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// set active profile if required
|
|
244
|
+
console.log('Setting CLI profile to active');
|
|
245
|
+
profiles.setActiveProfile({
|
|
246
|
+
profileName: profileName
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
console.log('g n a r e n g i n e - Created new project: ' + projectName);
|
|
250
|
+
console.log('Run `gnar dev up` to start the development server');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { profiles } from '../profiles/profiles.client.js';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
|
|
7
|
+
let client;
|
|
8
|
+
let profile;
|
|
9
|
+
let profileName;
|
|
10
|
+
let baseApiUrl;
|
|
11
|
+
let authToken;
|
|
12
|
+
let username;
|
|
13
|
+
let apiKey;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Initialise the profile
|
|
17
|
+
*/
|
|
18
|
+
export const initAxiosClient = () => {
|
|
19
|
+
// Determine the correct API URL based on the environment
|
|
20
|
+
try {
|
|
21
|
+
profile = profiles.getActiveProfile();
|
|
22
|
+
baseApiUrl = profile.profile.CLI_API_URL;
|
|
23
|
+
username = profile.profile.CLI_API_USERNAME;
|
|
24
|
+
apiKey = profile.profile.CLI_API_KEY;
|
|
25
|
+
profileName = profile.name;
|
|
26
|
+
|
|
27
|
+
console.log('Profile: ' + profile.name + ' | ' + baseApiUrl);
|
|
28
|
+
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error retrieving active profile:', error.message);
|
|
31
|
+
throw new Error('Active profile not found. Please set an active profile using `gnar profile set-active <profileName>`');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Create axios client
|
|
35
|
+
client = axios.create({
|
|
36
|
+
baseURL: baseApiUrl,
|
|
37
|
+
withCredentials: true,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Request interceptors
|
|
41
|
+
client.interceptors.request.use(
|
|
42
|
+
async (config) => {
|
|
43
|
+
|
|
44
|
+
// Return pre-existing acces token if we have one
|
|
45
|
+
try {
|
|
46
|
+
authToken = await getAccessToken({activeProfileName: profileName});
|
|
47
|
+
|
|
48
|
+
if (authToken) {
|
|
49
|
+
config.headers['Authorization'] = `Bearer ${authToken}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return config;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
//console.log('No access token found, authenticating...');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Authenticate if no token is found
|
|
58
|
+
try {
|
|
59
|
+
const authResponse = await axios.post(`${baseApiUrl}/authenticate/`, {
|
|
60
|
+
username: username,
|
|
61
|
+
apiKey: apiKey
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (!authResponse.data?.token) {
|
|
65
|
+
throw new Error('Authentication failed', authResponse.data?.error || 'No token received');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
authToken = authResponse.data.token;
|
|
69
|
+
|
|
70
|
+
setAccessToken({
|
|
71
|
+
activeProfileName: profileName,
|
|
72
|
+
accessToken: authToken,
|
|
73
|
+
accessTokenExpires: new Date(Date.now() + 3600000).toISOString()
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (authToken) {
|
|
77
|
+
config.headers['Authorization'] = `Bearer ${authToken}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return config;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('Authentication failed:', error.response?.data?.message || error.message);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
(error) => {
|
|
87
|
+
return Promise.reject(error);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
export default client;
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get data resource
|
|
98
|
+
*/
|
|
99
|
+
export const getDataResource = async (resourceSlug) => {
|
|
100
|
+
try {
|
|
101
|
+
const response = await client.get(`/data/${resourceSlug}`);
|
|
102
|
+
return response.data;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get access token
|
|
110
|
+
*
|
|
111
|
+
* @param {Object} options - Options for getting the access token
|
|
112
|
+
* @param {string} options.activeProfileName - The name of the active profile
|
|
113
|
+
* @returns {Promise<string>} - The access token
|
|
114
|
+
* @throws {Error} - If the access token is not found or has expired
|
|
115
|
+
*/
|
|
116
|
+
export const getAccessToken = async ({activeProfileName}) => {
|
|
117
|
+
|
|
118
|
+
let accessToken = null;
|
|
119
|
+
let accessTokenExpires = null;
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const profileCachePath = path.join(os.homedir(), '.gnarengine', activeProfileName + '.json');
|
|
123
|
+
const profileCache = JSON.parse(fs.readFileSync(profileCachePath, 'utf-8'));
|
|
124
|
+
accessToken = profileCache.accessToken;
|
|
125
|
+
accessTokenExpires = profileCache.accessTokenExpires;
|
|
126
|
+
|
|
127
|
+
if (!accessToken || !accessTokenExpires) {
|
|
128
|
+
throw new Error('Access token or expiration not found in cache');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (new Date(accessTokenExpires) < new Date()) {
|
|
132
|
+
throw new Error('Access token has expired');
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return accessToken;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Set access token
|
|
143
|
+
*
|
|
144
|
+
* @param {Object} options - Options for setting the access token
|
|
145
|
+
* @param {string} options.activeProfileName - The name of the active profile
|
|
146
|
+
* @param {string} options.accessToken - The access token to set
|
|
147
|
+
* @param {Date} options.accessTokenExpires - The expiration date of the access token
|
|
148
|
+
* @returns {Promise<void>}
|
|
149
|
+
* @throws {Error} - If unable to write to the profile cache file
|
|
150
|
+
*/
|
|
151
|
+
export const setAccessToken = async ({activeProfileName, accessToken, accessTokenExpires}) => {
|
|
152
|
+
try {
|
|
153
|
+
let profileCache = {};
|
|
154
|
+
|
|
155
|
+
const profileCachePath = path.join(os.homedir(), '.gnarengine', activeProfileName + '.json');
|
|
156
|
+
|
|
157
|
+
if (fs.existsSync(profileCachePath)) {
|
|
158
|
+
try {
|
|
159
|
+
profileCache = JSON.parse(fs.readFileSync(profileCachePath, 'utf-8'));
|
|
160
|
+
} catch (error) {
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
fs.mkdirSync(path.dirname(profileCachePath), { recursive: true });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
profileCache.accessToken = accessToken;
|
|
168
|
+
profileCache.accessTokenExpires = accessTokenExpires;
|
|
169
|
+
|
|
170
|
+
fs.writeFileSync(profileCachePath, JSON.stringify(profileCache, null, 2));
|
|
171
|
+
} catch (error) {
|
|
172
|
+
throw new Error('Unable to write to profile cache file: ' + error.message);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Dockerfile for {{pascalCase serviceName}} Service
|
|
2
|
+
FROM gnarengine/service-core:1.0.0
|
|
3
|
+
|
|
4
|
+
# Set the working directory
|
|
5
|
+
WORKDIR /usr/gnar_engine/app
|
|
6
|
+
|
|
7
|
+
# Copy package.json and package-lock.json
|
|
8
|
+
COPY ./services/{{serviceName}}/package*.json ./
|
|
9
|
+
|
|
10
|
+
# Install nodemon
|
|
11
|
+
RUN npm install -g nodemon
|
|
12
|
+
|
|
13
|
+
# Install app dependencies
|
|
14
|
+
RUN npm install
|
|
15
|
+
|
|
16
|
+
# Expose the port the service will run on
|
|
17
|
+
EXPOSE 3000
|
|
18
|
+
|
|
19
|
+
# Start the application
|
|
20
|
+
CMD ["nodemon", "--watch", "./gnar_engine", "./gnar_engine/app.js"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { message, http, logger, db } from '@gnar-engine/core';
|
|
2
|
+
import { config } from './config.js';
|
|
3
|
+
import { messageHandlers } from './controllers/message.controller.js';
|
|
4
|
+
import { httpController as {{pascalCase serviceName}}PlatformHttpController } from './controllers/http.controller.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Initialise service
|
|
8
|
+
*/
|
|
9
|
+
export const initService = async () => {
|
|
10
|
+
|
|
11
|
+
// Run migrations
|
|
12
|
+
db.migrations.runMigrations({config});
|
|
13
|
+
db.seeders.runSeeders({config});
|
|
14
|
+
|
|
15
|
+
// Import command handlers after the command bus is initialised
|
|
16
|
+
await import('./commands/{{lowerCasePlural serviceName}}.handler.js');
|
|
17
|
+
// Add more handlers as needed
|
|
18
|
+
|
|
19
|
+
// Initialise and register message handlers
|
|
20
|
+
await message.init({
|
|
21
|
+
config: config.message,
|
|
22
|
+
handlers: messageHandlers
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Register http routes
|
|
26
|
+
await http.registerRoutes({
|
|
27
|
+
controllers: [
|
|
28
|
+
{{pascalCase serviceName}}PlatformHttpController,
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Start the HTTP server
|
|
33
|
+
await http.start();
|
|
34
|
+
|
|
35
|
+
logger.info('G n a r E n g i n e | {{capitaliseFirstLetter serviceName}} Service initialised successfully.');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
initService();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { commands, logger, error } from '@gnar-engine/core';
|
|
2
|
+
import { auth } from '../services/authentication.service.js';
|
|
3
|
+
import { {{serviceName}} } from '../services/{{serviceName}}.service.js';
|
|
4
|
+
import { config } from '../config.js';
|
|
5
|
+
import { validate{{pascalCase serviceName}}, validateServiceAdmin{{pascalCase serviceName}}, validate{{pascalCase serviceName}}Update, validateServiceAdmin{{pascalCase serviceName}}Update } from '../schema/{{serviceName}}.schema.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get single {{serviceName}}
|
|
10
|
+
*/
|
|
11
|
+
commands.register('{{serviceName}}Service.getSingle{{pascalCase serviceName}}', async ({id}) => {
|
|
12
|
+
if (id) {
|
|
13
|
+
return await {{serviceName}}.getById({id: id});
|
|
14
|
+
} else {
|
|
15
|
+
throw new error.badRequest('{{pascalCase serviceName}} email or id required');
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get many {{lowerCasePlural serviceName}}
|
|
21
|
+
*/
|
|
22
|
+
commands.register('{{serviceName}}Service.getMany{{pascalCasePlural serviceName}}', async ({}) => {
|
|
23
|
+
return await {{serviceName}}.getAll();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Create {{lowerCasePlural serviceName}}
|
|
28
|
+
*/
|
|
29
|
+
commands.register('{{serviceName}}Service.create{{pascalCasePlural serviceName}}', async ({ {{lowerCasePlural serviceName}} }) => {
|
|
30
|
+
const validationErrors = [];
|
|
31
|
+
let createdNew{{pascalCasePlural serviceName}} = [];
|
|
32
|
+
|
|
33
|
+
for (const newData of {{lowerCasePlural serviceName}}) {
|
|
34
|
+
const { errors } = validate{{pascalCase serviceName}}(newData);
|
|
35
|
+
if (errors?.length) {
|
|
36
|
+
validationErrors.push(errors);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const created = await {{serviceName}}.create(newData);
|
|
41
|
+
createdNew{{pascalCasePlural serviceName}}.push(created);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (validationErrors.length) {
|
|
45
|
+
throw new error.badRequest(`Invalid {{serviceName}} data: ${validationErrors}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return createdNew{{pascalCasePlural serviceName}};
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Update {{serviceName}}
|
|
53
|
+
*/
|
|
54
|
+
commands.register('{{serviceName}}Service.update{{pascalCase serviceName}}', async ({id, new{{pascalCase serviceName}}Data}) => {
|
|
55
|
+
|
|
56
|
+
const validationErrors = [];
|
|
57
|
+
|
|
58
|
+
if (!id) {
|
|
59
|
+
throw new error.badRequest('{{pascalCase serviceName}} ID required');
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const obj = await {{serviceName}}.getById({id: id});
|
|
64
|
+
|
|
65
|
+
if (!obj) {
|
|
66
|
+
throw new error.notFound('{{pascalCase serviceName}} not found');
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
delete new{{pascalCase serviceName}}Data.id;
|
|
71
|
+
|
|
72
|
+
const { errors } = validate{{pascalCase serviceName}}Update(new{{pascalCase serviceName}}Data);
|
|
73
|
+
|
|
74
|
+
if (errors?.length) {
|
|
75
|
+
validationErrors.push(errors);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (validationErrors.length) {
|
|
79
|
+
throw new error.badRequest(`Invalid {{serviceName}} data: ${validationErrors}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return await {{serviceName}}.update({
|
|
83
|
+
id: id,
|
|
84
|
+
...new{{pascalCase serviceName}}Data
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Delete {{serviceName}}
|
|
90
|
+
*/
|
|
91
|
+
commands.register('{{serviceName}}Service.delete{{pascalCase serviceName}}', async ({id}) => {
|
|
92
|
+
const obj = await {{serviceName}}.getById({id: id});
|
|
93
|
+
if (!obj) {
|
|
94
|
+
throw new error.notFound('{{pascalCase serviceName}} not found');
|
|
95
|
+
}
|
|
96
|
+
return await {{serviceName}}.delete({id: id});
|
|
97
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gnar Engine Service Config
|
|
3
|
+
*/
|
|
4
|
+
export const config = {
|
|
5
|
+
// service name
|
|
6
|
+
serviceName: '{{serviceName}}Service',
|
|
7
|
+
|
|
8
|
+
// microservice | modular-monolith
|
|
9
|
+
architecture: process.env.GLOBAL_ARCHITECTURE || 'microservice',
|
|
10
|
+
|
|
11
|
+
// web server
|
|
12
|
+
http: {
|
|
13
|
+
allowedOrigins: [],
|
|
14
|
+
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
15
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
16
|
+
rateLimiting: {
|
|
17
|
+
max: 5,
|
|
18
|
+
timeWindow: '1 minute',
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// database
|
|
23
|
+
db: {
|
|
24
|
+
// type: mongodb | mysql
|
|
25
|
+
type: 'mysql',
|
|
26
|
+
|
|
27
|
+
// MongoDB
|
|
28
|
+
connectionUrl: process.env.{{upperCase serviceName}}_MONGO_URL,
|
|
29
|
+
connectionArgs: {},
|
|
30
|
+
|
|
31
|
+
// MySQL
|
|
32
|
+
host: process.env.{{upperCase serviceName}}_MYSQL_HOST,
|
|
33
|
+
user: process.env.{{upperCase serviceName}}_MYSQL_USER,
|
|
34
|
+
password: process.env.{{upperCase serviceName}}_MYSQL_PASSWORD,
|
|
35
|
+
database: process.env.{{upperCase serviceName}}_MYSQL_DATABASE,
|
|
36
|
+
connectionLimit: 10,
|
|
37
|
+
queueLimit: 20,
|
|
38
|
+
maxRetries: 5
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
// message broker
|
|
42
|
+
message: {
|
|
43
|
+
queueName: '{{serviceName}}ServiceQueue',
|
|
44
|
+
prefetch: 20
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
hashNameSpace: '{{uuid}}',
|
|
48
|
+
}
|