@eventcatalog/core 0.1.12 → 0.1.16

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/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +58 -38
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/eslint/.cache_1bay4w0 +1 -1
  6. package/.next/cache/next-server.js.nft.json +1 -1
  7. package/.next/cache/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/index.pack +0 -0
  9. package/.next/cache/webpack/server-production/0.pack +0 -0
  10. package/.next/cache/webpack/server-production/index.pack +0 -0
  11. package/.next/next-server.js.nft.json +1 -1
  12. package/.next/prerender-manifest.json +1 -1
  13. package/.next/routes-manifest.json +1 -1
  14. package/.next/server/chunks/484.js +572 -0
  15. package/.next/server/chunks/944.js +89 -53
  16. package/.next/server/pages/404.html +1 -1
  17. package/.next/server/pages/500.html +1 -1
  18. package/.next/server/pages/_app.js +16 -5
  19. package/.next/server/pages/events/AddedItemToCart/logs.html +1 -1
  20. package/.next/server/pages/events/AddedItemToCart/v/0.0.1.html +3 -3
  21. package/.next/server/pages/events/AddedItemToCart/v/0.0.1.json +1 -1
  22. package/.next/server/pages/events/AddedItemToCart/v/0.0.2.html +3 -3
  23. package/.next/server/pages/events/AddedItemToCart/v/0.0.2.json +1 -1
  24. package/.next/server/pages/events/AddedItemToCart.html +4 -22
  25. package/.next/server/pages/events/AddedItemToCart.json +1 -1
  26. package/.next/server/pages/events/OrderComplete/logs.html +1 -1
  27. package/.next/server/pages/events/OrderComplete.html +3 -21
  28. package/.next/server/pages/events/OrderComplete.json +1 -1
  29. package/.next/server/pages/events/OrderConfirmed/logs.html +1 -1
  30. package/.next/server/pages/events/OrderConfirmed.html +3 -21
  31. package/.next/server/pages/events/OrderConfirmed.json +1 -1
  32. package/.next/server/pages/events/OrderRequested/logs.html +1 -1
  33. package/.next/server/pages/events/OrderRequested.html +3 -21
  34. package/.next/server/pages/events/OrderRequested.json +1 -1
  35. package/.next/server/pages/events/PaymentProcessed/logs.html +1 -1
  36. package/.next/server/pages/events/PaymentProcessed.html +3 -21
  37. package/.next/server/pages/events/PaymentProcessed.json +1 -1
  38. package/.next/server/pages/events/RemovedItemFromCart/logs.html +1 -1
  39. package/.next/server/pages/events/RemovedItemFromCart.html +3 -21
  40. package/.next/server/pages/events/RemovedItemFromCart.json +1 -1
  41. package/.next/server/pages/events/ShipmentDelivered/logs.html +1 -1
  42. package/.next/server/pages/events/ShipmentDelivered.html +3 -23
  43. package/.next/server/pages/events/ShipmentDelivered.json +1 -1
  44. package/.next/server/pages/events/ShipmentDispatched/logs.html +1 -1
  45. package/.next/server/pages/events/ShipmentDispatched.html +3 -21
  46. package/.next/server/pages/events/ShipmentDispatched.json +1 -1
  47. package/.next/server/pages/events/ShipmentPrepared/logs.html +1 -1
  48. package/.next/server/pages/events/ShipmentPrepared.html +2 -20
  49. package/.next/server/pages/events/ShipmentPrepared.json +1 -1
  50. package/.next/server/pages/events/[name]/v/[version].js +29 -1
  51. package/.next/server/pages/events/[name]/v/[version].js.nft.json +1 -1
  52. package/.next/server/pages/events/[name].js +29 -1
  53. package/.next/server/pages/events/[name].js.nft.json +1 -1
  54. package/.next/server/pages/events.html +3 -3
  55. package/.next/server/pages/events.js.nft.json +1 -1
  56. package/.next/server/pages/events.json +1 -1
  57. package/.next/server/pages/index.html +1 -1
  58. package/.next/server/pages/overview.html +1 -1
  59. package/.next/server/pages/overview.json +1 -1
  60. package/.next/server/pages/services/Basket Service.html +2 -22
  61. package/.next/server/pages/services/Basket Service.json +1 -1
  62. package/.next/server/pages/services/Data Lake.html +2 -24
  63. package/.next/server/pages/services/Data Lake.json +1 -1
  64. package/.next/server/pages/services/Payment Service.html +2 -20
  65. package/.next/server/pages/services/Payment Service.json +1 -1
  66. package/.next/server/pages/services/Shipping Service.html +2 -28
  67. package/.next/server/pages/services/Shipping Service.json +1 -1
  68. package/.next/server/pages/services/[name].js +64 -4
  69. package/.next/server/pages/services/[name].js.nft.json +1 -1
  70. package/.next/server/pages/services.html +2 -2
  71. package/.next/server/pages/services.js.nft.json +1 -1
  72. package/.next/server/pages/services.json +1 -1
  73. package/.next/server/pages/users/[id].js.nft.json +1 -1
  74. package/.next/server/pages/users/dboyne.html +3 -3
  75. package/.next/server/pages/users/dboyne.json +1 -1
  76. package/.next/server/pages/users/mSmith.html +3 -3
  77. package/.next/server/pages/users/mSmith.json +1 -1
  78. package/.next/server/pages/visualiser.html +14 -0
  79. package/.next/server/pages/visualiser.js +583 -0
  80. package/.next/server/pages/visualiser.js.nft.json +1 -0
  81. package/.next/server/pages/visualiser.json +1 -0
  82. package/.next/server/pages-manifest.json +1 -0
  83. package/.next/static/7llqY64OLAlXQNo-YhXyr/_buildManifest.js +1 -0
  84. package/.next/static/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/_middlewareManifest.js +0 -0
  85. package/.next/static/7llqY64OLAlXQNo-YhXyr/_ssgManifest.js +1 -0
  86. package/.next/static/chunks/109-a08539311d3d6672.js +1 -0
  87. package/.next/static/chunks/178-87f01d17ab32dd4f.js +1 -0
  88. package/.next/static/chunks/252-08ab418f9b6821dd.js +1 -0
  89. package/.next/static/chunks/506-12764fcf4b5d93b0.js +1 -0
  90. package/.next/static/chunks/519-2ec6fc3cdbaa4dc2.js +1 -0
  91. package/.next/static/chunks/650-343888e13f994a09.js +1 -0
  92. package/.next/static/chunks/962-20c87db3880df896.js +1 -0
  93. package/.next/static/chunks/b744740b-229c238b25b9eeac.js +1 -0
  94. package/.next/static/chunks/pages/_app-6eba1099469a6889.js +1 -0
  95. package/.next/static/chunks/pages/events/[name]/v/{[version]-f6619ec4056cc70d.js → [version]-33051dbc32f5fe4e.js} +1 -1
  96. package/.next/static/chunks/pages/events/{[name]-73ecab7171745a3f.js → [name]-813780e7042af288.js} +1 -1
  97. package/.next/static/chunks/pages/services/[name]-142d7fa515cfc532.js +1 -0
  98. package/.next/static/chunks/pages/visualiser-0fbd55ba5b1f83ed.js +1 -0
  99. package/.next/static/chunks/{webpack-2ebfdb1666dac4ad.js → webpack-de66347fdf9ac788.js} +1 -1
  100. package/.next/static/css/f56eba33afeb64fa.css +3 -0
  101. package/.next/trace +56 -54
  102. package/CHANGELOG.md +26 -0
  103. package/components/Header.tsx +1 -0
  104. package/components/Mdx/Examples.tsx +27 -27
  105. package/components/Mdx/NodeGraph/GraphElements.tsx +238 -0
  106. package/components/Mdx/NodeGraph/GraphLayout.ts +57 -0
  107. package/components/Mdx/NodeGraph/Node.tsx +15 -0
  108. package/components/Mdx/NodeGraph/NodeGraph.tsx +180 -0
  109. package/components/Mdx/NodeGraph/__tests__/GraphElements.spec.ts +98 -0
  110. package/components/Mdx/NodeGraph/__tests__/GraphLayout.spec.ts +104 -0
  111. package/components/Mdx/NodeGraph/__tests__/__snapshots__/GraphElements.spec.ts.snap +995 -0
  112. package/components/Mdx/NodeGraph/__tests__/__snapshots__/GraphLayout.spec.ts.snap +81 -0
  113. package/components/Sidebars/EventSidebar.tsx +7 -0
  114. package/components/Sidebars/ServiceSidebar.tsx +8 -1
  115. package/components/SyntaxHighlighter.tsx +18 -10
  116. package/out/404/index.html +1 -1
  117. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/AddedItemToCart/logs.json +0 -0
  118. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/AddedItemToCart/v/0.0.1.json +1 -1
  119. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/AddedItemToCart/v/0.0.2.json +1 -1
  120. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/events/AddedItemToCart.json +1 -0
  121. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/OrderComplete/logs.json +0 -0
  122. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/events/OrderComplete.json +1 -0
  123. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/OrderConfirmed/logs.json +0 -0
  124. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/OrderConfirmed.json +1 -1
  125. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/OrderRequested/logs.json +0 -0
  126. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/events/OrderRequested.json +1 -0
  127. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/PaymentProcessed/logs.json +0 -0
  128. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/PaymentProcessed.json +1 -1
  129. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/RemovedItemFromCart/logs.json +0 -0
  130. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/RemovedItemFromCart.json +1 -1
  131. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/ShipmentDelivered/logs.json +0 -0
  132. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/events/ShipmentDelivered.json +1 -0
  133. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/ShipmentDispatched/logs.json +0 -0
  134. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/ShipmentDispatched.json +1 -1
  135. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events/ShipmentPrepared/logs.json +0 -0
  136. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/events/ShipmentPrepared.json +1 -0
  137. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/events.json +1 -1
  138. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/overview.json +1 -1
  139. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/services/Basket Service.json +1 -1
  140. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/services/Data Lake.json +1 -0
  141. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/services/Payment Service.json +1 -0
  142. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/services/Shipping Service.json +1 -0
  143. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/services.json +1 -0
  144. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/users/dboyne.json +1 -0
  145. package/out/_next/data/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/users/mSmith.json +1 -1
  146. package/out/_next/data/7llqY64OLAlXQNo-YhXyr/visualiser.json +1 -0
  147. package/out/_next/static/7llqY64OLAlXQNo-YhXyr/_buildManifest.js +1 -0
  148. package/out/_next/static/{bMdE5uGdmIhIs9cgTPp_Z → 7llqY64OLAlXQNo-YhXyr}/_middlewareManifest.js +0 -0
  149. package/out/_next/static/7llqY64OLAlXQNo-YhXyr/_ssgManifest.js +1 -0
  150. package/out/_next/static/chunks/109-a08539311d3d6672.js +1 -0
  151. package/out/_next/static/chunks/178-87f01d17ab32dd4f.js +1 -0
  152. package/out/_next/static/chunks/252-08ab418f9b6821dd.js +1 -0
  153. package/out/_next/static/chunks/506-12764fcf4b5d93b0.js +1 -0
  154. package/out/_next/static/chunks/519-2ec6fc3cdbaa4dc2.js +1 -0
  155. package/out/_next/static/chunks/650-343888e13f994a09.js +1 -0
  156. package/out/_next/static/chunks/962-20c87db3880df896.js +1 -0
  157. package/out/_next/static/chunks/b744740b-229c238b25b9eeac.js +1 -0
  158. package/out/_next/static/chunks/pages/_app-6eba1099469a6889.js +1 -0
  159. package/out/_next/static/chunks/pages/events/[name]/v/{[version]-f6619ec4056cc70d.js → [version]-33051dbc32f5fe4e.js} +1 -1
  160. package/out/_next/static/chunks/pages/events/{[name]-73ecab7171745a3f.js → [name]-813780e7042af288.js} +1 -1
  161. package/out/_next/static/chunks/pages/services/[name]-142d7fa515cfc532.js +1 -0
  162. package/out/_next/static/chunks/pages/visualiser-0fbd55ba5b1f83ed.js +1 -0
  163. package/out/_next/static/chunks/{webpack-2ebfdb1666dac4ad.js → webpack-de66347fdf9ac788.js} +1 -1
  164. package/out/_next/static/css/f56eba33afeb64fa.css +3 -0
  165. package/out/events/AddedItemToCart/index.html +4 -22
  166. package/out/events/AddedItemToCart/logs/index.html +1 -1
  167. package/out/events/AddedItemToCart/v/0.0.1/index.html +3 -3
  168. package/out/events/AddedItemToCart/v/0.0.2/index.html +3 -3
  169. package/out/events/OrderComplete/index.html +3 -21
  170. package/out/events/OrderComplete/logs/index.html +1 -1
  171. package/out/events/OrderConfirmed/index.html +3 -21
  172. package/out/events/OrderConfirmed/logs/index.html +1 -1
  173. package/out/events/OrderRequested/index.html +3 -21
  174. package/out/events/OrderRequested/logs/index.html +1 -1
  175. package/out/events/PaymentProcessed/index.html +3 -21
  176. package/out/events/PaymentProcessed/logs/index.html +1 -1
  177. package/out/events/RemovedItemFromCart/index.html +3 -21
  178. package/out/events/RemovedItemFromCart/logs/index.html +1 -1
  179. package/out/events/ShipmentDelivered/index.html +3 -23
  180. package/out/events/ShipmentDelivered/logs/index.html +1 -1
  181. package/out/events/ShipmentDispatched/index.html +3 -21
  182. package/out/events/ShipmentDispatched/logs/index.html +1 -1
  183. package/out/events/ShipmentPrepared/index.html +2 -20
  184. package/out/events/ShipmentPrepared/logs/index.html +1 -1
  185. package/out/events/index.html +3 -3
  186. package/out/index.html +1 -1
  187. package/out/overview/index.html +1 -1
  188. package/out/services/Basket Service/index.html +2 -22
  189. package/out/services/Data Lake/index.html +2 -24
  190. package/out/services/Payment Service/index.html +2 -20
  191. package/out/services/Shipping Service/index.html +2 -28
  192. package/out/services/index.html +2 -2
  193. package/out/users/dboyne/index.html +3 -3
  194. package/out/users/mSmith/index.html +3 -3
  195. package/out/visualiser/index.html +14 -0
  196. package/package.json +3 -1
  197. package/pages/events/[name].tsx +46 -8
  198. package/pages/services/[name].tsx +37 -1
  199. package/pages/visualiser.tsx +226 -0
  200. package/styles/globals.css +4 -0
  201. package/.next/static/bMdE5uGdmIhIs9cgTPp_Z/_buildManifest.js +0 -1
  202. package/.next/static/bMdE5uGdmIhIs9cgTPp_Z/_ssgManifest.js +0 -1
  203. package/.next/static/chunks/178-9b89f5c036d77ab9.js +0 -1
  204. package/.next/static/chunks/336-7c4681dab353ec23.js +0 -1
  205. package/.next/static/chunks/519-7c428c1e49c8e614.js +0 -1
  206. package/.next/static/chunks/650-4004943b2a9623ca.js +0 -1
  207. package/.next/static/chunks/962-d5070461f6d4a478.js +0 -1
  208. package/.next/static/chunks/pages/_app-46c2e0f1ff3b4efb.js +0 -1
  209. package/.next/static/chunks/pages/services/[name]-d8873d29190a6447.js +0 -1
  210. package/.next/static/css/0b54ec6503b91283.css +0 -3
  211. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/events/AddedItemToCart.json +0 -1
  212. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/events/OrderComplete.json +0 -1
  213. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/events/OrderRequested.json +0 -1
  214. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/events/ShipmentDelivered.json +0 -1
  215. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/events/ShipmentPrepared.json +0 -1
  216. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/services/Data Lake.json +0 -1
  217. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/services/Payment Service.json +0 -1
  218. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/services/Shipping Service.json +0 -1
  219. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/services.json +0 -1
  220. package/out/_next/data/bMdE5uGdmIhIs9cgTPp_Z/users/dboyne.json +0 -1
  221. package/out/_next/static/bMdE5uGdmIhIs9cgTPp_Z/_buildManifest.js +0 -1
  222. package/out/_next/static/bMdE5uGdmIhIs9cgTPp_Z/_ssgManifest.js +0 -1
  223. package/out/_next/static/chunks/178-9b89f5c036d77ab9.js +0 -1
  224. package/out/_next/static/chunks/336-7c4681dab353ec23.js +0 -1
  225. package/out/_next/static/chunks/519-7c428c1e49c8e614.js +0 -1
  226. package/out/_next/static/chunks/650-4004943b2a9623ca.js +0 -1
  227. package/out/_next/static/chunks/962-d5070461f6d4a478.js +0 -1
  228. package/out/_next/static/chunks/pages/_app-46c2e0f1ff3b4efb.js +0 -1
  229. package/out/_next/static/chunks/pages/services/[name]-d8873d29190a6447.js +0 -1
  230. package/out/_next/static/css/0b54ec6503b91283.css +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @eventcatalog/core
