@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,156 @@
|
|
|
1
|
+
// control/commands.js
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { control } from './control.client.js';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
|
|
6
|
+
export function registerControlCommands(program) {
|
|
7
|
+
const controlCmd = new Command('control').description('🎛️ Control related commands');
|
|
8
|
+
|
|
9
|
+
controlCmd
|
|
10
|
+
.command('migrate')
|
|
11
|
+
.description('📦 Run migrations')
|
|
12
|
+
.option('-a, --all', 'Run all migrations')
|
|
13
|
+
.option('-s, --service <service>', 'Run migrations for a specific service')
|
|
14
|
+
.option('-m, --migration <migration>', 'Run a specific migration (must also include service)')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
let response = {};
|
|
17
|
+
|
|
18
|
+
if (options.all) {
|
|
19
|
+
console.log('📦 Running all migrations...');
|
|
20
|
+
response = await control.runMigrations();
|
|
21
|
+
} else {
|
|
22
|
+
response.error = 'No options provided';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (response.error) {
|
|
26
|
+
console.error('❌ ' + response.error);
|
|
27
|
+
} else {
|
|
28
|
+
console.log('✅ ' + response.message);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
controlCmd
|
|
33
|
+
.command('seed')
|
|
34
|
+
.description('🌱 Run seeders')
|
|
35
|
+
.option('-a, --all', 'Run all seeders')
|
|
36
|
+
.option('-s, --service <service>', 'Run seeders for a specific service')
|
|
37
|
+
.option('-S, --seed <seed>', 'Run a specific seed (must also include service)')
|
|
38
|
+
.action(async (options) => {
|
|
39
|
+
let response = {};
|
|
40
|
+
|
|
41
|
+
if (options.all) {
|
|
42
|
+
console.log('🌱 Running all seeders...');
|
|
43
|
+
response = await control.runSeeders();
|
|
44
|
+
} else {
|
|
45
|
+
response.error = 'No options provided';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (response.error) {
|
|
49
|
+
console.error('❌ ' + response.error);
|
|
50
|
+
} else {
|
|
51
|
+
console.log('✅ ' + response.message);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
controlCmd
|
|
56
|
+
.command('reset')
|
|
57
|
+
.description('📦 Full Reset. Drop all data to return to initial state with root user only (development mode only)')
|
|
58
|
+
.option('-a, --all', 'Reset everything')
|
|
59
|
+
.option('-s, --service <service>', 'Run migrations for a specific service')
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
let response = {};
|
|
62
|
+
|
|
63
|
+
if (options.all) {
|
|
64
|
+
const confirmation = await inquirer.prompt([
|
|
65
|
+
{
|
|
66
|
+
type: 'confirm',
|
|
67
|
+
name: 'confirmReset',
|
|
68
|
+
message: '⚠️ Are you sure you want to run a full reset? This will delete all data.',
|
|
69
|
+
default: false,
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
if (!confirmation.confirmReset) {
|
|
74
|
+
console.log('❌ Reset cancelled.');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log('📦 Running full reset...');
|
|
79
|
+
response = await control.runReset();
|
|
80
|
+
} else {
|
|
81
|
+
response.error = 'No options provided';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (response.error) {
|
|
85
|
+
console.error('❌ ' + response.error);
|
|
86
|
+
} else {
|
|
87
|
+
console.log('✅ ' + response.message);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
controlCmd
|
|
92
|
+
.command('get-tasks')
|
|
93
|
+
.description('🛠️ Get tasks')
|
|
94
|
+
.option('-s, --status <status>', 'Task status (default: scheduled)')
|
|
95
|
+
.action(async (options) => {
|
|
96
|
+
if (!options.status) options.status = 'scheduled';
|
|
97
|
+
|
|
98
|
+
console.log('🛠️ Getting tasks with status: ' + options.status);
|
|
99
|
+
const response = await control.getTasks(options.status);
|
|
100
|
+
|
|
101
|
+
if (response.error) {
|
|
102
|
+
console.error('❌ ' + response.error);
|
|
103
|
+
} else {
|
|
104
|
+
console.log(JSON.stringify(response.tasks, null, 2));
|
|
105
|
+
console.log('✅ Got tasks ' + response.tasks.length);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
controlCmd
|
|
110
|
+
.command('execute-tasks')
|
|
111
|
+
.description('🛠️ Execute tasks')
|
|
112
|
+
.option('-s, --status <status>', 'Task status (default: scheduled)')
|
|
113
|
+
.action(async (options) => {
|
|
114
|
+
if (!options.status) options.status = 'scheduled';
|
|
115
|
+
|
|
116
|
+
console.log('🛠️ Executing tasks with status: ' + options.status);
|
|
117
|
+
const response = await control.handleTaskBatch(options.status);
|
|
118
|
+
|
|
119
|
+
if (response.error) {
|
|
120
|
+
console.error('❌ ' + response.error);
|
|
121
|
+
} else {
|
|
122
|
+
console.log('✅ ' + response.message);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
controlCmd
|
|
127
|
+
.command('delete-task')
|
|
128
|
+
.description('🛠️ Delete task')
|
|
129
|
+
.requiredOption('-id, --id <id>', 'Task ID')
|
|
130
|
+
.action(async (options) => {
|
|
131
|
+
console.log('🛠️ Deleting task with id: ' + options.id);
|
|
132
|
+
const response = await control.deleteTask(options.id);
|
|
133
|
+
|
|
134
|
+
if (response.error) {
|
|
135
|
+
console.error('❌ ' + response.error);
|
|
136
|
+
} else {
|
|
137
|
+
console.log('✅ ' + response.numDeletedTasks + ' ' + response.message);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
controlCmd
|
|
142
|
+
.command('delete-failed-tasks')
|
|
143
|
+
.description('🛠️ Delete failed tasks')
|
|
144
|
+
.action(async () => {
|
|
145
|
+
console.log('🛠️ Deleting failed tasks');
|
|
146
|
+
const response = await control.deleteFailedTasks();
|
|
147
|
+
|
|
148
|
+
if (response.error) {
|
|
149
|
+
console.error('❌ ' + response.error);
|
|
150
|
+
} else {
|
|
151
|
+
console.log('✅ ' + response.numDeletedTasks + ' ' + response.message);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
program.addCommand(controlCmd);
|
|
156
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import client, { initAxiosClient } from '../services/client.js';
|
|
2
|
+
import { profiles } from "../profiles/profiles.client.js";
|
|
3
|
+
|
|
4
|
+
export const control = {
|
|
5
|
+
|
|
6
|
+
// Run all migrations
|
|
7
|
+
runMigrations: async () => {
|
|
8
|
+
try {
|
|
9
|
+
await initAxiosClient();
|
|
10
|
+
const response = await client.post('/control/migrations', {});
|
|
11
|
+
|
|
12
|
+
if (response.status !== 200) {
|
|
13
|
+
throw new Error("Failed to run migrations");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return response.data;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return {error: "Migrations failed: " + error};
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Run seeders
|
|
23
|
+
runSeeders: async () => {
|
|
24
|
+
try {
|
|
25
|
+
await initAxiosClient();
|
|
26
|
+
const response = await client.post('/control/seeders', {});
|
|
27
|
+
|
|
28
|
+
if (response.status !== 200) {
|
|
29
|
+
throw new Error("Failed to run seeders");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return response.data;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return {error: "Seeders failed: " + error};
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// Run full reset
|
|
39
|
+
runReset: async () => {
|
|
40
|
+
try {
|
|
41
|
+
await initAxiosClient();
|
|
42
|
+
const response = await client.post('/control/reset', {});
|
|
43
|
+
|
|
44
|
+
if (response.status !== 200) {
|
|
45
|
+
throw new Error("Failed to run reset");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return response.data;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return {error: "Reset failed: " + error};
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Get tasks
|
|
55
|
+
getTasks: async (status) => {
|
|
56
|
+
try {
|
|
57
|
+
await initAxiosClient();
|
|
58
|
+
const response = await client.get(`/tasks/?status=${status}`);
|
|
59
|
+
|
|
60
|
+
if (response.status !== 200) {
|
|
61
|
+
throw new Error("Failed to get tasks");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return response.data;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return {error: "Failed to get tasks: " + error};
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
// Execute tasks
|
|
71
|
+
handleTaskBatch: async (status) => {
|
|
72
|
+
try {
|
|
73
|
+
await initAxiosClient();
|
|
74
|
+
console.log(`Executing task batch...`);
|
|
75
|
+
const response = await client.post(`/tasks/execute-batch`, {
|
|
76
|
+
status: status
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (response.status !== 200) {
|
|
80
|
+
throw new Error("Failed to execute task batch");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (response.data.errors && response.data.errors.length > 0) {
|
|
84
|
+
throw new Error("Task batch run but had errors: " + JSON.stringify(response.data.errors, null, 2));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return response.data;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return {error: "Task execution failed: " + error};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
// Delete task by id
|
|
95
|
+
deleteTask: async (id) => {
|
|
96
|
+
try {
|
|
97
|
+
await initAxiosClient();
|
|
98
|
+
console.log(`Deleting task with id ${id}...`);
|
|
99
|
+
const response = await client.delete(`/tasks/${id}`);
|
|
100
|
+
|
|
101
|
+
if (response.status !== 200) {
|
|
102
|
+
throw new Error("Failed to delete task");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return response.data;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return {error: "Failed to delete task: " + error};
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// Delete failed tasks
|
|
112
|
+
deleteFailedTasks: async () => {
|
|
113
|
+
try {
|
|
114
|
+
await initAxiosClient();
|
|
115
|
+
console.log(`Deleting failed tasks...`);
|
|
116
|
+
const response = await client.post(`/tasks/delete-failed`, {});
|
|
117
|
+
|
|
118
|
+
if (response.status !== 200) {
|
|
119
|
+
throw new Error("Failed to delete failed tasks");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return response.data;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
return {error: "Failed to delete failed tasks: " + error};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// control/commands.js
|
|
2
|
+
import { Command, Option } from 'commander';
|
|
3
|
+
import { profiles } from '../profiles/profiles.client.js';
|
|
4
|
+
import { up, down } from './dev.service.js';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
export function registerDevCommands(program) {
|
|
8
|
+
const devCmd = new Command('dev').description('🛠️ Start Gnar Engine Development Environment');
|
|
9
|
+
|
|
10
|
+
devCmd
|
|
11
|
+
.command('up')
|
|
12
|
+
.description('🛠️ Up Development Containers')
|
|
13
|
+
.option('-b, --build', 'Ruild without cache')
|
|
14
|
+
.option('-d, --detach', 'Run containers in background')
|
|
15
|
+
.addOption(new Option('--core-dev').hideHelp())
|
|
16
|
+
.action(async (options) => {
|
|
17
|
+
let response = {};
|
|
18
|
+
|
|
19
|
+
// Get active profile directory
|
|
20
|
+
const { profile: activeProfile } = profiles.getActiveProfile();
|
|
21
|
+
|
|
22
|
+
if (!activeProfile) {
|
|
23
|
+
response.error = 'No active profile found';
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Change to the active profile directory
|
|
28
|
+
const projectDir = activeProfile.PROJECT_DIR;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
up({
|
|
32
|
+
projectDir: projectDir,
|
|
33
|
+
build: options.build || false,
|
|
34
|
+
detach: options.detach || false,
|
|
35
|
+
coreDev: options.coreDev || false
|
|
36
|
+
});
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.error("❌ Error running containers:", err.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
devCmd
|
|
44
|
+
.command('down')
|
|
45
|
+
.description('🛠️ Down Development Containers')
|
|
46
|
+
.option('-a, --all-containers', 'Stop all running containers (not just Gnar Engine ones)')
|
|
47
|
+
.action(async (options) => {
|
|
48
|
+
// Get active profile directory
|
|
49
|
+
const { profile: activeProfile } = profiles.getActiveProfile();
|
|
50
|
+
|
|
51
|
+
if (!activeProfile) {
|
|
52
|
+
console.error('No active profile found');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Change to the active profile directory
|
|
57
|
+
const projectDir = activeProfile.PROJECT_DIR;
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
down({
|
|
61
|
+
projectDir: projectDir,
|
|
62
|
+
allContainers: options.allContainers || false
|
|
63
|
+
});
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.error("❌ Error running containers:", err.message);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
program.addCommand(devCmd);
|
|
71
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import Docker from "dockerode";
|
|
3
|
+
import process from "process";
|
|
4
|
+
import fs from "fs/promises";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import { gnarEngineCliConfig } from "../config.js";
|
|
8
|
+
|
|
9
|
+
const docker = new Docker();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Start the application locally
|
|
13
|
+
* - Creates a dynamic docker-compose file based on deploy.localdev.yml and secrets.localdev.yml
|
|
14
|
+
* - Runs docker-compose up
|
|
15
|
+
*
|
|
16
|
+
* @param {object} options
|
|
17
|
+
* @param {string} options.projectDir - The project directory
|
|
18
|
+
* @param {boolean} [options.build=false] - Whether to re-build images
|
|
19
|
+
* @param {boolean} [options.detached=false] - Whether to run containers in background
|
|
20
|
+
* @param {boolean} [options.coreDev=false] - Whether to run in core development mode (requires access to core source)
|
|
21
|
+
*/
|
|
22
|
+
export async function up({ projectDir, build = false, detached = false, coreDev = false }) {
|
|
23
|
+
// parse config
|
|
24
|
+
const configPath = path.join(projectDir, "deploy.localdev.yml");
|
|
25
|
+
const secretsPath = path.join(projectDir, "secrets.localdev.yml");
|
|
26
|
+
|
|
27
|
+
const parsedConfig = yaml.load(await fs.readFile(configPath, "utf8"));
|
|
28
|
+
const parsedSecrets = yaml.load(await fs.readFile(secretsPath, "utf8"));
|
|
29
|
+
|
|
30
|
+
// assert .gnarengine directory in projectDir
|
|
31
|
+
const gnarHiddenDir = path.join(projectDir, ".gnarengine");
|
|
32
|
+
await assertGnarEngineHiddenDir(gnarHiddenDir);
|
|
33
|
+
|
|
34
|
+
// create nginx.conf dynamically from configPath
|
|
35
|
+
const nginxConfPath = path.join(gnarHiddenDir, "nginx", "nginx.conf");
|
|
36
|
+
const nginxConf = await createDynamicNginxConf({
|
|
37
|
+
config: parsedConfig.config
|
|
38
|
+
});
|
|
39
|
+
await fs.writeFile(nginxConfPath, nginxConf);
|
|
40
|
+
|
|
41
|
+
// create docker-compose.yml dynamically from parsed config and secrets
|
|
42
|
+
const dockerComposePath = path.join(gnarHiddenDir, "docker-compose.dev.yml");
|
|
43
|
+
const dockerCompose = await createDynamicDockerCompose({
|
|
44
|
+
config: parsedConfig.config,
|
|
45
|
+
secrets: parsedSecrets,
|
|
46
|
+
gnarHiddenDir: gnarHiddenDir,
|
|
47
|
+
projectDir: projectDir,
|
|
48
|
+
coreDev: coreDev
|
|
49
|
+
});
|
|
50
|
+
await fs.writeFile(dockerComposePath, yaml.dump(dockerCompose));
|
|
51
|
+
|
|
52
|
+
// up docker-compose
|
|
53
|
+
const args = ["-f", dockerComposePath, "up"];
|
|
54
|
+
|
|
55
|
+
if (build) {
|
|
56
|
+
args.push("--build");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (detached) {
|
|
60
|
+
args.push("-d");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const processRef = spawn(
|
|
64
|
+
"docker-compose",
|
|
65
|
+
args,
|
|
66
|
+
{
|
|
67
|
+
cwd: projectDir,
|
|
68
|
+
stdio: "inherit",
|
|
69
|
+
shell: "/bin/sh"
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// handle exit
|
|
74
|
+
const exitCode = await new Promise((resolve) => {
|
|
75
|
+
processRef.on("close", resolve);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
if (exitCode !== 0) {
|
|
79
|
+
throw new Error(`docker-compose up exited with code ${exitCode}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Down the containers
|
|
85
|
+
*
|
|
86
|
+
* @param {object} options
|
|
87
|
+
* @param {string} options.projectDir - The project directory
|
|
88
|
+
* @param {boolean} [options.allContainers=false] - Stop all running containers (not just Gnar Engine ones)
|
|
89
|
+
*/
|
|
90
|
+
export async function down({ projectDir, allContainers = false }) {
|
|
91
|
+
// list all containers
|
|
92
|
+
const containers = await docker.listContainers();
|
|
93
|
+
|
|
94
|
+
// filter containers by image name
|
|
95
|
+
if (!allContainers) {
|
|
96
|
+
const containers = containers.filter(c => c.Image.includes("ge-dev"));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (containers.length === 0) {
|
|
100
|
+
console.log("No running containers found.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log('Stopping containers...');
|
|
105
|
+
containers.forEach(c => {
|
|
106
|
+
console.log(` - ${c.Names[0]} (${c.Id})`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// stop each container
|
|
110
|
+
await Promise.all(
|
|
111
|
+
containers.map(c => {
|
|
112
|
+
const container = docker.getContainer(c.Id);
|
|
113
|
+
return container.stop().catch(err => {
|
|
114
|
+
console.error(`Failed to stop ${c.Names[0]}: ${err.message}`);
|
|
115
|
+
});
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create dynamic nginx.conf file for running application locally
|
|
122
|
+
*
|
|
123
|
+
* @param {object} config
|
|
124
|
+
* @param {string} outputPath - where to write nginx.conf
|
|
125
|
+
*/
|
|
126
|
+
export async function createDynamicNginxConf({ config, outputPath }) {
|
|
127
|
+
// Start with the static parts of nginx.conf
|
|
128
|
+
let nginxConf = `
|
|
129
|
+
http {
|
|
130
|
+
server {
|
|
131
|
+
listen 80;
|
|
132
|
+
server_name ${config.namespace};
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
// Loop over each service
|
|
136
|
+
for (const service of config.services || []) {
|
|
137
|
+
const serviceName = service.name;
|
|
138
|
+
const paths = service.listener_rules?.paths || [];
|
|
139
|
+
const containerPort = service.ports && service.ports.length > 0 ? service.ports[0].split(':')[1] : '3000';
|
|
140
|
+
|
|
141
|
+
for (const p of paths) {
|
|
142
|
+
// normalize path without trailing slash
|
|
143
|
+
const cleanPath = p.replace(/\/+$/, '');
|
|
144
|
+
|
|
145
|
+
// build location block
|
|
146
|
+
nginxConf += `
|
|
147
|
+
# ${serviceName} service
|
|
148
|
+
location ${cleanPath} {
|
|
149
|
+
rewrite ^${cleanPath}$ ${cleanPath}/ break;
|
|
150
|
+
proxy_pass http://${serviceName}-service:${containerPort}${cleanPath};
|
|
151
|
+
}
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Close server and http blocks
|
|
157
|
+
nginxConf += `
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
return nginxConf;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Create dynamic docker compose file for running application locally
|
|
167
|
+
*
|
|
168
|
+
* @param {object} config
|
|
169
|
+
* @param {object} secrets
|
|
170
|
+
* @param {string} gnarHiddenDir
|
|
171
|
+
* @param {string} projectDir
|
|
172
|
+
* @param {boolean} coreDev - Whether to volume mount the core source code
|
|
173
|
+
*/
|
|
174
|
+
async function createDynamicDockerCompose({ config, secrets, gnarHiddenDir, projectDir, coreDev = false }) {
|
|
175
|
+
let mysqlPortsCounter = 3306;
|
|
176
|
+
let mongoPortsCounter = 27017;
|
|
177
|
+
const services = {};
|
|
178
|
+
|
|
179
|
+
// nginx
|
|
180
|
+
services['nginx'] = {
|
|
181
|
+
image: 'nginx:latest',
|
|
182
|
+
container_name: `ge-${config.environment}-${config.namespace}-nginx`,
|
|
183
|
+
ports: [
|
|
184
|
+
"80:80",
|
|
185
|
+
"443:443"
|
|
186
|
+
],
|
|
187
|
+
volumes: [
|
|
188
|
+
`${gnarHiddenDir}/nginx/nginx.conf:/etc/nginx/nginx.conf`
|
|
189
|
+
],
|
|
190
|
+
restart: 'always'
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// rabbit
|
|
194
|
+
services['rabbitmq'] = {
|
|
195
|
+
image: 'rabbitmq:management',
|
|
196
|
+
container_name: `ge-${config.environment}-${config.namespace}-rabbitmq`,
|
|
197
|
+
ports: [
|
|
198
|
+
"5672:5672",
|
|
199
|
+
"15672:15672"
|
|
200
|
+
],
|
|
201
|
+
environment: {
|
|
202
|
+
RABBITMQ_DEFAULT_USER: secrets.global.RABBITMQ_USER || '',
|
|
203
|
+
RABBITMQ_DEFAULT_PASS: secrets.global.RABBITMQ_PASS || ''
|
|
204
|
+
},
|
|
205
|
+
restart: 'always'
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// services
|
|
209
|
+
for (const svc of config.services) {
|
|
210
|
+
|
|
211
|
+
// env variables
|
|
212
|
+
const serviceEnvVars = secrets.services?.[svc.name] || {};
|
|
213
|
+
const localisedServiceEnvVars = {};
|
|
214
|
+
|
|
215
|
+
for (const [key, value] of Object.entries(serviceEnvVars)) {
|
|
216
|
+
localisedServiceEnvVars[svc.name.toUpperCase() + '_' + key] = value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const env = {
|
|
220
|
+
...(secrets.global || {}),
|
|
221
|
+
...(localisedServiceEnvVars || {})
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// service block
|
|
225
|
+
services[`${svc.name}-service`] = {
|
|
226
|
+
container_name: `ge-${config.environment}-${config.namespace}-${svc.name}`,
|
|
227
|
+
image: `ge-${config.environment}-${config.namespace}-${svc.name}`,
|
|
228
|
+
build: {
|
|
229
|
+
context: projectDir,
|
|
230
|
+
dockerfile: `./services/${svc.name}/Dockerfile`
|
|
231
|
+
},
|
|
232
|
+
command: svc.command || [],
|
|
233
|
+
environment: env,
|
|
234
|
+
ports: svc.ports || [],
|
|
235
|
+
depends_on: svc.depends_on || [],
|
|
236
|
+
volumes: [
|
|
237
|
+
`${projectDir}/services/${svc.name}/src:/usr/gnar_engine/app/src`
|
|
238
|
+
],
|
|
239
|
+
restart: 'always'
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// add the core source code mount if in coreDeve mode
|
|
243
|
+
if (coreDev) {
|
|
244
|
+
services[`${svc.name}-service`].volumes.push(`../../../gnar-engine-core:${gnarEngineCliConfig.corePath}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// add a mysql instance if required
|
|
248
|
+
if (
|
|
249
|
+
serviceEnvVars.MYSQL_HOST &&
|
|
250
|
+
serviceEnvVars.MYSQL_DATABASE &&
|
|
251
|
+
serviceEnvVars.MYSQL_USER &&
|
|
252
|
+
serviceEnvVars.MYSQL_PASSWORD &&
|
|
253
|
+
serviceEnvVars.MYSQL_RANDOM_ROOT_PASSWORD
|
|
254
|
+
) {
|
|
255
|
+
services[`${svc.name}-db`] = {
|
|
256
|
+
container_name: `ge-${config.environment}-${config.namespace}-${svc.name}-db`,
|
|
257
|
+
image: 'mysql',
|
|
258
|
+
ports: [
|
|
259
|
+
`${mysqlPortsCounter}:${mysqlPortsCounter}`
|
|
260
|
+
],
|
|
261
|
+
restart: 'always',
|
|
262
|
+
environment: {
|
|
263
|
+
MYSQL_HOST: serviceEnvVars.MYSQL_HOST,
|
|
264
|
+
MYSQL_DATABASE: serviceEnvVars.MYSQL_DATABASE,
|
|
265
|
+
MYSQL_USER: serviceEnvVars.MYSQL_USER,
|
|
266
|
+
MYSQL_PASSWORD: serviceEnvVars.MYSQL_PASSWORD,
|
|
267
|
+
MYSQL_RANDOM_ROOT_PASSWORD: serviceEnvVars.MYSQL_RANDOM_ROOT_PASSWORD,
|
|
268
|
+
},
|
|
269
|
+
volumes: [
|
|
270
|
+
`${gnarHiddenDir}/data/${svc.name}-db-data:/var/lib/mysql`
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// increment mysql port for next service as required
|
|
275
|
+
mysqlPortsCounter++;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// add a mongodb instance if required
|
|
279
|
+
if (
|
|
280
|
+
serviceEnvVars.MONGO_URL &&
|
|
281
|
+
serviceEnvVars.MONGO_ROOT_PASSWORD &&
|
|
282
|
+
serviceEnvVars.MONGO_USER &&
|
|
283
|
+
serviceEnvVars.MONGO_PASSWORD
|
|
284
|
+
) {
|
|
285
|
+
services[`${svc.name}-mongo`] = {
|
|
286
|
+
container_name: `ge-${config.environment}-${config.namespace}-${svc.name}-mongo`,
|
|
287
|
+
image: `ge-${config.environment}-${config.namespace}-${svc.name}-mongo`,
|
|
288
|
+
ports: [
|
|
289
|
+
`${mongoPortsCounter}:${mongoPortsCounter}`
|
|
290
|
+
],
|
|
291
|
+
restart: 'always',
|
|
292
|
+
environment: {
|
|
293
|
+
[`${svc.name.toUpperCase()}_MONGO_URL`]: serviceEnvVars.MONGO_URL,
|
|
294
|
+
[`${svc.name.toUpperCase()}_MONGO_ROOT_PASSWORD`]: serviceEnvVars.MONGO_ROOT_PASSWORD,
|
|
295
|
+
[`${svc.name.toUpperCase()}_MONGO_USER`]: serviceEnvVars.MONGO_USER,
|
|
296
|
+
[`${svc.name.toUpperCase()}_MONGO_PASSWORD`]: serviceEnvVars.MONGO_PASSWORD,
|
|
297
|
+
},
|
|
298
|
+
volumes: [
|
|
299
|
+
`${gnarHiddenDir}/Data/${svc.name}-mongo-data:/data/db`
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// increment mongo port for next service as required
|
|
304
|
+
mongoPortsCounter++;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
version: "3.9",
|
|
311
|
+
services
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Assert the .gnarengine directory in the project directory
|
|
317
|
+
*/
|
|
318
|
+
async function assertGnarEngineHiddenDir(gnarHiddenDir) {
|
|
319
|
+
await fs.mkdir(gnarHiddenDir, { recursive: true });
|
|
320
|
+
}
|