@gnar-engine/cli 1.0.0 → 1.0.2

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.
Files changed (230) hide show
  1. package/assets/gnar-engine-logo-white.svg +9 -0
  2. package/bootstrap/deploy.localdev.yml +51 -0
  3. package/bootstrap/secrets.localdev.yml +27 -0
  4. package/bootstrap/services/agent/Dockerfile +23 -0
  5. package/bootstrap/services/agent/notes.md +28 -0
  6. package/bootstrap/services/agent/package.json +16 -0
  7. package/bootstrap/services/agent/src/app.js +52 -0
  8. package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
  9. package/bootstrap/services/agent/src/config.js +52 -0
  10. package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
  11. package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
  12. package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
  13. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
  14. package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
  15. package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
  16. package/bootstrap/services/agent/src/services/agent.service.js +259 -0
  17. package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
  18. package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
  19. package/bootstrap/services/control/Dockerfile +23 -0
  20. package/bootstrap/services/control/Dockerfile.prod +37 -0
  21. package/bootstrap/services/control/README.md +25 -0
  22. package/bootstrap/services/control/package.json +16 -0
  23. package/bootstrap/services/control/src/app.js +45 -0
  24. package/bootstrap/services/control/src/commands/control.handler.js +231 -0
  25. package/bootstrap/services/control/src/commands/service.handler.js +81 -0
  26. package/bootstrap/services/control/src/commands/task.handler.js +247 -0
  27. package/bootstrap/services/control/src/config.js +55 -0
  28. package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
  29. package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
  30. package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
  31. package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
  32. package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
  33. package/bootstrap/services/control/src/policies/task.policy.js +53 -0
  34. package/bootstrap/services/control/src/schema/control.schema.js +42 -0
  35. package/bootstrap/services/control/src/services/registry.service.js +83 -0
  36. package/bootstrap/services/control/src/services/reset.service.js +28 -0
  37. package/bootstrap/services/control/src/services/task.service.js +153 -0
  38. package/bootstrap/services/control/src/tests/control.test.js +50 -0
  39. package/bootstrap/services/notification/Dockerfile +23 -0
  40. package/bootstrap/services/notification/Dockerfile.prod +37 -0
  41. package/bootstrap/services/notification/README.md +3 -0
  42. package/bootstrap/services/notification/package.json +34 -0
  43. package/bootstrap/services/notification/src/app.js +51 -0
  44. package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
  45. package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
  46. package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
  47. package/bootstrap/services/notification/src/config.js +15 -0
  48. package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
  49. package/bootstrap/services/notification/src/services/logger.service.js +16 -0
  50. package/bootstrap/services/notification/src/services/ses.service.js +23 -0
  51. package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
  52. package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
  53. package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
  54. package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
  55. package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
  56. package/bootstrap/services/portal/Dockerfile +23 -0
  57. package/bootstrap/services/portal/Dockerfile.remote +40 -0
  58. package/bootstrap/services/portal/README.md +22 -0
  59. package/bootstrap/services/portal/nginx.conf +12 -0
  60. package/bootstrap/services/portal/package.json +59 -0
  61. package/bootstrap/services/portal/public/favicon.ico +0 -0
  62. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  63. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  64. package/bootstrap/services/portal/public/index.html +43 -0
  65. package/bootstrap/services/portal/public/logo192.png +0 -0
  66. package/bootstrap/services/portal/public/logo512.png +0 -0
  67. package/bootstrap/services/portal/public/manifest.json +25 -0
  68. package/bootstrap/services/portal/public/robots.txt +3 -0
  69. package/bootstrap/services/portal/src/App.js +56 -0
  70. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
  71. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
  72. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
  73. package/bootstrap/services/portal/src/assets/activity.svg +3 -0
  74. package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
  75. package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
  76. package/bootstrap/services/portal/src/assets/bin.svg +3 -0
  77. package/bootstrap/services/portal/src/assets/check.svg +3 -0
  78. package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
  79. package/bootstrap/services/portal/src/assets/contact.svg +3 -0
  80. package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
  81. package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
  82. package/bootstrap/services/portal/src/assets/eye.svg +4 -0
  83. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
  84. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
  85. package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
  86. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  87. package/bootstrap/services/portal/src/assets/home.svg +3 -0
  88. package/bootstrap/services/portal/src/assets/link.svg +3 -0
  89. package/bootstrap/services/portal/src/assets/lock.svg +3 -0
  90. package/bootstrap/services/portal/src/assets/package.svg +4 -0
  91. package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
  92. package/bootstrap/services/portal/src/assets/settings.svg +4 -0
  93. package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
  94. package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
  95. package/bootstrap/services/portal/src/assets/user.svg +3 -0
  96. package/bootstrap/services/portal/src/assets/users.svg +3 -0
  97. package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
  98. package/bootstrap/services/portal/src/css/style.css +1007 -0
  99. package/bootstrap/services/portal/src/data/data.js +70 -0
  100. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
  101. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
  102. package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
  103. package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
  104. package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
  105. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
  106. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
  107. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
  108. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
  109. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
  110. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
  111. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
  112. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
  113. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
  114. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
  115. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
  116. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
  117. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
  118. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
  119. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
  120. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
  121. package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
  122. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
  123. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
  124. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
  125. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
  126. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
  127. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
  128. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
  129. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
  130. package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
  131. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
  132. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
  133. package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
  134. package/bootstrap/services/portal/src/features/user/user.less +57 -0
  135. package/bootstrap/services/portal/src/includes/utilities.js +259 -0
  136. package/bootstrap/services/portal/src/index.js +14 -0
  137. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
  138. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
  139. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
  140. package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
  141. package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
  142. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
  143. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
  144. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
  145. package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
  146. package/bootstrap/services/portal/src/pages/login/login.less +10 -0
  147. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
  148. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
  149. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
  150. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
  151. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
  152. package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
  153. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
  154. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
  155. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
  156. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
  157. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
  158. package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
  159. package/bootstrap/services/portal/src/pages/users/users.less +25 -0
  160. package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
  161. package/bootstrap/services/portal/src/store/configureStore.js +12 -0
  162. package/bootstrap/services/portal/src/styles/global.less +159 -0
  163. package/bootstrap/services/portal/src/styles/inputs.less +157 -0
  164. package/bootstrap/services/portal/src/styles/main.less +26 -0
  165. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
  166. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
  167. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
  168. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
  169. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
  170. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
  171. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
  172. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
  173. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
  174. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
  175. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
  176. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
  177. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
  178. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  179. package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
  180. package/bootstrap/services/user/Dockerfile +23 -0
  181. package/bootstrap/services/user/Dockerfile.prod +37 -0
  182. package/bootstrap/services/user/README.md +8 -0
  183. package/bootstrap/services/user/package.json +16 -0
  184. package/bootstrap/services/user/src/app.js +45 -0
  185. package/bootstrap/services/user/src/commands/session.handler.js +23 -0
  186. package/bootstrap/services/user/src/commands/user.handler.js +286 -0
  187. package/bootstrap/services/user/src/config.js +73 -0
  188. package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
  189. package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
  190. package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
  191. package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
  192. package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
  193. package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
  194. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
  195. package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
  196. package/bootstrap/services/user/src/policies/user.policy.js +81 -0
  197. package/bootstrap/services/user/src/schema/user.schema.js +69 -0
  198. package/bootstrap/services/user/src/services/authentication.service.js +127 -0
  199. package/bootstrap/services/user/src/services/session.service.js +58 -0
  200. package/bootstrap/services/user/src/services/user.service.js +130 -0
  201. package/bootstrap/services/user/src/tests/user.test.js +126 -0
  202. package/package.json +3 -7
  203. package/src/agent/agent.client.js +28 -0
  204. package/src/agent/commands.js +48 -0
  205. package/src/cli.js +30 -0
  206. package/src/config.js +8 -0
  207. package/src/control/commands.js +156 -0
  208. package/src/control/control.client.js +127 -0
  209. package/src/dev/commands.js +71 -0
  210. package/src/dev/dev.service.js +320 -0
  211. package/src/engine/infra.js +142 -0
  212. package/src/helpers/helpers.js +63 -0
  213. package/src/profiles/command.js +170 -0
  214. package/src/profiles/profiles.client.js +101 -0
  215. package/src/scaffolder/commands.js +123 -0
  216. package/src/scaffolder/scaffolder.handler.js +252 -0
  217. package/src/services/client.js +174 -0
  218. package/templates/service/Dockerfile.hbs +20 -0
  219. package/templates/service/app.js.hbs +38 -0
  220. package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
  221. package/templates/service/config.js.hbs +48 -0
  222. package/templates/service/controllers/http.controller.js.hbs +87 -0
  223. package/templates/service/controllers/message.controller.js.hbs +51 -0
  224. package/templates/service/db/migrations/01-init.js.hbs +50 -0
  225. package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
  226. package/templates/service/package.json.hbs +18 -0
  227. package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
  228. package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
  229. package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
  230. package/dist/cli.js +0 -18