2
2
 
3
+ ## 0.1.16
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2d10847`](https://github.com/boyney123/eventcatalog/commit/2d108470af945e1cec59c114627878c56d7385dd) [#186](https://github.com/boyney123/eventcatalog/pull/186) Thanks [@boyney123](https://github.com/boyney123)! - feat: added new visualiser feature
8
+
9
+ ## 0.1.15
10
+
11
+ ### Patch Changes
12
+
13
+ - [`60bea4d`](https://github.com/boyney123/eventcatalog/commit/60bea4db471bf3c63a936b86ce7ee549e73972a6) [#182](https://github.com/boyney123/eventcatalog/pull/182) Thanks [@thim81](https://github.com/thim81)! - fix: optional title for all MDX components
14
+
15
+ * [`bf5bab4`](https://github.com/boyney123/eventcatalog/commit/bf5bab44b9be92c5888c6548694c42d1fa83a678) [#184](https://github.com/boyney123/eventcatalog/pull/184) Thanks [@thim81](https://github.com/thim81)! - fix: increase node width for NodeGraph
16
+
17
+ ## 0.1.14
18
+
19
+ ### Patch Changes
20
+
21
+ - [`1558d17`](https://github.com/boyney123/eventcatalog/commit/1558d17b1c9f925c8e74d22b57edbfc4195a73a6) [#178](https://github.com/boyney123/eventcatalog/pull/178) Thanks [@boyney123](https://github.com/boyney123)! - feat: added better code example component
22
+
23
+ ## 0.1.13
24
+
25
+ ### Patch Changes
26
+
27
+ - [`ca01bef`](https://github.com/boyney123/eventcatalog/commit/ca01bef1659b2c364210a86e0f9e916f6c1fbaa4) [#166](https://github.com/boyney123/eventcatalog/pull/166) Thanks [@thim81](https://github.com/thim81)! - feat: new nodegraph component to render services and events
28
+
3
29
  ## 0.1.12
4
30
 
5
31
  ### Patch Changes
@@ -6,6 +6,7 @@ import { useConfig } from '@/hooks/EventCatalog';
6
6
  const navigation = [
7
7
  { name: 'Events', href: '/events' },
8
8
  { name: 'Services', href: '/services' },
9
+ { name: 'Visualiser', href: '/visualiser' },
9
10
  { name: '3D Node Graph', href: '/overview' },
10
11
  ];
11
12
 
@@ -33,33 +33,33 @@ function Examples({ title = 'Examples', description, examples = [], showLineNumb
33
33
  {description && <p className="text-md font-medium text-gray-700">{description}</p>}
34
34
 
35
35
  <div>
36
- <nav className="-mb-px flex" aria-label="Tabs">
37
- {tabs.map((tab) => {
38
- const isSelected = tab.name === selectedTab.name;
39
- return (
40
- <button
41
- type="button"
42
- key={tab.name}
43
- onClick={() => handleTabSelection(tab)}
44
- className={classNames(
45
- isSelected
46
- ? 'border-green-500 text-green-600 selected'
47
- : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300',
48
- 'whitespace-nowrap py-4 border-b-2 font-medium text-sm important:no-underline px-8 hover:bg-gray-50 transition'
49
- )}
50
- aria-current={isSelected ? 'page' : undefined}
51
- >
52
- {tab.name}
53
- <span className="block text-xs mt-">({tab.langugage})</span>
54
- </button>
55
- );
56
- })}
57
- </nav>
58
- <div className="my-4">
59
- <SyntaxHighlighter language={selectedTab.langugage} showLineNumbers={showLineNumbers}>
60
- {selectedTab.content}
61
- </SyntaxHighlighter>
62
- {selectedTab.langugage && <span className="-mb-2 block text-xs text-right font-bold">{selectedTab.name}</span>}
36
+ <div className="col-span-5">
37
+ <nav className="-mb-2 flex bg-gray-900" aria-label="Tabs">
38
+ {tabs.map((tab) => {
39
+ const isSelected = tab.name === selectedTab.name;
40
+ return (
41
+ <button
42
+ type="button"
43
+ key={tab.name}
44
+ onClick={() => handleTabSelection(tab)}
45
+ className={classNames(
46
+ isSelected
47
+ ? 'border-yellow-300 text-yellow-300 selected bg-gray-700'
48
+ : 'border-transparent text-gray-500 hover:text-gray-400 bg-gray-800 ',
49
+ 'whitespace-nowrap py-3 border-b-2 font-medium important:no-underline px-6 text-xs transition '
50
+ )}
51
+ aria-current={isSelected ? 'page' : undefined}
52
+ >
53
+ {tab.name}
54
+ </button>
55
+ );
56
+ })}
57
+ </nav>
58
+ <div>
59
+ <SyntaxHighlighter language={selectedTab.langugage} showLineNumbers={showLineNumbers}>
60
+ {selectedTab.content}
61
+ </SyntaxHighlighter>
62
+ </div>
63
63
  </div>
64
64
  </div>
65
65
  </div>
@@ -0,0 +1,238 @@
1
+ import { ArrowHeadType, XYPosition, Node, Edge } from 'react-flow-renderer';
2
+ import getConfig from 'next/config';
3
+ import type { Event, Service } from '@eventcatalog/types';
4
+ import CustomNode from './Node';
5
+
6
+ const { publicRuntimeConfig: { basePath = '' } = {} } = getConfig();
7
+
8
+ const MIN_NODE_WIDTH = 150;
9
+ type NODE_TYPES = 'service' | 'event';
10
+
11
+ const generateLink = (value, type) => (basePath !== '' ? `${basePath}/${type}/${value}` : `/${type}/${value}`);
12
+ const calcWidth = (value) => (value.length * 8 > MIN_NODE_WIDTH ? value.length * 8 : MIN_NODE_WIDTH);
13
+
14
+ const buildNodeEdge = ({ id, target, source, label, isAnimated = true }): Edge => ({
15
+ id,
16
+ target,
17
+ source,
18
+ type: 'smoothstep',
19
+ arrowHeadType: ArrowHeadType.ArrowClosed,
20
+ animated: isAnimated,
21
+ label,
22
+ labelBgPadding: [8, 4],
23
+ labelBgBorderRadius: 4,
24
+ labelStyle: { fontSize: '6px' },
25
+ labelBgStyle: { fill: 'white', color: '#fff', fillOpacity: 0.5 },
26
+ });
27
+
28
+ const buildNodeData = ({ name, label, type, maxWidth }: { name: string; label: string; type: NODE_TYPES; maxWidth?: number }) => {
29
+ const width = calcWidth(label);
30
+ const linkType = type === 'service' ? 'services' : 'events';
31
+ const link = generateLink(name, linkType);
32
+ return { label, link, width, maxWidth };
33
+ };
34
+
35
+ const getNodeLabel = ({ type, label, includeIcon }: { type: NODE_TYPES; label: any; includeIcon: boolean }) => {
36
+ if (!includeIcon) return label;
37
+ return <CustomNode type={type} label={label} />;
38
+ };
39
+
40
+ /**
41
+ * Builds a graph for a given event
42
+ * @param {Event} - event
43
+ * @param rootNodeColor - The color of the root node
44
+ * @param isAnimated - whether to animate the graph
45
+ */
46
+ export const getEventElements = (
47
+ { name: eventName, producers: eventProducers, consumers: eventConsumers }: Event,
48
+ rootNodeColor = '#2563eb',
49
+ isAnimated = true,
50
+ includeLabels = false,
51
+ includeNodeIcons = false
52
+ ) => {
53
+ const position: XYPosition = { x: 0, y: 0 };
54
+
55
+ const consumerColor = '#818cf8';
56
+ const producerColor = '#75d7b6';
57
+ const nodeStyles = {
58
+ fontSize: includeNodeIcons ? '8px' : 'auto',
59
+ };
60
+
61
+ const producersNames = eventProducers.map((s) => calcWidth(s));
62
+ const maxProducersWidth = Math.max(...producersNames);
63
+ const consumersNames = eventConsumers.map((s) => calcWidth(s));
64
+ const maxConsumersWidth = Math.max(...consumersNames);
65
+
66
+ const eventNameAsNodeID = `ev-${eventName.replace(/ /g, '_')}`;
67
+ const eventNodeWidth = calcWidth(eventName);
68
+
69
+ const producers = eventProducers.map((node) => ({ label: node, id: `pr-${node.replace(/ /g, '_')}` }));
70
+ const consumers = eventConsumers.map((node) => ({ label: node, id: `co-${node.replace(/ /g, '_')}` }));
71
+
72
+ // Transforms services & event into a graph model
73
+ const producersNodes: Node[] = producers.map(({ label, id }) => {
74
+ const nodeWidth = calcWidth(label);
75
+ const diff = maxProducersWidth - nodeWidth;
76
+ const nodeMaxWidth = diff !== 0 ? nodeWidth - diff : maxProducersWidth;
77
+ const labelToRender = getNodeLabel({ type: 'service', label, includeIcon: includeNodeIcons });
78
+ return {
79
+ id,
80
+ data: buildNodeData({ name: label, label: labelToRender, type: 'service', maxWidth: nodeMaxWidth }),
81
+ style: { border: `2px solid ${producerColor}`, width: nodeWidth, ...nodeStyles },
82
+ type: 'input',
83
+ position,
84
+ };
85
+ });
86
+ const consumersNodes: Node[] = consumers.map(({ id, label }) => {
87
+ const width = calcWidth(label);
88
+ const labelToRender = getNodeLabel({ type: 'service', label, includeIcon: includeNodeIcons });
89
+ return {
90
+ id,
91
+ data: buildNodeData({ name: label, label: labelToRender, type: 'service', maxWidth: maxConsumersWidth }),
92
+ style: { border: `2px solid ${consumerColor}`, width, ...nodeStyles },
93
+ type: 'output',
94
+ position,
95
+ };
96
+ });
97
+
98
+ const eventNode: Node = {
99
+ id: eventNameAsNodeID,
100
+ data: buildNodeData({
101
+ name: eventName,
102
+ label: getNodeLabel({ type: 'event', label: eventName, includeIcon: includeNodeIcons }),
103
+ type: 'event',
104
+ maxWidth: eventNodeWidth,
105
+ }),
106
+ style: {
107
+ border: `2px solid ${rootNodeColor}`,
108
+ width: eventNodeWidth,
109
+ ...nodeStyles,
110
+ },
111
+ position,
112
+ };
113
+
114
+ // Build connections
115
+ const producersEdges: Edge[] = producers.map(({ id, label }) =>
116
+ buildNodeEdge({
117
+ id: `epe-${label.replace(/ /g, '_')}`,
118
+ source: id,
119
+ target: eventNameAsNodeID,
120
+ isAnimated,
121
+ label: includeLabels ? 'publishes' : '',
122
+ })
123
+ );
124
+ const consumersEdges: Edge[] = consumers.map(({ id, label }) =>
125
+ buildNodeEdge({
126
+ id: `ece-${label.replace(/ /g, '_')}`,
127
+ target: id,
128
+ source: eventNameAsNodeID,
129
+ isAnimated,
130
+ label: includeLabels ? 'subscribed by' : '',
131
+ })
132
+ );
133
+
134
+ // Merge nodes in order
135
+ const elements: (Node | Edge)[] = [...producersNodes, eventNode, ...consumersNodes, ...producersEdges, ...consumersEdges];
136
+ return elements;
137
+ };
138
+
139
+ /**
140
+ * Builds a graph for a given service
141
+ * @param {Service} service
142
+ * @param {string} rootNodeColor of the root node
143
+ * @param isAnimated whether the graph should be animated
144
+ * @returns {string} Mermaid Graph
145
+ */
146
+ export const getServiceElements = (
147
+ { publishes, subscribes, name: serviceName }: Service,
148
+ rootNodeColor = '#2563eb',
149
+ isAnimated = true,
150
+ includeEdgeLabels = false,
151
+ includeNodeIcons = false
152
+ ) => {
153
+ const position: XYPosition = { x: 0, y: 0 };
154
+
155
+ const publishColor = '#818cf8';
156
+ const subscribeColor = '#75d7b6';
157
+ const nodeStyles = {
158
+ fontSize: includeNodeIcons ? '8px' : 'auto',
159
+ };
160
+
161
+ const publishesNames = publishes.map((e) => calcWidth(e.name));
162
+ const maxPublishesWidth = Math.max(...publishesNames);
163
+ const subscribesNames = subscribes.map((e) => calcWidth(e.name));
164
+ const maxSubscribesWidth = Math.max(...subscribesNames);
165
+
166
+ const serviceNameAsNodeID = `ser-${serviceName.replace(/ /g, '_')}`;
167
+
168
+ // Transforms services & event into a graph model
169
+ const publishesNodes: Node[] = publishes.map((node) => {
170
+ const nodeWidth = calcWidth(node.name);
171
+ const labelToRender = getNodeLabel({ type: 'event', label: node.name, includeIcon: includeNodeIcons });
172
+ return {
173
+ id: `pub-${node.name.replace(/ /g, '_')}`,
174
+ data: buildNodeData({ name: node.name, label: labelToRender, type: 'event', maxWidth: maxPublishesWidth }),
175
+ style: { border: `2px solid ${publishColor}`, width: nodeWidth, ...nodeStyles },
176
+ type: 'output',
177
+ position,
178
+ };
179
+ });
180
+ const subscribesNodes: Node[] = subscribes.map((node) => {
181
+ const nodeWidth = calcWidth(node.name);
182
+ const diff = maxSubscribesWidth - nodeWidth;
183
+ const nodeMaxWidth = diff !== 0 ? nodeWidth - diff : maxSubscribesWidth;
184
+ const labelToRender = getNodeLabel({ type: 'event', label: node.name, includeIcon: includeNodeIcons });
185
+ return {
186
+ id: `sub-${node.name.replace(/ /g, '_')}`,
187
+ data: buildNodeData({ name: node.name, label: labelToRender, type: 'event', maxWidth: nodeMaxWidth, ...nodeStyles }),
188
+ style: {
189
+ border: `2px solid ${subscribeColor}`,
190
+ width: nodeWidth,
191
+ ...nodeStyles,
192
+ },
193
+ type: 'input',
194
+ position,
195
+ };
196
+ });
197
+
198
+ const serviceNode: Node = {
199
+ id: serviceNameAsNodeID,
200
+ data: buildNodeData({
201
+ name: serviceName,
202
+ label: getNodeLabel({ type: 'service', label: serviceName, includeIcon: includeNodeIcons }),
203
+ type: 'service',
204
+ maxWidth: calcWidth(serviceName),
205
+ }),
206
+ style: {
207
+ border: `2px solid ${rootNodeColor}`,
208
+ width: calcWidth(serviceName),
209
+ ...nodeStyles,
210
+ },
211
+ position,
212
+ };
213
+
214
+ // Build connections
215
+ const publishesEdges: Edge[] = publishes.map((node) =>
216
+ buildNodeEdge({
217
+ id: `ecp-${node.name.replace(/ /g, '_')}`,
218
+ source: serviceNameAsNodeID,
219
+ target: `pub-${node.name.replace(/ /g, '_')}`,
220
+ isAnimated,
221
+ label: includeEdgeLabels ? 'publishes' : '',
222
+ })
223
+ );
224
+
225
+ const subscribesEdges: Edge[] = subscribes.map((node) =>
226
+ buildNodeEdge({
227
+ id: `esc-${node.name.replace(/ /g, '_')}`,
228
+ target: serviceNameAsNodeID,
229
+ source: `sub-${node.name.replace(/ /g, '_')}`,
230
+ isAnimated,
231
+ label: includeEdgeLabels ? 'subscribed by' : '',
232
+ })
233
+ );
234
+
235
+ // Merge nodes in order
236
+ const elements: (Node | Edge)[] = [...subscribesNodes, serviceNode, ...publishesNodes, ...publishesEdges, ...subscribesEdges];
237
+ return elements;
238
+ };
@@ -0,0 +1,57 @@
1
+ import { isNode, Elements, Position } from 'react-flow-renderer';
2
+ import dagre from 'dagre';
3
+
4
+ const nodeDefaultWidth = 150;
5
+ const nodeDefaultHeight = 36;
6
+ const offset = 48;
7
+ const verticalOffset = offset / 1.5;
8
+
9
+ export default function createGraphLayout(elements: Elements, isHorizontal: boolean): Elements {
10
+ const dagreGraph = new dagre.graphlib.Graph();
11
+
12
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
13
+ dagreGraph.setGraph({ rankdir: 'LR', ranksep: offset * 2, nodesep: verticalOffset });
14
+
15
+ elements.forEach((element) => {
16
+ if (isNode(element)) {
17
+ // eslint-disable-next-line no-underscore-dangle
18
+ const nodeWidth = element.__rf?.width ? element.__rf?.width : element.data?.width;
19
+ dagreGraph.setNode(element.id, {
20
+ width: nodeWidth || nodeDefaultWidth,
21
+ // eslint-disable-next-line no-underscore-dangle
22
+ height: element.__rf?.height || nodeDefaultHeight,
23
+ });
24
+ } else {
25
+ dagreGraph.setEdge(element.source, element.target);
26
+ }
27
+ });
28
+
29
+ // Calculate the layout, to get the node positions with their widths and heights
30
+ dagre.layout(dagreGraph);
31
+
32
+ return elements.map((element) => {
33
+ if (isNode(element)) {
34
+ const node = dagreGraph.node(element.id);
35
+ element.targetPosition = isHorizontal ? Position.Left : Position.Top;
36
+ element.sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
37
+ element.position = {
38
+ x: offset / 2 + node.x - (element?.data?.maxWidth || node.width) / 2,
39
+ y: node.y - node.height / 2,
40
+ };
41
+ }
42
+ return element;
43
+ });
44
+ }
45
+
46
+ // Helper - ReactFlow canvas height calculator
47
+ export const calcCanvasHeight = (data, type): number => {
48
+ const minHeight = 300;
49
+ const nodeSpacing = nodeDefaultHeight + verticalOffset;
50
+ let nodesHeight = 0;
51
+ if (type === 'event') {
52
+ nodesHeight = Math.max(data.producers.length, data.consumers.length) * nodeSpacing;
53
+ } else {
54
+ nodesHeight = Math.max(data.publishes.length, data.subscribes.length) * nodeSpacing;
55
+ }
56
+ return Math.max(minHeight, nodesHeight);
57
+ };
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { ServerIcon } from '@heroicons/react/outline/';
3
+ import { MailIcon } from '@heroicons/react/solid/';
4
+
5
+ function Node({ type, label }: any) {
6
+ const Icon = type === 'event' ? MailIcon : ServerIcon;
7
+ return (
8
+ <div>
9
+ <Icon className="h-3 w-3 text-gray-700 inline-block mr-1 -mt-0.5" />
10
+ <span className="text-gray-700">{label}</span>
11
+ </div>
12
+ );
13
+ }
14
+
15
+ export default Node;
@@ -0,0 +1,180 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import Link from 'next/link';
3
+ import ReactFlow, { Controls, ReactFlowProvider, useStoreState, Background, useZoomPanHelper } from 'react-flow-renderer';
4
+ import { Event, Service } from '@eventcatalog/types';
5
+ import { getEventElements, getServiceElements } from './GraphElements';
6
+ import createGraphLayout, { calcCanvasHeight } from './GraphLayout';
7
+
8
+ interface NodeGraphBuilderProps {
9
+ data: Event | Service;
10
+ source: 'event' | 'service';
11
+ title?: string;
12
+ subtitle?: string;
13
+ rootNodeColor?: string;
14
+ maxZoom?: number;
15
+ fitView?: boolean;
16
+ zoomOnScroll?: boolean;
17
+ isAnimated?: boolean;
18
+ isDraggable?: boolean;
19
+ isHorizontal?: boolean;
20
+ includeBackground?: boolean;
21
+ includeEdgeLabels?: boolean;
22
+ includeNodeIcons?: boolean;
23
+ }
24
+
25
+ interface NodeGraphProps extends NodeGraphBuilderProps {
26
+ maxHeight?: number | string;
27
+ renderWithBorder?: boolean;
28
+ }
29
+
30
+ // NodeGraphBuilder component wrapping ReactFlow
31
+ function NodeGraphBuilder({
32
+ data,
33
+ source,
34
+ rootNodeColor,
35
+ maxZoom = 10,
36
+ isAnimated = true,
37
+ fitView = true,
38
+ zoomOnScroll = false,
39
+ isDraggable = false,
40
+ isHorizontal = true,
41
+ includeBackground = false,
42
+ includeEdgeLabels = false,
43
+ includeNodeIcons,
44
+ title,
45
+ subtitle,
46
+ }: NodeGraphBuilderProps) {
47
+ const getElements = () => {
48
+ if (source === 'event') {
49
+ return getEventElements(data as Event, rootNodeColor, isAnimated, includeEdgeLabels, includeNodeIcons);
50
+ }
51
+ return getServiceElements(data as Service, rootNodeColor, isAnimated, includeEdgeLabels, includeNodeIcons);
52
+ };
53
+
54
+ // Initialize graph layout
55
+ const isInitializedRef = useRef(false);
56
+ const nodes = useStoreState((state) => state.nodes);
57
+ const edges = useStoreState((state) => state.edges);
58
+ const { fitView: resetView } = useZoomPanHelper();
59
+
60
+ // Calculate initial element layout
61
+ const graphElements = createGraphLayout(getElements(), isHorizontal);
62
+ const [elements, setElements] = useState(graphElements);
63
+
64
+ // if data changes, reset the elements
65
+ useEffect(() => {
66
+ const updatedElements = createGraphLayout(getElements(), isHorizontal);
67
+ setElements(updatedElements);
68
+ setTimeout(() => {
69
+ resetView();
70
+ }, 1);
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ }, [data]);
73
+
74
+ // Rerender graph layout to get rendered width/height for nodes/edges
75
+ useEffect(() => {
76
+ if (
77
+ isInitializedRef.current === false &&
78
+ nodes.length > 0 &&
79
+ // eslint-disable-next-line no-underscore-dangle
80
+ nodes?.[0]?.__rf.width != null
81
+ ) {
82
+ // Calculate element layout
83
+ const updateElements = () => {
84
+ const updatedElements = createGraphLayout([...nodes, ...edges], isHorizontal);
85
+ setElements(updatedElements);
86
+ isInitializedRef.current = true;
87
+ };
88
+ updateElements();
89
+ }
90
+ }, [nodes, edges, isInitializedRef, isHorizontal]);
91
+
92
+ // ReactFlow operations
93
+ const onElementClick = (event, element) => window.open(element.data.link, '_self');
94
+ const onLoad = useCallback(
95
+ (reactFlowInstance) => {
96
+ if (fitView) {
97
+ reactFlowInstance.fitView();
98
+ }
99
+ },
100
+ [fitView]
101
+ );
102
+
103
+ return (
104
+ <ReactFlow
105
+ elements={elements}
106
+ onLoad={onLoad}
107
+ onElementClick={onElementClick}
108
+ nodesDraggable={isDraggable}
109
+ zoomOnScroll={zoomOnScroll}
110
+ maxZoom={maxZoom}
111
+ >
112
+ {title && (
113
+ <div className="absolute top-4 right-4 bg-white z-10 text-lg px-4 py-2 space-x-2">
114
+ <span className=" font-bold">{title}</span>
115
+ {subtitle && (
116
+ <>
117
+ <span className="text-gray-200">|</span>
118
+ <span className="font-light">{subtitle}</span>
119
+ </>
120
+ )}
121
+ </div>
122
+ )}
123
+ <Controls className="block absolute top-5 react-flow__controls-no-shadow" />
124
+ {includeBackground && <Background color="#c1c1c1" gap={8} />}
125
+ </ReactFlow>
126
+ );
127
+ }
128
+
129
+ // NodeGraph wrapping NodeGraphBuilder Component
130
+ function NodeGraph({
131
+ data,
132
+ source,
133
+ rootNodeColor,
134
+ maxHeight,
135
+ maxZoom,
136
+ fitView,
137
+ zoomOnScroll,
138
+ isAnimated,
139
+ isDraggable,
140
+ isHorizontal,
141
+ includeBackground,
142
+ renderWithBorder = true,
143
+ title,
144
+ subtitle,
145
+ includeEdgeLabels,
146
+ includeNodeIcons,
147
+ }: NodeGraphProps) {
148
+ // Set dynamic height of node graph
149
+ const dynamicHeight = maxHeight || calcCanvasHeight(data, source);
150
+
151
+ const borderClasses = `border-dashed border-2 border-slate-300`;
152
+
153
+ return (
154
+ <div className={`node-graph w-full h-screen ${renderWithBorder ? borderClasses : ''}`} style={{ height: dynamicHeight }}>
155
+ <ReactFlowProvider>
156
+ <NodeGraphBuilder
157
+ source={source}
158
+ data={data}
159
+ rootNodeColor={rootNodeColor}
160
+ maxZoom={maxZoom}
161
+ fitView={fitView}
162
+ includeBackground={includeBackground}
163
+ zoomOnScroll={zoomOnScroll}
164
+ isAnimated={isAnimated}
165
+ isDraggable={isDraggable}
166
+ isHorizontal={isHorizontal}
167
+ includeEdgeLabels={includeEdgeLabels}
168
+ includeNodeIcons={includeNodeIcons}
169
+ title={title}
170
+ subtitle={subtitle}
171
+ />
172
+ </ReactFlowProvider>
173
+ <Link href={`/visualiser?type=${source}&name=${data.name}`}>
174
+ <a className="block text-right underline text-xs mt-4">Open in Visualiser &rarr;</a>
175
+ </Link>
176
+ </div>
177
+ );
178
+ }
179
+
180
+ export default NodeGraph;