@gnar-engine/cli 1.0.3 → 1.0.5

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 (259) hide show
  1. package/bootstrap/deploy.localdev.yml +44 -30
  2. package/bootstrap/secrets.localdev.yml +20 -14
  3. package/bootstrap/services/control/src/config.js +4 -0
  4. package/bootstrap/services/{agent → page}/Dockerfile +3 -3
  5. package/bootstrap/services/page/package.json +16 -0
  6. package/bootstrap/services/page/src/app.js +50 -0
  7. package/bootstrap/services/page/src/commands/block.handler.js +94 -0
  8. package/bootstrap/services/page/src/commands/page.handler.js +167 -0
  9. package/bootstrap/services/page/src/config.js +62 -0
  10. package/bootstrap/services/page/src/controllers/block.http.controller.js +87 -0
  11. package/bootstrap/services/page/src/controllers/message.controller.js +51 -0
  12. package/bootstrap/services/page/src/controllers/page.http.controller.js +89 -0
  13. package/bootstrap/services/page/src/policies/block.policy.js +50 -0
  14. package/bootstrap/services/page/src/policies/page.policy.js +49 -0
  15. package/bootstrap/services/page/src/schema/page.schema.js +139 -0
  16. package/bootstrap/services/page/src/services/block.service.js +83 -0
  17. package/bootstrap/services/page/src/services/page.service.js +83 -0
  18. package/bootstrap/services/portal/Dockerfile +7 -10
  19. package/bootstrap/services/portal/README.md +66 -15
  20. package/bootstrap/services/portal/index.html +13 -0
  21. package/bootstrap/services/portal/nginx.conf +5 -12
  22. package/bootstrap/services/portal/package.json +27 -53
  23. package/bootstrap/services/portal/public/vite.svg +1 -0
  24. package/bootstrap/services/portal/react-router.config.js +7 -0
  25. package/bootstrap/services/portal/src/App.jsx +16 -0
  26. package/bootstrap/services/portal/src/assets/gnar-engine-white-logo.svg +9 -0
  27. package/bootstrap/services/portal/src/assets/icon-agent.svg +6 -0
  28. package/bootstrap/services/portal/src/assets/icon-cog.svg +4 -0
  29. package/bootstrap/services/portal/src/assets/icon-delete.svg +3 -0
  30. package/bootstrap/services/portal/src/assets/icon-home.svg +3 -0
  31. package/bootstrap/services/portal/src/assets/icon-padlock.svg +3 -0
  32. package/bootstrap/services/portal/src/assets/icon-page.svg +6 -0
  33. package/bootstrap/services/portal/src/assets/icon-reports.svg +3 -0
  34. package/bootstrap/services/portal/src/assets/icon-user.svg +3 -0
  35. package/bootstrap/services/portal/src/assets/icon-users.svg +3 -0
  36. package/bootstrap/services/portal/src/assets/login-green-rad-back-1.jpg +0 -0
  37. package/bootstrap/services/portal/src/assets/react.svg +1 -0
  38. package/bootstrap/services/portal/src/components/CrudList/CrudList.jsx +85 -0
  39. package/bootstrap/services/portal/src/components/CrudList/CrudList.less +59 -0
  40. package/bootstrap/services/portal/src/{ui/customSelect → components/CustomSelect}/CustomSelect.jsx +21 -3
  41. package/bootstrap/services/portal/src/components/LoginForm/LoginForm.jsx +58 -0
  42. package/bootstrap/services/portal/src/components/PageBlockSwitch/PageBlockSwitch.jsx +129 -0
  43. package/bootstrap/services/portal/src/components/Sidebar/Sidebar.jsx +33 -0
  44. package/bootstrap/services/portal/src/components/Sidebar/Sidebar.less +37 -0
  45. package/bootstrap/services/portal/src/components/Topbar/Topbar.jsx +19 -0
  46. package/bootstrap/services/portal/src/components/Topbar/Topbar.less +22 -0
  47. package/bootstrap/services/portal/src/components/UserInfo/UserInfo.jsx +33 -0
  48. package/bootstrap/services/portal/src/components/UserInfo/UserInfo.less +21 -0
  49. package/bootstrap/services/portal/src/css/style.css +446 -742
  50. package/bootstrap/services/portal/src/data/pages.data.js +10 -0
  51. package/bootstrap/services/portal/src/elements/CustomSelect/CustomSelect.jsx +65 -0
  52. package/bootstrap/services/portal/src/{ui/customSelect/customSelect.less → elements/CustomSelect/CustomSelect.less} +17 -7
  53. package/bootstrap/services/portal/src/elements/ImageInput/ImageInput.jsx +115 -0
  54. package/bootstrap/services/portal/src/elements/ImageInput/ImageInput.less +43 -0
  55. package/bootstrap/services/portal/src/elements/ImageMultiInput/ImageMultiInput.jsx +124 -0
  56. package/bootstrap/services/portal/src/elements/ImageMultiInput/ImageMultiInput.less +0 -0
  57. package/bootstrap/services/portal/src/elements/Repeater/Repeater.jsx +52 -0
  58. package/bootstrap/services/portal/src/elements/Repeater/Repeater.less +70 -0
  59. package/bootstrap/services/portal/src/elements/RichTextInput/RichTextInput.jsx +18 -0
  60. package/bootstrap/services/portal/src/elements/RichTextInput/RichTextInput.less +37 -0
  61. package/bootstrap/services/portal/src/elements/SaveButton/SaveButton.jsx +45 -0
  62. package/bootstrap/services/portal/src/elements/SelectRepeater/SelectRepeater.jsx +63 -0
  63. package/bootstrap/services/portal/src/elements/SelectRepeater/SelectRepeater.less +23 -0
  64. package/bootstrap/services/portal/src/elements/TextInput/TextInput.jsx +17 -0
  65. package/bootstrap/services/portal/src/layouts/Card/Card.jsx +15 -0
  66. package/bootstrap/services/portal/src/layouts/PortalLayout/PortalLayout.jsx +29 -0
  67. package/bootstrap/services/portal/src/layouts/PortalLayout/PortalLayout.less +49 -0
  68. package/bootstrap/services/portal/src/main.jsx +51 -0
  69. package/bootstrap/services/portal/src/pages/BlockSinglePage/BlockSinglePage.jsx +277 -0
  70. package/bootstrap/services/portal/src/pages/BlocksPage/BlocksPage.jsx +23 -0
  71. package/bootstrap/services/portal/src/pages/DashboardPage/DashboardPage.jsx +11 -0
  72. package/bootstrap/services/portal/src/pages/DashboardPage/DashboardPage.less +0 -0
  73. package/bootstrap/services/portal/src/pages/LoginPage/LoginPage.jsx +21 -0
  74. package/bootstrap/services/portal/src/pages/LoginPage/LoginPage.less +51 -0
  75. package/bootstrap/services/portal/src/pages/PageSinglePage/PageSinglePage.jsx +338 -0
  76. package/bootstrap/services/portal/src/pages/PagesPage/PagesPage.jsx +23 -0
  77. package/bootstrap/services/portal/src/pages/UserSinglePage/UserSinglePage.jsx +9 -0
  78. package/bootstrap/services/portal/src/pages/UserSinglePage/UserSinglePage.less +0 -0
  79. package/bootstrap/services/portal/src/pages/UsersPage/UsersPage.jsx +25 -0
  80. package/bootstrap/services/portal/src/pages/UsersPage/UsersPage.less +0 -0
  81. package/bootstrap/services/portal/src/services/block.js +28 -0
  82. package/bootstrap/services/portal/src/services/client.js +67 -0
  83. package/bootstrap/services/portal/src/services/gravatar.js +14 -0
  84. package/bootstrap/services/portal/src/services/page.js +28 -0
  85. package/bootstrap/services/portal/src/services/storage.js +62 -0
  86. package/bootstrap/services/portal/src/services/user.js +41 -0
  87. package/bootstrap/services/portal/src/slices/authSlice.js +44 -14
  88. package/bootstrap/services/portal/src/store/configureStore.js +1 -3
  89. package/bootstrap/services/portal/src/style/cards.less +57 -0
  90. package/bootstrap/services/portal/src/{styles → style}/global.less +90 -45
  91. package/bootstrap/services/portal/src/style/icons.less +21 -0
  92. package/bootstrap/services/portal/src/style/inputs.less +52 -0
  93. package/bootstrap/services/portal/src/style/main.less +28 -0
  94. package/bootstrap/services/portal/src/utils/utils.js +9 -0
  95. package/bootstrap/services/portal/vite.config.js +12 -0
  96. package/bootstrap/services/user/Dockerfile +1 -1
  97. package/bootstrap/services/user/src/app.js +6 -1
  98. package/bootstrap/services/user/src/commands/user.handler.js +0 -3
  99. package/bootstrap/services/user/src/config.js +5 -1
  100. package/bootstrap/services/user/src/policies/user.policy.js +3 -1
  101. package/bootstrap/services/user/src/tests/commands/user.test.js +22 -0
  102. package/install-from-clone.sh +30 -0
  103. package/package.json +1 -1
  104. package/src/cli.js +8 -0
  105. package/src/config.js +2 -1
  106. package/src/dev/commands.js +10 -2
  107. package/src/dev/dev.service.js +167 -52
  108. package/src/provisioner/Dockerfile +27 -0
  109. package/src/provisioner/package.json +19 -0
  110. package/src/provisioner/src/app.js +56 -0
  111. package/src/provisioner/src/services/mongodb.js +58 -0
  112. package/src/provisioner/src/services/mysql.js +51 -0
  113. package/src/provisioner/src/services/secrets.js +84 -0
  114. package/src/scaffolder/commands.js +12 -5
  115. package/src/scaffolder/scaffolder.handler.js +256 -58
  116. package/templates/service/Dockerfile.hbs +4 -1
  117. package/templates/service/package.json.hbs +14 -16
  118. package/templates/service/src/app.js.hbs +53 -0
  119. package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +2 -3
  120. package/templates/service/src/mongodb.config.js.hbs +49 -0
  121. package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +10 -0
  122. package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
  123. package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
  124. package/bootstrap/services/agent/notes.md +0 -28
  125. package/bootstrap/services/agent/package.json +0 -16
  126. package/bootstrap/services/agent/src/app.js +0 -52
  127. package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
  128. package/bootstrap/services/agent/src/config.js +0 -52
  129. package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
  130. package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
  131. package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
  132. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
  133. package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
  134. package/bootstrap/services/agent/src/services/agent.service.js +0 -259
  135. package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
  136. package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
  137. package/bootstrap/services/portal/Dockerfile.remote +0 -40
  138. package/bootstrap/services/portal/public/favicon.ico +0 -0
  139. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  140. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  141. package/bootstrap/services/portal/public/index.html +0 -43
  142. package/bootstrap/services/portal/public/logo192.png +0 -0
  143. package/bootstrap/services/portal/public/logo512.png +0 -0
  144. package/bootstrap/services/portal/public/manifest.json +0 -25
  145. package/bootstrap/services/portal/public/robots.txt +0 -3
  146. package/bootstrap/services/portal/src/App.js +0 -56
  147. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
  148. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
  149. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
  150. package/bootstrap/services/portal/src/assets/activity.svg +0 -3
  151. package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
  152. package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
  153. package/bootstrap/services/portal/src/assets/bin.svg +0 -3
  154. package/bootstrap/services/portal/src/assets/check.svg +0 -3
  155. package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
  156. package/bootstrap/services/portal/src/assets/contact.svg +0 -3
  157. package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
  158. package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
  159. package/bootstrap/services/portal/src/assets/eye.svg +0 -4
  160. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
  161. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
  162. package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
  163. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  164. package/bootstrap/services/portal/src/assets/home.svg +0 -3
  165. package/bootstrap/services/portal/src/assets/link.svg +0 -3
  166. package/bootstrap/services/portal/src/assets/lock.svg +0 -3
  167. package/bootstrap/services/portal/src/assets/package.svg +0 -4
  168. package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
  169. package/bootstrap/services/portal/src/assets/settings.svg +0 -4
  170. package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
  171. package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
  172. package/bootstrap/services/portal/src/assets/user.svg +0 -3
  173. package/bootstrap/services/portal/src/assets/users.svg +0 -3
  174. package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
  175. package/bootstrap/services/portal/src/data/data.js +0 -70
  176. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
  177. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
  178. package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
  179. package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
  180. package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
  181. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
  182. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
  183. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
  184. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
  185. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
  186. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
  187. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
  188. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
  189. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
  190. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
  191. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
  192. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
  193. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
  194. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
  195. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
  196. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
  197. package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
  198. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
  199. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
  200. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
  201. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
  202. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
  203. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
  204. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
  205. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
  206. package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
  207. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
  208. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
  209. package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
  210. package/bootstrap/services/portal/src/features/user/user.less +0 -57
  211. package/bootstrap/services/portal/src/includes/utilities.js +0 -259
  212. package/bootstrap/services/portal/src/index.js +0 -14
  213. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
  214. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
  215. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
  216. package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
  217. package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
  218. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
  219. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
  220. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
  221. package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
  222. package/bootstrap/services/portal/src/pages/login/login.less +0 -10
  223. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
  224. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
  225. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
  226. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
  227. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
  228. package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
  229. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
  230. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
  231. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
  232. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
  233. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
  234. package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
  235. package/bootstrap/services/portal/src/pages/users/users.less +0 -25
  236. package/bootstrap/services/portal/src/styles/inputs.less +0 -157
  237. package/bootstrap/services/portal/src/styles/main.less +0 -26
  238. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
  239. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
  240. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
  241. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
  242. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
  243. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
  244. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
  245. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
  246. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
  247. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
  248. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
  249. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
  250. package/bootstrap/services/user/src/tests/user.test.js +0 -126
  251. package/templates/service/app.js.hbs +0 -38
  252. package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
  253. /package/bootstrap/services/portal/src/{ui/saveButton/saveButton.less → components/CustomSelect/CustomSelect.less} +0 -0
  254. /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
  255. /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
  256. /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
  257. /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
  258. /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
  259. /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