@@ -0,0 +1,228 @@
1
+ import { commands } from '@gnar-engine/core';
2
+ import { authorise } from '../policies/task.policy.js';
3
+
4
+
5
+ /**
6
+ * HTTP controller
7
+ */
8
+ export const httpController = {
9
+
10
+ /**
11
+ * Schedule a task
12
+ */
13
+ tasksSchedule: {
14
+ method: 'POST',
15
+ url: '/tasks/schedule',
16
+ preHandler: async (request, reply) => authorise.scheduleTaskByApi(request, reply),
17
+ handler: async (request, reply) => {
18
+
19
+ // params from request
20
+ const params = {
21
+ name: request.body.name,
22
+ payload: request.body.payload
23
+ };
24
+
25
+ // execute
26
+ const task = await commands.execute('scheduleTask', params);
27
+
28
+ // handle response
29
+ reply.code(200).send(
30
+ { task: task }
31
+ );
32
+ },
33
+ },
34
+
35
+ /**
36
+ * Execute task (not implemented)
37
+ */
38
+ tasksExecute: {
39
+ method: 'POST',
40
+ url: '/tasks/execute',
41
+ preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
42
+ handler: async (request, reply) => {
43
+
44
+ // handle response
45
+ reply.code(400).send(
46
+ { message: 'Not implemented' }
47
+ );
48
+ },
49
+ },
50
+
51
+ /**
52
+ * Execute task batch
53
+ */
54
+ tasksExecuteBatch: {
55
+ method: 'POST',
56
+ url: '/tasks/execute-batch',
57
+ preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
58
+ handler: async (request, reply) => {
59
+
60
+ // execute
61
+ const errors = await commands.execute('handleTaskBatch', request.body?.status);
62
+
63
+ if (errors && errors.length > 0) {
64
+ // handle response
65
+ reply.code(200).send(
66
+ {
67
+ message: 'Task batch run but had errors',
68
+ errors: errors
69
+ }
70
+ );
71
+ return;
72
+ }
73
+
74
+ // handle response
75
+ reply.code(200).send(
76
+ { message: 'Task batch run with no errors' }
77
+ );
78
+ },
79
+ },
80
+
81
+ /**
82
+ * Get tasks by status
83
+ */
84
+ tasksGet: {
85
+ method: 'GET',
86
+ url: '/tasks/',
87
+ preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
88
+ handler: async (request, reply) => {
89
+
90
+ const status = request.query.status || 'scheduled';
91
+
92
+ // execute
93
+ const tasks = await commands.execute('getTasksByStatus', status);
94
+
95
+ // handle response
96
+ reply.code(200).send(
97
+ {
98
+ status: status,
99
+ tasks: tasks
100
+ }
101
+ );
102
+ },
103
+ },
104
+
105
+ /**
106
+ * Delete failed tasks
107
+ */
108
+ tasksDeleteFailed: {
109
+ method: 'POST',
110
+ url: '/tasks/delete-failed',
111
+ preHandler: async (request, reply) => authorise.executeTaskByApi(request, reply),
112
+ handler: async (request, reply) => {
113
+
114
+ // execute
115
+ const numDeletedTasks = await commands.execute('deleteFailedTasks');
116
+
117
+ // handle response
118
+ reply.code(200).send(
119
+ {
120
+ message: 'Failed tasks deleted',
121
+ numDeletedTasks: numDeletedTasks
122
+ }
123
+ );
124
+ },
125
+ },
126
+
127
+ /**
128
+ * Migrations
129
+ */
130
+ runMigrations: {
131
+ method: 'POST',
132
+ url: '/control/migrations',
133
+ preHandler: async (request, reply) => authorise.runMigrationsByApi(request, reply),
134
+ handler: async (request, reply) => {
135
+
136
+ const params = {
137
+ service: request.body.service || null,
138
+ migration: request.body.migration || null
139
+ };
140
+
141
+ // execute
142
+ await commands.execute('runMigrations', params);
143
+
144
+ // handle response
145
+ reply.code(200).send(
146
+ { message: 'Migrations triggered' }
147
+ );
148
+ },
149
+ },
150
+
151
+ /**
152
+ * Seeders
153
+ */
154
+ runSeeders: {
155
+ method: 'POST',
156
+ url: '/control/seeders',
157
+ preHandler: async (request, reply) => authorise.runSeedersByApi(request, reply),
158
+ handler: async (request, reply) => {
159
+
160
+ const params = {
161
+ service: request.body.service || null
162
+ };
163
+
164
+ // execute
165
+ await commands.execute('runSeeders', params);
166
+
167
+ // handle response
168
+ reply.code(200).send(
169
+ { message: 'Seeders triggered' }
170
+ );
171
+ }
172
+ },
173
+
174
+ /**
175
+ * Reset
176
+ */
177
+ reset: {
178
+ method: 'POST',
179
+ url: '/control/reset',
180
+ preHandler: async (request, reply) => authorise.runResetByApi(request, reply),
181
+ handler: async (request, reply) => {
182
+
183
+ const params = {
184
+ service: request.body.service || null
185
+ };
186
+
187
+ // execute
188
+ await commands.execute('runReset', params);
189
+
190
+ // handle response
191
+ reply.code(200).send(
192
+ { message: 'Reset triggered' }
193
+ );
194
+ }
195
+ },
196
+
197
+ /**
198
+ * Health check
199
+ */
200
+ healthCheck: {
201
+ method: 'GET',
202
+ url: '/control/health',
203
+ handler: async (request, reply) => {
204
+
205
+ // execute
206
+ await commands.execute('runHealthcheck');
207
+
208
+ // handle response
209
+ reply.code(200).send(
210
+ { message: 'health check passed!' }
211
+ );
212
+ }
213
+ },
214
+
215
+ /**
216
+ * ECS health check
217
+ */
218
+ ecsHealthCheck: {
219
+ method: 'GET',
220
+ url: '/control/',
221
+ handler: async (request, reply) => {
222
+ reply.code(200).send(
223
+ { message: 'Server is up' }
224
+ );
225
+ }
226
+ },
227
+
228
+ };
@@ -0,0 +1,40 @@
1
+ import { commands } from '@gnar-engine/core';
2
+
3
+
4
+ /**
5
+ * Message Controller: handlers for incoming service messages
6
+ */
7
+ export const messageHandlers = {
8
+
9
+ registerService: async (payload) => {
10
+ const service = await commands.execute('registerService', {
11
+ service: payload.data.service,
12
+ });
13
+
14
+ return { service };
15
+ },
16
+
17
+ getServices: async (payload) => {
18
+ const services = await commands.execute('getServices', payload.data);
19
+
20
+ return { services };
21
+ },
22
+
23
+ scheduleTask: async (payload) => {
24
+ const task = await commands.execute('scheduleTask', payload.data);
25
+
26
+ return { task };
27
+ },
28
+
29
+ cancelTasks: async (payload) => {
30
+ const tasks = await commands.execute('cancelTasks', payload.data);
31
+
32
+ return { tasks };
33
+ },
34
+
35
+ getManifests: async (payload) => {
36
+ const manifests = await commands.execute('getManifests', payload.data);
37
+
38
+ return { manifests };
39
+ }
40
+ }
@@ -0,0 +1,50 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+
3
+ /**
4
+ * Up
5
+ */
6
+ export const up = async () => {
7
+ await initDatabaseTables();
8
+ }
9
+
10
+ /**
11
+ * Down
12
+ */
13
+ export const down = async () => {
14
+ await dropDatabaseTables();
15
+ }
16
+
17
+ /**
18
+ * Create all tables
19
+ */
20
+ export const initDatabaseTables = async () => {
21
+
22
+ // Migrations table
23
+ logger.info("Creating migrations table");
24
+ const createMigrationsTableQuery = `
25
+ CREATE TABLE migrations (
26
+ id INT AUTO_INCREMENT PRIMARY KEY,
27
+ name VARCHAR(255) NOT NULL UNIQUE,
28
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
29
+ )`;
30
+ await db.query(createMigrationsTableQuery);
31
+
32
+ // Seeders table
33
+ logger.info("Creating seeders table");
34
+ const createSeedersTableQuery = `
35
+ CREATE TABLE seeders (
36
+ id INT AUTO_INCREMENT PRIMARY KEY,
37
+ name VARCHAR(255) NOT NULL UNIQUE,
38
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
39
+ )`;
40
+ await db.query(createSeedersTableQuery);
41
+ }
42
+
43
+ /**
44
+ * Drop all tables
45
+ */
46
+ export const dropDatabaseTables = async () => {
47
+ logger.info('Dropping tables');
48
+ await db.query('DROP TABLE IF EXISTS migrations');
49
+ await db.query('DROP TABLE IF EXISTS seeders');
50
+ }
@@ -0,0 +1,60 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+
3
+ /**
4
+ * Up
5
+ */
6
+ export const up = async () => {
7
+ await initDatabaseTables();
8
+ }
9
+
10
+ /**
11
+ * Down
12
+ */
13
+ export const down = async () => {
14
+ await dropDatabaseTables();
15
+ }
16
+
17
+ /**
18
+ * Create all tables
19
+ */
20
+ export const initDatabaseTables = async () => {
21
+
22
+ // Tasks table
23
+ logger.info('Creating tasks table');
24
+ const createTasksTableQuery = `
25
+ CREATE TABLE tasks (
26
+ id CHAR(36) PRIMARY KEY,
27
+ name VARCHAR(255) NOT NULL,
28
+ payload TEXT,
29
+ status ENUM('scheduled', 'queued', 'completed', 'failed', 'cancelled') DEFAULT 'scheduled',
30
+ scheduled TIMESTAMP,
31
+ recurring_interval ENUM('daily', 'weekly', 'monthly', 'yearly', 'none') DEFAULT 'none',
32
+ recurring_interval_count INT DEFAULT 0,
33
+ handler_service_name VARCHAR(255) NOT NULL,
34
+ handler_name VARCHAR(255) NOT NULL,
35
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
36
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
37
+ )`;
38
+ await db.query(createTasksTableQuery);
39
+
40
+ // Service registry table
41
+ logger.info('Creating service registry table');
42
+ const createServiceRegistryTableQuery = `
43
+ CREATE TABLE service_registry (
44
+ id CHAR(36) PRIMARY KEY,
45
+ name VARCHAR(255) NOT NULL,
46
+ manifest JSON,
47
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
48
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
49
+ )`;
50
+ await db.query(createServiceRegistryTableQuery);
51
+ }
52
+
53
+ /**
54
+ * Drop all tables
55
+ */
56
+ export const dropDatabaseTables = async () => {
57
+ logger.info('Dropping tables');
58
+ await db.query('DROP TABLE IF EXISTS tasks');
59
+ await db.query('DROP TABLE IF EXISTS service_registry');
60
+ }
@@ -0,0 +1,29 @@
1
+ import { logger, db } from '@gnar-engine/core';
2
+
3
+ /**
4
+ * Up
5
+ */
6
+ export const up = async () => {
7
+ await alertTaskTable();
8
+ }
9
+
10
+ /**
11
+ * Down
12
+ */
13
+ export const down = async () => {
14
+
15
+ }
16
+
17
+ /**
18
+ * Add new columns to task table
19
+ */
20
+ export const alertTaskTable = async () => {
21
+ const alterTasksTableQuery = `
22
+ ALTER TABLE tasks
23
+ MODIFY COLUMN recurring_interval ENUM('hourly', 'daily', 'weekly', 'monthly', 'yearly', 'none') DEFAULT 'none',
24
+ ADD COLUMN reschedule_centrally_on_success BOOLEAN DEFAULT FALSE,
25
+ ADD COLUMN reschedule_centrally_on_failure BOOLEAN DEFAULT FALSE,
26
+ ADD COLUMN idempotency_key VARCHAR(255) DEFAULT NULL
27
+ `;
28
+ await db.query(alterTasksTableQuery);
29
+ }
@@ -0,0 +1,53 @@
1
+
2
+ export const authorise = {
3
+
4
+ /**
5
+ * Authorise update product
6
+ */
7
+ scheduleTaskByApi: async (request, reply) => {
8
+ // only service admins can schedule tasks via the API
9
+ if (!request.user || request.user.role !== 'service_admin') {
10
+ reply.code(403).send({error: 'not authorised'});
11
+ }
12
+ },
13
+
14
+ /**
15
+ * Authorise execute task
16
+ */
17
+ executeTaskByApi: async (request, reply) => {
18
+ // only service admins can execute tasks via the API
19
+ if (!request.user || request.user.role !== 'service_admin') {
20
+ reply.code(403).send({error: 'not authorised'});
21
+ }
22
+ },
23
+
24
+ /**
25
+ * Authorise run migrations
26
+ */
27
+ runMigrationsByApi: async (request, reply) => {
28
+ // only service admins can run migrations via the API
29
+ if (!request.user || request.user.role !== 'service_admin') {
30
+ reply.code(403).send({error: 'not authorised'});
31
+ }
32
+ },
33
+
34
+ /**
35
+ * Authorise run seeders
36
+ */
37
+ runSeedersByApi: async (request, reply) => {
38
+ // only service admins can run seeders via the API
39
+ if (!request.user || request.user.role !== 'service_admin') {
40
+ reply.code(403).send({error: 'not authorised'});
41
+ }
42
+ },
43
+
44
+ /**
45
+ * Authorise run reset
46
+ */
47
+ runResetByApi: async (request, reply) => {
48
+ // only service admins can run reset via the API
49
+ if (!request.user || request.user.role !== 'service_admin') {
50
+ reply.code(403).send({error: 'not authorised'});
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,42 @@
1
+ import { schema } from '@gnar-engine/core';
2
+
3
+ // Task schema
4
+ const taskSchema = {
5
+ schemaName: 'controlService.taskSchema',
6
+ schema: {
7
+ type: 'object',
8
+ properties: {
9
+ name: { type: 'string' },
10
+ payload: { type: 'object' },
11
+ status: { type: 'string', enum: ['scheduled'] },
12
+ scheduled: { type: 'string', format: 'mysql-date' },
13
+ recurringInterval: { type: 'string', enum: ['hourly', 'daily', 'weekly', 'monthly', 'yearly'] },
14
+ recurringIntervalCount: { type: 'number' },
15
+ handlerServiceName: { type: 'string' },
16
+ handlerName: { type: 'string' },
17
+ rescheduleCentrallyOnSuccess: { type: 'boolean' },
18
+ rescheduleCentrallyOnFailure: { type: 'boolean' },
19
+ idempotencyKey: { type: 'string' }
20
+ },
21
+ required: ['name', 'payload', 'scheduled', 'handlerServiceName', 'handlerName'],
22
+ additionalProperties: false
23
+ }
24
+ };
25
+
26
+ // Service schema
27
+ const serviceSchema = {
28
+ schemaName: 'controlService.serviceSchema',
29
+ schema: {
30
+ type: 'object',
31
+ properties: {
32
+ name: { type: 'string' },
33
+ manifest: { type: 'object' }
34
+ },
35
+ required: ['name'],
36
+ additionalProperties: false
37
+ }
38
+ };
39
+
40
+ // Compile schemas
41
+ export const validateTask = schema.compile(taskSchema);
42
+ export const validateService = schema.compile(serviceSchema);
@@ -0,0 +1,83 @@
1
+ import { db, utils, logger } from '@gnar-engine/core';
2
+
3
+
4
+ /**
5
+ * Registry Service
6
+ */
7
+ export const registry = {
8
+
9
+ // register service
10
+ registerService: async ({name, manifest}) => {
11
+ try {
12
+ const [result] = await db.execute(
13
+ 'INSERT INTO `service_registry` (`id`, `name`, `manifest`) VALUES (?, ?, ?)',
14
+ [utils.uuid(), name, manifest]
15
+ );
16
+
17
+ return result.insertId;
18
+ } catch (error) {
19
+ logger.error("Error registering service: " + error);
20
+ throw error;
21
+ }
22
+ },
23
+
24
+ updateService: async ({name, manifest}) => {
25
+ try {
26
+ const [result] = await db.execute(
27
+ 'UPDATE `service_registry` SET `manifest` = ?, `updated_at` = CURRENT_TIMESTAMP WHERE `name` = ?',
28
+ [manifest, name]
29
+ );
30
+ return result.affectedRows;
31
+ } catch (error) {
32
+ logger.error("Error updating service: " + error);
33
+ throw error;
34
+ }
35
+ },
36
+
37
+ // get services
38
+ getServices: async () => {
39
+ try {
40
+ const [result] = await db.execute(
41
+ 'SELECT name FROM `service_registry`'
42
+ );
43
+
44
+ return result;
45
+ } catch (error) {
46
+ logger.error("Error getting services: " + error);
47
+ throw error;
48
+ }
49
+ },
50
+
51
+ /**
52
+ * Get services with manifests
53
+ */
54
+ getServicesWithManifests: async () => {
55
+ try {
56
+ const [result] = await db.execute(
57
+ 'SELECT * FROM `service_registry`'
58
+ );
59
+
60
+ return result;
61
+ } catch (error) {
62
+ logger.error("Error getting services: " + error);
63
+ throw error;
64
+ }
65
+ },
66
+
67
+
68
+ /**
69
+ * Get manifests
70
+ */
71
+ getManifests: async () => {
72
+ try {
73
+ const [result] = await db.execute(
74
+ 'SELECT manifest FROM `service_registry`'
75
+ );
76
+
77
+ return result;
78
+ } catch (error) {
79
+ logger.error("Error getting manifests: " + error);
80
+ throw error;
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,28 @@
1
+ import { logger } from '@gnar-engine/core';
2
+
3
+
4
+ /**
5
+ * Registry Service
6
+ */
7
+ export const reset = {
8
+
9
+ // drop MYSQL databases
10
+ dropMysqlDatabases: async () => {
11
+ try {
12
+ throw new Error("Not implemented");
13
+ } catch (error) {
14
+ logger.error("Error resetting MYSQL: " + error);
15
+ throw error;
16
+ }
17
+ },
18
+
19
+ // drop all mongodb collections
20
+ dropMongoCollections: async () => {
21
+ try {
22
+ throw new Error("Not implemented");
23
+ } catch (error) {
24
+ logger.error("Error resetting MYSQL: " + error);
25
+ throw error;
26
+ }
27
+ }
28
+ }