@@ -1,51 +1,65 @@
1
- # deploy.localdev.yml
2
-
3
- # - This file is used to orchestrate locally running containers for development
4
- # - environment: localdev is a named convention required for local development
5
-
6
1
  config:
7
- core-version: 1.0
2
+ core-version: 1
8
3
  architecture: microservice
9
4
  region: eu-west-2
10
5
  environment: localdev
11
6
  namespace: my-project
12
-
13
7
  services:
14
8
  - name: control
15
9
  listener_rules:
16
10
  paths:
17
11
  - /control
18
12
  - /tasks
19
- min-tasks: 1
20
- max-tasks: 1
13
+ min_tasks: 1
14
+ max_tasks: 1
21
15
  depends_on:
22
- - control-db
23
- command: ["npm", "run", "start:dev"]
24
- ports:
25
- - "4001:3000"
26
-
16
+ - db-mysql
17
+ command:
18
+ - npm
19
+ - run
20
+ - start:dev
21
+ ports:
22
+ - '4001:3000'
27
23
  - name: user
28
24
  listener_rules:
29
25
  paths:
30
26
  - /authenticate
31
27
  - /users
32
- min-tasks: 1
33
- max-tasks: 1
28
+ min_tasks: 1
29
+ max_tasks: 1
34
30
  depends_on:
35
- - control-db
36
- command: ["npm", "run", "start:dev"]
37
- ports:
38
- - "4002:3000"
39
-
40
- - name: agent
31
+ - db-mysql
32
+ command:
33
+ - npm
34
+ - run
35
+ - start:dev
36
+ ports:
37
+ - '4002:3000'
38
+ - name: portal
41
39
  listener_rules:
42
40
  paths:
43
- - /agent
44
- min-tasks: 1
45
- max-tasks: 1
41
+ - /portal
42
+ min_tasks: 1
43
+ max_tasks: 1
44
+ command:
45
+ - npm
46
+ - run
47
+ - dev
48
+ - '-- --host'
49
+ ports:
50
+ - '4003:5173'
51
+ - name: page
52
+ listener_rules:
53
+ paths:
54
+ - /pages
55
+ - /blocks
56
+ min_tasks: 1
57
+ max_tasks: 1
58
+ command:
59
+ - npm
60
+ - run
61
+ - start:dev
62
+ ports:
63
+ - '4004:3000'
46
64
  depends_on:
47
- - agent-db
48
- command: ["npm", "run", "start:dev"]
49
- ports:
50
- - "4003:3000"
51
-
65
+ - db-mongo
@@ -1,27 +1,33 @@
1
+ provision:
2
+ MYSQL_ROOT_PASSWORD: GExtMVydbpIihS5f
3
+ MONGO_ROOT_PASSWORD: E7lVrilnp07gIxcX
1
4
  global:
2
5
  RABBITMQ_URL: amqp://gnar_engine_rabbit_user:gn4rlyRaB81Tw4sh@rabbitmq:5672
3
6
  RABBITMQ_USER: gnar_engine_rabbit_user
4
7
  RABBITMQ_PASS: gn4rlyRaB81Tw4sh
8
+ UPLOADS_URL: https://gnar-engine-test.s3.eu-west-2.amazonaws.com
9
+ S3_BUCKET: gnar-engine-test
10
+ AWS_REGION: eu-west-2
11
+ AWS_ACCESS_KEY_ID:
12
+ AWS_SECRET_ACCESS_KEY:
5
13
  services:
6
14
  control:
7
- MYSQL_HOST: control-db
15
+ MYSQL_HOST: db-mysql
8
16
  MYSQL_DATABASE: ge_control_db
9
17
  MYSQL_USER: ge_control_db_user
10
- MYSQL_PASSWORD: zWF85kfGJNRA9ayp
11
- MYSQL_RANDOM_ROOT_PASSWORD: wH0Pzkht75NvMd3b
18
+ MYSQL_PASSWORD: bL6I1ABJFDPO3JAR
12
19
  user:
13
- MYSQL_HOST: user-db
20
+ MYSQL_HOST: db-mysql
14
21
  MYSQL_DATABASE: ge_user_db
15
22
  MYSQL_USER: ge_user_db_user
16
- MYSQL_PASSWORD: WTEYWqs6wDBX459p
17
- MYSQL_RANDOM_ROOT_PASSWORD: GXEy5T7Cp2zuOTah
23
+ MYSQL_PASSWORD: 7cm0crGDTaJy9Sa2
18
24
  ROOT_ADMIN_EMAIL: adam@gnar.co.uk
19
25
  ROOT_ADMIN_USERNAME: engineadmin
20
- ROOT_ADMIN_PASSWORD: n0eYk6aoiYAeSur1
21
- ROOT_ADMIN_API_KEY: qydfeMcyutzIXBvHjrB2qGL9hTdco81X
22
- agent:
23
- MYSQL_HOST: agent-db
24
- MYSQL_DATABASE: ge_agent_db
25
- MYSQL_USER: ge_agent_db_user
26
- MYSQL_PASSWORD: 4BARYvygGSv6BRPH
27
- MYSQL_RANDOM_ROOT_PASSWORD: s27o951anIt8Lqmy
26
+ ROOT_ADMIN_PASSWORD: MOF4TWiFh4TXOHcL
27
+ ROOT_ADMIN_API_KEY: JPpmhQN0bs8f5x2jN5ypCU6Ww6VETrW2
28
+ page:
29
+ MONGO_HOST: db-mongo
30
+ MONGO_DATABASE: page_db
31
+ MONGO_USER: page_user
32
+ MONGO_PASSWORD: Q2atGxh21VqNIrZO
33
+
@@ -6,6 +6,10 @@ export const config = {
6
6
  // service name
7
7
  serviceName: 'controlService',
8
8
 
9
+ // environment
10
+ environment: process.env.CONTROL_NODE_ENV || 'dev',
11
+ runTests: process.env.CONTROL_RUN_TESTS || false,
12
+
9
13
  // microservice | modular-monolith
10
14
  architecture: process.env.GLOBAL_ARCHITECTURE || 'microservice',
11
15
 
@@ -1,5 +1,5 @@
1
- # Dockerfile for Agent Service
2
- FROM node:20-alpine
1
+ # Dockerfile for Page Service
2
+ FROM node:20-alpine
3
3
 
4
4
  # Set the working directory
5
5
  WORKDIR /usr/gnar_engine/app
@@ -8,7 +8,7 @@ WORKDIR /usr/gnar_engine/app
8
8
  ENV GLOBAL_SERVICE_BASE_DIR=/usr/gnar_engine/app/src/
9
9
 
10
10
  # Copy package.json and package-lock.json
11
- COPY ./services/agent/package*.json ./
11
+ COPY ./services/page/package*.json ./
12
12
 
13
13
  # Install nodemon
14
14
  RUN npm install -g nodemon
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "page-service",
3
+ "version": "1.0.0",
4
+ "description": "Page microservice for Gnar Engine",
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "node ./src/app.js",
8
+ "start:dev": "nodemon --watch ./src ./src/app.js",
9
+ "test": "jest --watchAll --verbose"
10
+ },
11
+ "author": "Gnar Software Ltd.",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "@gnar-engine/core": "^1.0.1"
15
+ }
16
+ }
@@ -0,0 +1,50 @@
1
+ import { message, http, logger, db, registerService, webSockets, test } from '@gnar-engine/core';
2
+ import { config } from './config.js';
3
+ import { messageHandlers } from './controllers/message.controller.js';
4
+ import { httpController as pagePlatformHttpController } from './controllers/page.http.controller.js';
5
+ import { httpController as blockPlatformHttpController } from './controllers/block.http.controller.js';
6
+
7
+ /**
8
+ * Initialise service
9
+ */
10
+ export const initService = async () => {
11
+
12
+ // Run seeders
13
+ db.seeders.runSeeders({config});
14
+
15
+ // Import command handlers after the command bus is initialised
16
+ await import('./commands/page.handler.js');
17
+ await import('./commands/block.handler.js');
18
+
19
+ // Initialise and register message handlers
20
+ await message.init({
21
+ config: config.message,
22
+ handlers: messageHandlers
23
+ });
24
+
25
+ // Initialise websocket client & server
26
+ await webSockets.init(config.webSockets, config.serviceName);
27
+
28
+ // Register http routes
29
+ await http.registerRoutes({
30
+ controllers: [
31
+ pagePlatformHttpController,
32
+ blockPlatformHttpController
33
+ ]
34
+ });
35
+
36
+ // Start the HTTP server
37
+ await http.start();
38
+
39
+ // Register service with control service
40
+ await registerService();
41
+
42
+ logger.info('G n a r E n g i n e | Page Service initialised successfully.');
43
+
44
+ // Tests
45
+ if (config.environment === 'test' && config.runTests) {
46
+ test.runCommandTests({config});
47
+ }
48
+ }
49
+
50
+ initService();
@@ -0,0 +1,94 @@
1
+ import { commands, logger, error } from '@gnar-engine/core';
2
+ import { block } from '../services/block.service.js';
3
+ import { config } from '../config.js';
4
+ import { validateBlock } from '../schema/page.schema.js';
5
+
6
+
7
+ /**
8
+ * Get single block
9
+ */
10
+ commands.register('pageService.getSingleBlock', async ({id}) => {
11
+ if (id) {
12
+ return await block.getById({id: id});
13
+ } else {
14
+ throw new error.badRequest('Block id required');
15
+ }
16
+ });
17
+
18
+ /**
19
+ * Get many blocks
20
+ */
21
+ commands.register('pageService.getManyBlocks', async ({}) => {
22
+ return await block.getAll();
23
+ });
24
+
25
+ /**
26
+ * Create blocks
27
+ */
28
+ commands.register('pageService.createBlocks', async ({ blocks }) => {
29
+ const validationErrors = [];
30
+ let createdNewBlocks = [];
31
+
32
+ for (const newData of blocks) {
33
+ const { errors } = validateBlock(newData);
34
+ if (errors?.length) {
35
+ validationErrors.push(errors);
36
+ continue;
37
+ }
38
+
39
+ const created = await block.create(newData);
40
+ createdNewBlocks.push(created);
41
+ }
42
+
43
+ if (validationErrors.length) {
44
+ throw new error.badRequest(`Invalid block data: ${validationErrors}`);
45
+ }
46
+
47
+ return createdNewBlocks;
48
+ });
49
+
50
+ /**
51
+ * Update block
52
+ */
53
+ commands.register('pageService.updateBlock', async ({id, newBlockData}) => {
54
+
55
+ const validationErrors = [];
56
+
57
+ if (!id) {
58
+ throw new error.badRequest('Block ID required');
59
+ }
60
+
61
+ const obj = await block.getById({id: id});
62
+
63
+ if (!obj) {
64
+ throw new error.notFound('Block not found');
65
+ }
66
+
67
+ delete newBlockData.id;
68
+
69
+ const { errors } = validateBlock(newBlockData);
70
+
71
+ if (errors?.length) {
72
+ validationErrors.push(errors);
73
+ }
74
+
75
+ if (validationErrors.length) {
76
+ throw new error.badRequest(`Invalid block data: ${validationErrors}`);
77
+ }
78
+
79
+ return await block.update({
80
+ id: id,
81
+ updatedData: newBlockData
82
+ });
83
+ });
84
+
85
+ /**
86
+ * Delete block
87
+ */
88
+ commands.register('pageService.deleteBlock', async ({id}) => {
89
+ const obj = await block.getById({id: id});
90
+ if (!obj) {
91
+ throw new error.notFound('Block not found');
92
+ }
93
+ return await block.delete({id: id});
94
+ });
@@ -0,0 +1,167 @@
1
+ import { commands, logger, error, storage } from '@gnar-engine/core';
2
+ import { page } from '../services/page.service.js';
3
+ import { config } from '../config.js';
4
+ import { validatePage } from '../schema/page.schema.js';
5
+
6
+
7
+ /**
8
+ * Get single page
9
+ */
10
+ commands.register('pageService.getSinglePage', async ({id}) => {
11
+ if (id) {
12
+ return await page.getById({id: id});
13
+ } else {
14
+ throw new error.badRequest('Page email or id required');
15
+ }
16
+ });
17
+
18
+ /**
19
+ * Get many pages
20
+ */
21
+ commands.register('pageService.getManyPages', async ({}) => {
22
+ return await page.getAll();
23
+ });
24
+
25
+ /**
26
+ * Create pages
27
+ */
28
+ commands.register('pageService.createPages', async ({ pages, requestUser }) => {
29
+ const validationErrors = [];
30
+ let createdNewPages = [];
31
+
32
+ for (const newData of pages) {
33
+ const { errors } = validatePage(newData);
34
+ if (errors?.length) {
35
+ validationErrors.push(errors);
36
+ continue;
37
+ }
38
+
39
+ newData = await commands.execute('processUploadsInData', { data: newData, requestUser });
40
+
41
+ const created = await page.create(newData);
42
+ createdNewPages.push(created);
43
+ }
44
+
45
+ if (validationErrors.length) {
46
+ throw new error.badRequest(`Invalid page data: ${validationErrors}`);
47
+ }
48
+
49
+ return createdNewPages;
50
+ });
51
+
52
+ /**
53
+ * Update page
54
+ */
55
+ commands.register('pageService.updatePage', async ({id, newPageData, requestUser}) => {
56
+
57
+ const validationErrors = [];
58
+
59
+ if (!id) {
60
+ throw new error.badRequest('Page ID required');
61
+
62
+ }
63
+
64
+ const obj = await page.getById({id: id});
65
+
66
+ if (!obj) {
67
+ throw new error.notFound('Page not found');
68
+
69
+ }
70
+
71
+ delete newPageData.id;
72
+
73
+ const { errors } = validatePage(newPageData);
74
+
75
+ if (errors?.length) {
76
+ validationErrors.push(errors);
77
+ }
78
+
79
+ if (validationErrors.length) {
80
+ throw new error.badRequest(`Invalid page data: ${validationErrors}`);
81
+ }
82
+
83
+ newPageData = await commands.execute('processUploadsInData', { data: newPageData, requestUser });
84
+
85
+ return await page.update({
86
+ id: id,
87
+ updatedData: newPageData
88
+ });
89
+ });
90
+
91
+ /**
92
+ * Delete page
93
+ */
94
+ commands.register('pageService.deletePage', async ({id}) => {
95
+ const obj = await page.getById({id: id});
96
+ if (!obj) {
97
+ throw new error.notFound('Page not found');
98
+ }
99
+ return await page.delete({id: id});
100
+ });
101
+
102
+
103
+ /**
104
+ * Find file and image uploads and store them
105
+ *
106
+ * @param {Object} data - The data object to search for files/images
107
+ * @param {Function} uploadFn - Function to handle the actual upload process
108
+ * @returns {Object} - The updated data object with stored file/image references
109
+ */
110
+ commands.register('pageService.processUploadsInData', async ({ data, requestUser }) => {
111
+
112
+ const uploadFilesRecursive = async (data) => {
113
+ if (Array.isArray(data)) {
114
+ return Promise.all(data.map(item => uploadFilesRecursive(item)));
115
+ } else if (data && typeof data === 'object') {
116
+ const result = { ...data };
117
+
118
+ for (const [key, value] of Object.entries(data)) {
119
+ if (key === 'file' && typeof value === 'string') {
120
+
121
+ logger.info('Processing file upload in page data');
122
+
123
+ // Filename
124
+ const fileName = result.fileName || `upload_${Date.now()}`;
125
+
126
+ // Mime type
127
+ let mimeType = result.mimeType;
128
+ let base64Data = value;
129
+
130
+ const matches = value.match(/^data:(.+);base64,(.+)$/);
131
+ if (matches) {
132
+ mimeType = mimeType || matches[1];
133
+ base64Data = matches[2];
134
+ }
135
+
136
+ if (!mimeType) mimeType = 'application/octet-stream';
137
+
138
+ // Upload
139
+ const url = await storage.upload({
140
+ file: Buffer.from(base64Data, 'base64'),
141
+ key: 'public/page-content/' + fileName,
142
+ contentType: mimeType,
143
+ metadata: {
144
+ uploadedAt: new Date().toISOString(),
145
+ uploadedBy: requestUser ? requestUser.id : 'unknown'
146
+ }
147
+ });
148
+
149
+ // Add url and remove upload keys
150
+ result.url = url;
151
+ delete result.file;
152
+ if (result.fileName) delete result.fileName;
153
+ if (result.mimeType) delete result.mimeType;
154
+
155
+ } else {
156
+ result[key] = await uploadFilesRecursive(value);
157
+ }
158
+ }
159
+
160
+ return result;
161
+ }
162
+
163
+ return data;
164
+ };
165
+
166
+ return await uploadFilesRecursive(data);
167
+ });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Gnar Engine Service Config
3
+ */
4
+ export const config = {
5
+ // service name
6
+ serviceName: 'pageService',
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: 'mongodb',
26
+
27
+ // MongoDB
28
+ host: process.env.PAGE_MONGO_HOST,
29
+ database: process.env.PAGE_MONGO_DATABASE,
30
+ user: process.env.PAGE_MONGO_USER,
31
+ password: process.env.PAGE_MONGO_PASSWORD,
32
+ port: process.env.PAGE_MONGO_PORT || 27017,
33
+ connectionArgs: {},
34
+ },
35
+
36
+ // storage
37
+ storage: {
38
+ // driver: s3
39
+ driver: 's3',
40
+ uploadsUrl: process.env.UPLOADS_URL,
41
+
42
+ // s3
43
+ bucket: process.env.S3_BUCKET,
44
+ region: process.env.AWS_REGION,
45
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
46
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
47
+ },
48
+
49
+ // message broker
50
+ message: {
51
+ url: process.env.RABBITMQ_URL,
52
+ queueName: 'pageServiceQueue',
53
+ prefetch: 20
54
+ },
55
+
56
+ webSockets: {
57
+ reconnectInterval: 5000,
58
+ maxInitialConnectionAttempts: 5
59
+ },
60
+
61
+ hashNameSpace: '',
62
+ }
@@ -0,0 +1,87 @@
1
+ import { commands } from '@gnar-engine/core';
2
+ import { authorise } from '../policies/block.policy.js';
3
+
4
+ /**
5
+ * HTTP controller
6
+ */
7
+ export const httpController = {
8
+
9
+ /**
10
+ * Get single block
11
+ */
12
+ getSingle: {
13
+ method: 'GET',
14
+ url: '/blocks/:id',
15
+ preHandler: async (request, reply) => authorise.getSingle(request, reply),
16
+ handler: async (request, reply) => {
17
+ const params = {
18
+ id: request.params.id
19
+ };
20
+ const result = await commands.execute('getSingleBlock', params);
21
+ reply.code(200).send({ block: result });
22
+ }
23
+ },
24
+
25
+ /**
26
+ * Get multiple blocks
27
+ */
28
+ getMany: {
29
+ method: 'GET',
30
+ url: '/blocks/',
31
+ preHandler: async (request, reply) => authorise.getMany(request, reply),
32
+ handler: async (request, reply) => {
33
+ const params = {};
34
+ const results = await commands.execute('getManyBlocks', params);
35
+ reply.code(200).send({ blocks: results });
36
+ }
37
+ },
38
+
39
+ /**
40
+ * Create new block
41
+ */
42
+ create: {
43
+ method: 'POST',
44
+ url: '/blocks/',
45
+ preHandler: async (request, reply) => authorise.create(request, reply),
46
+ handler: async (request, reply) => {
47
+ const params = {
48
+ blocks: [request.body.block]
49
+ };
50
+ const results = await commands.execute('createBlocks', params);
51
+ reply.code(200).send({ blocks: results });
52
+ },
53
+ },
54
+
55
+ /**
56
+ * Update block
57
+ */
58
+ update: {
59
+ method: 'POST',
60
+ url: '/blocks/:id',
61
+ preHandler: async (request, reply) => authorise.update(request, reply),
62
+ handler: async (request, reply) => {
63
+ const params = {
64
+ id: request.params.id,
65
+ newBlockData: request.body.block
66
+ };
67
+ const result = await commands.execute('updateBlock', params);
68
+ reply.code(200).send({ page: result });
69
+ },
70
+ },
71
+
72
+ /**
73
+ * Delete block
74
+ */
75
+ delete: {
76
+ method: 'DELETE',
77
+ url: '/blocks/:id',
78
+ preHandler: async (request, reply) => authorise.delete(request, reply),
79
+ handler: async (request, reply) => {
80
+ const params = {
81
+ id: request.params.id
82
+ };
83
+ await commands.execute('deleteBlock', params);
84
+ reply.code(200).send({ message: 'Block deleted' });
85
+ },
86
+ },
87
+ }