@elyx-code/editor-ui 0.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 (452) hide show
  1. package/README.md +2 -0
  2. package/package.json +109 -0
  3. package/src/App.tsx +31 -0
  4. package/src/Router.tsx +115 -0
  5. package/src/__mocks__/defaultModuleMock.ts +1 -0
  6. package/src/__mocks__/fileMock.ts +1 -0
  7. package/src/__mocks__/styleMock.ts +1 -0
  8. package/src/assets/Clock-11.1s-18px.svg +16 -0
  9. package/src/assets/Clock-11.1s-28px.svg +16 -0
  10. package/src/assets/authentication.svg +1 -0
  11. package/src/assets/canvas-backdrop-0.png +0 -0
  12. package/src/assets/canvas-backdrop-1.png +0 -0
  13. package/src/assets/canvas-backdrop-2.png +0 -0
  14. package/src/assets/canvas-backdrop-3.png +0 -0
  15. package/src/assets/canvas-backdrop-4.png +0 -0
  16. package/src/assets/canvas-backdrop-5.png +0 -0
  17. package/src/assets/canvas-backdrop.png +0 -0
  18. package/src/assets/checkmark-animation.gif +0 -0
  19. package/src/assets/checkmark-animation.mp4 +0 -0
  20. package/src/assets/code-formatting/format-black.svg +6 -0
  21. package/src/assets/code-formatting/format-dark-grey.svg +6 -0
  22. package/src/assets/code-formatting/format-light-grey.svg +6 -0
  23. package/src/assets/code-formatting/format-white.svg +6 -0
  24. package/src/assets/code-formatting/inline-black.svg +5 -0
  25. package/src/assets/code-formatting/inline-dark-grey.svg +5 -0
  26. package/src/assets/code-formatting/inline-light-grey.svg +5 -0
  27. package/src/assets/code-formatting/inline-white.svg +5 -0
  28. package/src/assets/contained-logo-full-word.png +0 -0
  29. package/src/assets/cron-job-color.png +0 -0
  30. package/src/assets/cron-job.png +0 -0
  31. package/src/assets/database-table-color.png +0 -0
  32. package/src/assets/database-table.png +0 -0
  33. package/src/assets/datatype-icons/black/any.svg +1 -0
  34. package/src/assets/datatype-icons/black/binary.svg +1 -0
  35. package/src/assets/datatype-icons/black/boolean.svg +3 -0
  36. package/src/assets/datatype-icons/black/date-time.svg +3 -0
  37. package/src/assets/datatype-icons/black/definition-entity.svg +6 -0
  38. package/src/assets/datatype-icons/black/key-file.svg +1 -0
  39. package/src/assets/datatype-icons/black/list.svg +3 -0
  40. package/src/assets/datatype-icons/black/null.svg +3 -0
  41. package/src/assets/datatype-icons/black/number.svg +13 -0
  42. package/src/assets/datatype-icons/black/project.svg +12 -0
  43. package/src/assets/datatype-icons/black/sql-program.svg +2 -0
  44. package/src/assets/datatype-icons/black/text.svg +3 -0
  45. package/src/assets/datatype-icons/black/unknown.svg +3 -0
  46. package/src/assets/datatype-icons/black/uuid.svg +4 -0
  47. package/src/assets/datatype-icons/black/void.svg +1 -0
  48. package/src/assets/datatype-icons/dark-grey/any.svg +1 -0
  49. package/src/assets/datatype-icons/dark-grey/boolean.svg +3 -0
  50. package/src/assets/datatype-icons/dark-grey/date-time.svg +3 -0
  51. package/src/assets/datatype-icons/dark-grey/definition-entity.svg +6 -0
  52. package/src/assets/datatype-icons/dark-grey/list.svg +3 -0
  53. package/src/assets/datatype-icons/dark-grey/null.svg +3 -0
  54. package/src/assets/datatype-icons/dark-grey/number.svg +13 -0
  55. package/src/assets/datatype-icons/dark-grey/project.svg +12 -0
  56. package/src/assets/datatype-icons/dark-grey/sql-program.svg +2 -0
  57. package/src/assets/datatype-icons/dark-grey/text.svg +3 -0
  58. package/src/assets/datatype-icons/dark-grey/unknown.svg +3 -0
  59. package/src/assets/datatype-icons/dark-grey/uuid.svg +4 -0
  60. package/src/assets/datatype-icons/dark-grey/void.svg +1 -0
  61. package/src/assets/datatype-icons/light-grey/any.svg +1 -0
  62. package/src/assets/datatype-icons/light-grey/boolean.svg +3 -0
  63. package/src/assets/datatype-icons/light-grey/date-time.svg +3 -0
  64. package/src/assets/datatype-icons/light-grey/definition-entity.svg +6 -0
  65. package/src/assets/datatype-icons/light-grey/list.svg +3 -0
  66. package/src/assets/datatype-icons/light-grey/null.svg +3 -0
  67. package/src/assets/datatype-icons/light-grey/number.svg +13 -0
  68. package/src/assets/datatype-icons/light-grey/project.svg +12 -0
  69. package/src/assets/datatype-icons/light-grey/sql-program.svg +2 -0
  70. package/src/assets/datatype-icons/light-grey/text.svg +3 -0
  71. package/src/assets/datatype-icons/light-grey/unknown.svg +3 -0
  72. package/src/assets/datatype-icons/light-grey/uuid.svg +4 -0
  73. package/src/assets/datatype-icons/light-grey/void.svg +1 -0
  74. package/src/assets/edit.png +0 -0
  75. package/src/assets/execution.svg +13 -0
  76. package/src/assets/favicon.svg +14 -0
  77. package/src/assets/file-search.svg +1 -0
  78. package/src/assets/http-endpoint.png +0 -0
  79. package/src/assets/image-input-placeholder.png +0 -0
  80. package/src/assets/logo-full-word-white.png +0 -0
  81. package/src/assets/logo-full-word.png +0 -0
  82. package/src/assets/password.svg +85 -0
  83. package/src/assets/pencil.png +0 -0
  84. package/src/assets/publish-project-rich-icon-2.svg +1 -0
  85. package/src/assets/publish-project-rich-icon.svg +1 -0
  86. package/src/assets/relational-database.png +0 -0
  87. package/src/assets/resources.svg +3 -0
  88. package/src/assets/resume-icon-14px.png +0 -0
  89. package/src/assets/server.png +0 -0
  90. package/src/assets/small-status/checkmark.svg +4 -0
  91. package/src/assets/small-status/error.svg +4 -0
  92. package/src/assets/small-status/loading.svg +4 -0
  93. package/src/assets/small-status/skipped.svg +11 -0
  94. package/src/assets/sql-connection-config.svg +1 -0
  95. package/src/assets/sql-row-transformer.svg +1 -0
  96. package/src/assets/ssl-certificate-config.svg +1 -0
  97. package/src/assets/sync.svg +1 -0
  98. package/src/assets/testing-logic-icon.svg +1 -0
  99. package/src/assets/versions.svg +25 -0
  100. package/src/assets/visual-programming-icon.svg +1 -0
  101. package/src/assets/warning-sign-24px.png +0 -0
  102. package/src/auth/index.ts +318 -0
  103. package/src/components/DialogLoader.tsx +94 -0
  104. package/src/components/EntityDialogHeader.tsx +110 -0
  105. package/src/components/EntityDialogSectionHeader.tsx +214 -0
  106. package/src/components/GalleryAddExternalIntegrationInfoDialog.tsx +87 -0
  107. package/src/components/GenerateProjectStartingLogicPromptDialog.tsx +281 -0
  108. package/src/components/LegacyRouteRedirector.tsx +55 -0
  109. package/src/components/ProPlanChip.tsx +23 -0
  110. package/src/components/ReportBugDialog.tsx +412 -0
  111. package/src/components/RequestIntegrationAccessDialog.tsx +261 -0
  112. package/src/components/UseTemplateProjectDialog.tsx +193 -0
  113. package/src/components/WorkspaceLayout.tsx +152 -0
  114. package/src/components/animated-svg/AnimatedCheckmark.tsx +41 -0
  115. package/src/components/animated-svg/AnimatedCrossmark.tsx +51 -0
  116. package/src/components/animated-svg/AnimatedEmailSending.tsx +38 -0
  117. package/src/components/animated-svg/AnimatedLoading.tsx +72 -0
  118. package/src/components/animated-svg/animated-svg.css +239 -0
  119. package/src/components/canvas/Canvas.tsx +16 -0
  120. package/src/components/canvas/CreateEntityMenu.tsx +2020 -0
  121. package/src/components/canvas/canvas.css +10 -0
  122. package/src/components/canvas/create-entity-menu.css +579 -0
  123. package/src/components/canvas-search/CanvasSearch.tsx +501 -0
  124. package/src/components/canvas-search/canvas-search.css +126 -0
  125. package/src/components/canvas-settings-menu/CanvasSettingsMenuButton.tsx +515 -0
  126. package/src/components/canvas-settings-menu/canvas-settings-menu.css +96 -0
  127. package/src/components/circular-image-upload/CircularImageUpload.tsx +113 -0
  128. package/src/components/circular-image-upload/circular-image-upload.css +69 -0
  129. package/src/components/costs/CostsDialog.tsx +459 -0
  130. package/src/components/data-type/DataTypeBuilder.tsx +3127 -0
  131. package/src/components/data-type/data-type-builder.css +45 -0
  132. package/src/components/dialogs/BetaAcknowledgeDialog.tsx +43 -0
  133. package/src/components/dialogs/ComplexDataDialog.tsx +458 -0
  134. package/src/components/dialogs/CronBuilderDialog.tsx +2145 -0
  135. package/src/components/dialogs/ExternalIntegrationConnections.tsx +565 -0
  136. package/src/components/dialogs/JsonEditorDialog.tsx +1392 -0
  137. package/src/components/dialogs/StringEditorDialog.tsx +268 -0
  138. package/src/components/dialogs/argument-declaration/ArgumentDeclaration.tsx +1167 -0
  139. package/src/components/dialogs/argument-declaration/ArgumentDeclarationDialogContent.tsx +128 -0
  140. package/src/components/dialogs/beta-dialog.css +165 -0
  141. package/src/components/dialogs/condition/Condition.tsx +431 -0
  142. package/src/components/dialogs/condition/ConditionDialogContent.tsx +126 -0
  143. package/src/components/dialogs/definition-entity/DefinitionEntityDialogContent.tsx +973 -0
  144. package/src/components/dialogs/function-call/FunctionCall.tsx +442 -0
  145. package/src/components/dialogs/function-call/FunctionCallDialogContent.tsx +126 -0
  146. package/src/components/dialogs/function-declaration/FunctionDeclaration.tsx +926 -0
  147. package/src/components/dialogs/function-declaration/FunctionDeclarationDialogContent.tsx +124 -0
  148. package/src/components/dialogs/generating-project-starting-logic-overlay/GeneratingProjectStartingLogicOverlay.tsx +176 -0
  149. package/src/components/dialogs/generating-project-starting-logic-overlay/generating-project-starting-logic-overlay.css +13 -0
  150. package/src/components/dialogs/global-event/GlobalEvent.tsx +475 -0
  151. package/src/components/dialogs/global-event/GlobalEventDialogContent.tsx +126 -0
  152. package/src/components/dialogs/help/HelpDialog.tsx +217 -0
  153. package/src/components/dialogs/help/HelpDilalogHomeContent.tsx +178 -0
  154. package/src/components/dialogs/help/help-dialog.css +116 -0
  155. package/src/components/dialogs/help/help-icon/HelpIconButton.tsx +41 -0
  156. package/src/components/dialogs/help/help-icon/help-icon.css +9 -0
  157. package/src/components/dialogs/input-map/InputMap.tsx +635 -0
  158. package/src/components/dialogs/input-map/InputMapDialogContent.tsx +126 -0
  159. package/src/components/dialogs/json-editor-dialog.css +4 -0
  160. package/src/components/dialogs/loop/Loop.tsx +650 -0
  161. package/src/components/dialogs/loop/LoopDialogContent.tsx +122 -0
  162. package/src/components/dialogs/operation/Operation.tsx +440 -0
  163. package/src/components/dialogs/operation/OperationDialogContent.tsx +126 -0
  164. package/src/components/dialogs/output-map/OutputMap.tsx +536 -0
  165. package/src/components/dialogs/output-map/OutputMapDialogContent.tsx +126 -0
  166. package/src/components/dialogs/property/Property.tsx +1490 -0
  167. package/src/components/dialogs/property/PropertyDialogContent.tsx +106 -0
  168. package/src/components/dialogs/search-statement/ColumnSelector.tsx +334 -0
  169. package/src/components/dialogs/search-statement/ConditionBuilder.tsx +750 -0
  170. package/src/components/dialogs/search-statement/DataAggregationSection.tsx +621 -0
  171. package/src/components/dialogs/search-statement/DataSourceSelection.tsx +734 -0
  172. package/src/components/dialogs/search-statement/EntityMetadataSection.tsx +135 -0
  173. package/src/components/dialogs/search-statement/FilterConditionsSection.tsx +151 -0
  174. package/src/components/dialogs/search-statement/InlineInputMap.tsx +153 -0
  175. package/src/components/dialogs/search-statement/LiteralValue.tsx +616 -0
  176. package/src/components/dialogs/search-statement/MainSourceAndInputsSection.tsx +271 -0
  177. package/src/components/dialogs/search-statement/NestedSearchStatementBuilder.tsx +170 -0
  178. package/src/components/dialogs/search-statement/OutputFormatSection.tsx +1779 -0
  179. package/src/components/dialogs/search-statement/ResultsSection.tsx +344 -0
  180. package/src/components/dialogs/search-statement/SearchStatementBuilder.tsx +251 -0
  181. package/src/components/dialogs/search-statement/SearchStatementDialogContent.tsx +398 -0
  182. package/src/components/dialogs/search-statement/ValueSelector.tsx +766 -0
  183. package/src/components/dialogs/search-statement/search-statement-context.tsx +1630 -0
  184. package/src/components/dialogs/search-statement/search-statement-dialog.css +56 -0
  185. package/src/components/dialogs/search-statement/test.sql +111 -0
  186. package/src/components/dialogs/value-descriptor/ValueDescriptor.tsx +824 -0
  187. package/src/components/dialogs/value-descriptor/ValueDescriptorDialogContent.tsx +124 -0
  188. package/src/components/dialogs/variable-declaration/VariableDeclaration.tsx +836 -0
  189. package/src/components/dialogs/variable-declaration/VariableDeclarationDialogContent.tsx +106 -0
  190. package/src/components/dialogs/variable-instance/VariableInstance.tsx +443 -0
  191. package/src/components/dialogs/variable-instance/VariableInstanceDialogContent.tsx +124 -0
  192. package/src/components/draggable-entity-card/ArgumentDeclaration.tsx +736 -0
  193. package/src/components/draggable-entity-card/CollapseEntityButton.tsx +170 -0
  194. package/src/components/draggable-entity-card/ConditionCard.tsx +1062 -0
  195. package/src/components/draggable-entity-card/ConnectionDeleteButton.tsx +309 -0
  196. package/src/components/draggable-entity-card/DataTypeIcon.tsx +624 -0
  197. package/src/components/draggable-entity-card/DraggableEntityCard.tsx +617 -0
  198. package/src/components/draggable-entity-card/ErrorMapProperty.tsx +464 -0
  199. package/src/components/draggable-entity-card/EventCard.tsx +700 -0
  200. package/src/components/draggable-entity-card/ExecutionInProgressValue.tsx +327 -0
  201. package/src/components/draggable-entity-card/FunctionDeclarationCard.tsx +819 -0
  202. package/src/components/draggable-entity-card/InputMapProperty.tsx +1067 -0
  203. package/src/components/draggable-entity-card/InternalCall.tsx +978 -0
  204. package/src/components/draggable-entity-card/InternalCallExecutionNode.tsx +643 -0
  205. package/src/components/draggable-entity-card/LogicScopeCallerNode.tsx +262 -0
  206. package/src/components/draggable-entity-card/LoopCard.tsx +791 -0
  207. package/src/components/draggable-entity-card/MainValueInput.tsx +523 -0
  208. package/src/components/draggable-entity-card/MainValueOutput.tsx +458 -0
  209. package/src/components/draggable-entity-card/MethodDeclaration.tsx +1088 -0
  210. package/src/components/draggable-entity-card/NestedCondition.tsx +1025 -0
  211. package/src/components/draggable-entity-card/OutputMapProperty.tsx +843 -0
  212. package/src/components/draggable-entity-card/PassthroughEntityCard.tsx +1247 -0
  213. package/src/components/draggable-entity-card/ReturnedError.tsx +549 -0
  214. package/src/components/draggable-entity-card/SmallSuccessFailureNodes.tsx +523 -0
  215. package/src/components/draggable-entity-card/SuccessFailureNodes.tsx +509 -0
  216. package/src/components/draggable-entity-card/TestEntityButton.tsx +946 -0
  217. package/src/components/draggable-entity-card/TestMenu.tsx +523 -0
  218. package/src/components/draggable-entity-card/TestMenuValidationDropdown.tsx +84 -0
  219. package/src/components/draggable-entity-card/UnreachableMarker.tsx +114 -0
  220. package/src/components/draggable-entity-card/VariableCard.tsx +1577 -0
  221. package/src/components/draggable-entity-card/VariableScopeMarker.tsx +117 -0
  222. package/src/components/draggable-entity-card/collapse-entity-button.css +44 -0
  223. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityCard.tsx +1181 -0
  224. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityIcon.tsx +36 -0
  225. package/src/components/draggable-entity-card/definition-entity/DefinitionEntityProperty.tsx +478 -0
  226. package/src/components/draggable-entity-card/definition-entity/DynamicFooterActions.tsx +112 -0
  227. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/ExportCredentialsFooterAction.tsx +461 -0
  228. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/RestablishConnectionFooterAction.tsx +199 -0
  229. package/src/components/draggable-entity-card/definition-entity/actions/external-integration-connection/restablish-connection-footer-action.css +85 -0
  230. package/src/components/draggable-entity-card/definition-entity/actions/google-drive/GoogleDriveFilePickerAPIFooterAction.tsx +277 -0
  231. package/src/components/draggable-entity-card/definition-entity/actions/google-drive/google-drive-file-picker-api-footer-action.css +107 -0
  232. package/src/components/draggable-entity-card/definition-entity/actions/persisted-entity/DatabaseFooterAction.tsx +452 -0
  233. package/src/components/draggable-entity-card/definition-entity/actions/persisted-entity/database-footer-action.css +86 -0
  234. package/src/components/draggable-entity-card/definition-entity/definition-entity-card.css +17 -0
  235. package/src/components/draggable-entity-card/draggable-entity-card.css +1140 -0
  236. package/src/components/draggable-entity-card/entity-locked-icon/EntityLockedIcon.tsx +133 -0
  237. package/src/components/draggable-entity-card/entity-locked-icon/entity-locked.css +8 -0
  238. package/src/components/draggable-entity-card/expand-properties-icon-button/ExpandPropertiesIconButton.tsx +84 -0
  239. package/src/components/draggable-entity-card/expand-properties-icon-button/expand-properties-icon-button.css +21 -0
  240. package/src/components/draggable-entity-card/implement-entity-icon/ImplementEntityIcon.tsx +74 -0
  241. package/src/components/draggable-entity-card/implement-entity-icon/implement-entity-icon.css +13 -0
  242. package/src/components/draggable-entity-card/logic-error/LogicErrorIconMenu.tsx +424 -0
  243. package/src/components/draggable-entity-card/logic-error/logic-error.css +23 -0
  244. package/src/components/draggable-entity-card/new-card-input-button/NewCardInputButton.tsx +193 -0
  245. package/src/components/draggable-entity-card/new-card-input-button/NewDynamicInputButton.tsx +214 -0
  246. package/src/components/draggable-entity-card/new-card-input-button/new-card-input-button.css +71 -0
  247. package/src/components/draggable-entity-card/new-card-output-button/NewCardOutputButton.tsx +192 -0
  248. package/src/components/draggable-entity-card/new-card-output-button/new-card-output-button.css +71 -0
  249. package/src/components/draggable-entity-card/termination-statement/TerminationStatementCard.tsx +1543 -0
  250. package/src/components/draggable-entity-card/termination-statement/termination-statement-card.css +17 -0
  251. package/src/components/draggable-entity-card/test-entity-button.css +55 -0
  252. package/src/components/draggable-entity-card/test-menu.css +181 -0
  253. package/src/components/draggable-entity-card/unreachable-marker.css +43 -0
  254. package/src/components/draggable-entity-card/variable-scope-marker.css +22 -0
  255. package/src/components/dynamic-value/DynamicValue.tsx +2395 -0
  256. package/src/components/dynamic-value/DynamicValueEntry.tsx +1957 -0
  257. package/src/components/dynamic-value/dynamic-value.css +230 -0
  258. package/src/components/editor/ElyxMonacoEditor.tsx +38 -0
  259. package/src/components/entity-error/EntityErrorListItem.tsx +47 -0
  260. package/src/components/entity-error/entity-error.css +198 -0
  261. package/src/components/entity-icon/EntityIcon.tsx +292 -0
  262. package/src/components/entity-icon/entity-icon.css +39 -0
  263. package/src/components/gallery-card/CreateNewProject.tsx +222 -0
  264. package/src/components/gallery-card/GalleryCard.tsx +171 -0
  265. package/src/components/gallery-card/MarketplaceCard.tsx +87 -0
  266. package/src/components/gallery-card/ProjectDuplicationCard.tsx +575 -0
  267. package/src/components/gallery-card/gallery-card.css +25 -0
  268. package/src/components/notifications/NotificationsIconButton.tsx +124 -0
  269. package/src/components/notifications/NotificationsPanel.tsx +385 -0
  270. package/src/components/notifications/notifications.css +189 -0
  271. package/src/components/online-users/LocalOnlineUsers.tsx +175 -0
  272. package/src/components/online-users/PageOnlineUsers.tsx +297 -0
  273. package/src/components/online-users/online-users.css +72 -0
  274. package/src/components/page-backdrop/PageBackdrop.tsx +8 -0
  275. package/src/components/page-backdrop/page-backdrop.css +7 -0
  276. package/src/components/project-configuration/DeleteProjectConfirmationDialog.tsx +134 -0
  277. package/src/components/project-configuration/ProjectConfigurationDialog.tsx +972 -0
  278. package/src/components/project-configuration/ProjectDataForm.tsx +121 -0
  279. package/src/components/project-configuration/UnpublishProjectConfirmationDialog.tsx +162 -0
  280. package/src/components/project-configuration/project-configuration-content.css +209 -0
  281. package/src/components/project-name/ProjectName.tsx +2025 -0
  282. package/src/components/project-name/project-name.css +599 -0
  283. package/src/components/publishing/Publication.tsx +133 -0
  284. package/src/components/publishing/history/PublicationHistoryContent.tsx +414 -0
  285. package/src/components/publishing/history/PublicationHistoryDialog.tsx +234 -0
  286. package/src/components/publishing/preview/PublicationPreviewDialog.tsx +1158 -0
  287. package/src/components/publishing/preview/PublishingPriceForecast.tsx +160 -0
  288. package/src/components/publishing/preview/PublishingResourcesDetails.tsx +91 -0
  289. package/src/components/publishing/publication-sequence/PublishingSequenceContent.tsx +375 -0
  290. package/src/components/publishing/publication-sequence/PublishingSequenceDialog.tsx +344 -0
  291. package/src/components/publishing/publishing-dialog.css +142 -0
  292. package/src/components/publishing/utils.ts +227 -0
  293. package/src/components/resources/ResourcesDialog.tsx +591 -0
  294. package/src/components/resources/UpgradeBanner.tsx +102 -0
  295. package/src/components/resources/codebase/CodebaseDetails.tsx +156 -0
  296. package/src/components/resources/cron-job/CronJobsList.tsx +532 -0
  297. package/src/components/resources/functions/FunctionsList.tsx +454 -0
  298. package/src/components/resources/http-api/HttpAPI.tsx +566 -0
  299. package/src/components/resources/http-api/HttpAPIClientModule.tsx +37 -0
  300. package/src/components/resources/logs/LogsViewer.tsx +768 -0
  301. package/src/components/resources/query.ts +74 -0
  302. package/src/components/resources/relational-database/DatabaseTable.tsx +905 -0
  303. package/src/components/resources/relational-database/RelationalDatabase.tsx +83 -0
  304. package/src/components/resources/relational-database/RelationalDatabaseSecrets.tsx +361 -0
  305. package/src/components/resources/resources-dialog.css +74 -0
  306. package/src/components/test-relational-database/DatabaseTable.tsx +913 -0
  307. package/src/components/test-relational-database/TestDatabaseDialogContent.tsx +670 -0
  308. package/src/components/test-relational-database/query.ts +74 -0
  309. package/src/components/toolbar/ToolBar.tsx +236 -0
  310. package/src/components/toolbar/toolbar.css +78 -0
  311. package/src/components/transaction-history/TransactionHistoryDialog.tsx +268 -0
  312. package/src/components/user/CurrentUserAvatar.tsx +65 -0
  313. package/src/components/user/UserChip.tsx +62 -0
  314. package/src/components/user/user.css +39 -0
  315. package/src/components/user-profile/ChangePasswordForm.tsx +67 -0
  316. package/src/components/user-profile/OwnUserProfileContent.tsx +665 -0
  317. package/src/components/user-profile/PublicUserProfileContent.tsx +99 -0
  318. package/src/components/user-profile/UserDataForm.tsx +75 -0
  319. package/src/components/user-profile/UserProfileDialog.tsx +110 -0
  320. package/src/components/user-profile/user-profile-content.css +25 -0
  321. package/src/config.ts +130 -0
  322. package/src/globals.d.ts +13 -0
  323. package/src/index.html +27 -0
  324. package/src/index.tsx +23 -0
  325. package/src/lib/badge/Badge.tsx +35 -0
  326. package/src/lib/badge/badge.css +32 -0
  327. package/src/lib/button/Button.tsx +129 -0
  328. package/src/lib/button/button.css +145 -0
  329. package/src/lib/canvas/canvas-undo-redo.ts +263 -0
  330. package/src/lib/canvas/defs.ts +170 -0
  331. package/src/lib/canvas/index.test.ts +189 -0
  332. package/src/lib/canvas/index.ts +6999 -0
  333. package/src/lib/canvas/utils.ts +59 -0
  334. package/src/lib/card/Card.tsx +62 -0
  335. package/src/lib/card/LoadingCard.tsx +82 -0
  336. package/src/lib/card/card.css +259 -0
  337. package/src/lib/chip/Chip.tsx +79 -0
  338. package/src/lib/chip/chip.css +0 -0
  339. package/src/lib/dialog/Dialog.tsx +122 -0
  340. package/src/lib/dialog/SmallDialog.tsx +61 -0
  341. package/src/lib/dialog/dialog.css +40 -0
  342. package/src/lib/display-data-structure/index.tsx +21 -0
  343. package/src/lib/dropdown/CanvasDropdownMenuCard.tsx +68 -0
  344. package/src/lib/dropdown/CanvasDropdownMenuCardOption.tsx +136 -0
  345. package/src/lib/dropdown/DropdownButton.tsx +104 -0
  346. package/src/lib/dropdown/DropdownMenuCard.tsx +324 -0
  347. package/src/lib/dropdown/DropdownMenuPopup.tsx +27 -0
  348. package/src/lib/dropdown/dropdown-button.css +76 -0
  349. package/src/lib/dropdown/dropdown-menu.css +151 -0
  350. package/src/lib/json-editor/RawJsonEditor.tsx +137 -0
  351. package/src/lib/json-editor/json-editor.css +35 -0
  352. package/src/lib/loader/Loader.tsx +120 -0
  353. package/src/lib/loader/loader.css +38 -0
  354. package/src/lib/pagination/Pagination.tsx +64 -0
  355. package/src/lib/popup/CanvasPopupBaseComponent.tsx +103 -0
  356. package/src/lib/popup/Popup.tsx +243 -0
  357. package/src/lib/popup/popup.css +16 -0
  358. package/src/lib/table/RowForm.tsx +301 -0
  359. package/src/lib/table/Table.tsx +1069 -0
  360. package/src/lib/table/table.css +249 -0
  361. package/src/lib/table/types.ts +108 -0
  362. package/src/lib/text-area/TextArea.tsx +183 -0
  363. package/src/lib/text-area/text-area.css +156 -0
  364. package/src/lib/text-field/TextField.tsx +218 -0
  365. package/src/lib/text-field/index.ts +8 -0
  366. package/src/lib/text-field/text-field.css +201 -0
  367. package/src/lib/tooltip/Tooltip.tsx +24 -0
  368. package/src/lib/tooltip/tooltip.css +17 -0
  369. package/src/localization/index.ts +47 -0
  370. package/src/main.css +343 -0
  371. package/src/pages/Auth.tsx +848 -0
  372. package/src/pages/Editor.tsx +883 -0
  373. package/src/pages/ErrorPage.tsx +179 -0
  374. package/src/pages/Gallery.tsx +1693 -0
  375. package/src/pages/NewPaymentMethodCallback.tsx +53 -0
  376. package/src/pages/NotFoundPage.tsx +126 -0
  377. package/src/pages/PricingPlans.tsx +155 -0
  378. package/src/pages/auth.css +304 -0
  379. package/src/pages/gallery.css +421 -0
  380. package/src/payments/index.ts +187 -0
  381. package/src/popup-notification/index.ts +90 -0
  382. package/src/services/database/index.ts +1 -0
  383. package/src/services/database/utils.ts +1301 -0
  384. package/src/services/editor/CanvasElement.tsx +2934 -0
  385. package/src/services/editor/CanvasElementConnectionDeleteButton.ts +204 -0
  386. package/src/services/editor/CanvasPopup.tsx +749 -0
  387. package/src/services/editor/EditorService.ts +8157 -0
  388. package/src/services/editor/area.ts +1312 -0
  389. package/src/services/editor/connections.ts +1019 -0
  390. package/src/services/editor/create/condition.ts +25 -0
  391. package/src/services/editor/create/definition-entity.ts +29 -0
  392. package/src/services/editor/create/function-call.ts +25 -0
  393. package/src/services/editor/create/global-event.ts +33 -0
  394. package/src/services/editor/create/loop.ts +25 -0
  395. package/src/services/editor/create/operation.ts +30 -0
  396. package/src/services/editor/create/utils.ts +140 -0
  397. package/src/services/editor/create/variable-declaration.ts +135 -0
  398. package/src/services/editor/create/variable-instance.ts +100 -0
  399. package/src/services/editor/editor-ui-extensions-context.ts +43 -0
  400. package/src/services/editor/entities-metadata.json +9310 -0
  401. package/src/services/editor/icons.ts +1093 -0
  402. package/src/services/editor/index.ts +1 -0
  403. package/src/services/editor/layout.ts +102 -0
  404. package/src/services/editor/modules/built-in-function-implementations/base.ts +14 -0
  405. package/src/services/editor/modules/built-in-function-implementations/create-persisted-entity/index.ts +56 -0
  406. package/src/services/editor/modules/built-in-function-implementations/delete-persisted-entity/index.ts +55 -0
  407. package/src/services/editor/modules/built-in-function-implementations/index.ts +4 -0
  408. package/src/services/editor/modules/built-in-function-implementations/update-persisted-entity/index.ts +56 -0
  409. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/get-files.ts +183 -0
  410. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/list-drives.ts +124 -0
  411. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/list-root-folders.ts +125 -0
  412. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/smart-fetch-document.ts +702 -0
  413. package/src/services/editor/modules/operations-implementations/external-integrations/google-drive/upload-document.ts +535 -0
  414. package/src/services/editor/modules/operations-implementations/external-integrations/google-gemini/generate-content.ts +193 -0
  415. package/src/services/editor/modules/operations-implementations/external-integrations/google-mail/get-emails.ts +586 -0
  416. package/src/services/editor/modules/operations-implementations/external-integrations/google-mail/send-email.ts +386 -0
  417. package/src/services/editor/modules/operations-implementations/external-integrations/index.ts +12 -0
  418. package/src/services/editor/modules/operations-implementations/external-integrations/slack/channels.ts +240 -0
  419. package/src/services/editor/modules/operations-implementations/external-integrations/slack/messages.ts +210 -0
  420. package/src/services/editor/modules/operations-implementations/external-integrations/slack/replies.ts +200 -0
  421. package/src/services/editor/modules/operations-implementations/external-integrations/slack/send-message.ts +177 -0
  422. package/src/services/editor/modules/operations-implementations/index.ts +1 -0
  423. package/src/services/editor/modules/search-node-implementation/index.ts +42 -0
  424. package/src/services/editor/modules/sql-migrations-generation.tsx +1054 -0
  425. package/src/services/editor/publication/publication.ts +578 -0
  426. package/src/services/editor/ui.ts +1348 -0
  427. package/src/services/editor/utils.ts +5868 -0
  428. package/src/services/editor/value-store.ts +619 -0
  429. package/src/services/execution/built-in-function-implementations.ts +422 -0
  430. package/src/services/execution/index.ts +4747 -0
  431. package/src/services/execution/logic.ts +121 -0
  432. package/src/services/execution/test-instance.tsx +2296 -0
  433. package/src/services/execution/utils.ts +33 -0
  434. package/src/services/execution/value-resolution.test.ts +424 -0
  435. package/src/services/execution/value-resolution.ts +4087 -0
  436. package/src/services/integrations/ExternalIntegrationsService.ts +439 -0
  437. package/src/services/integrations/api.ts +175 -0
  438. package/src/services/local-relational-database/idb_helper.ts +66 -0
  439. package/src/services/local-relational-database/index.ts +3308 -0
  440. package/src/services/local-relational-database/utils.ts +403 -0
  441. package/src/services/notifications/index.ts +525 -0
  442. package/src/services/user/index.ts +144 -0
  443. package/src/setupTests.ts +1 -0
  444. package/src/socket/socket.ts +248 -0
  445. package/src/socket/utils.ts +10 -0
  446. package/src/store/workspace.ts +12 -0
  447. package/src/theme.ts +19 -0
  448. package/src/utils/DOM.ts +39 -0
  449. package/src/utils/date.ts +169 -0
  450. package/src/utils/index.ts +158 -0
  451. package/src/utils/react.tsx +679 -0
  452. package/src/utils/testing.ts +103 -0
@@ -0,0 +1,248 @@
1
+ // browser-socket.ts
2
+ import {
3
+ Events,
4
+ IWebSocketCommon,
5
+ IWebsocketsClient,
6
+ Logger,
7
+ } from '@elyx-code/common-ts-utils';
8
+ import { parseRTCMessage } from './utils';
9
+ import { ILiveMessageDTO } from '@elyx-code/definitions';
10
+
11
+ type BrowserSocketOptions = {
12
+ socketUrl: string;
13
+ maxQueue?: number; // default 1000
14
+ connectTimeoutMs?: number; // default 10_000
15
+ heartbeatMs?: number; // default 30_000
16
+ idleRestartMs?: number; // default 120_000
17
+ backoffInitialMs?: number; // default 500
18
+ backoffMaxMs?: number; // default 15_000
19
+ };
20
+
21
+ export class Socket extends Events implements IWebsocketsClient {
22
+ public connection!: IWebSocketCommon;
23
+
24
+ private url: string;
25
+ private queue: ILiveMessageDTO[] = [];
26
+
27
+ private reconnectAttempts = 0;
28
+ private manualClose = false;
29
+ private connectTimer?: number;
30
+ private heartbeatTimer?: number;
31
+ private idleTimer?: number;
32
+ private lastSeenAt = Date.now();
33
+
34
+ private readonly MAX_QUEUE: number;
35
+ private readonly CONNECT_TIMEOUT_MS: number;
36
+ private readonly HEARTBEAT_MS: number;
37
+ private readonly IDLE_RESTART_MS: number;
38
+ private readonly BACKOFF_INITIAL_MS: number;
39
+ private readonly BACKOFF_MAX_MS: number;
40
+
41
+ constructor(options: BrowserSocketOptions) {
42
+ super();
43
+
44
+ this.url = options.socketUrl;
45
+ this.MAX_QUEUE = options.maxQueue ?? 1000;
46
+ this.CONNECT_TIMEOUT_MS = options.connectTimeoutMs ?? 10_000;
47
+ this.HEARTBEAT_MS = options.heartbeatMs ?? 30_000;
48
+ this.IDLE_RESTART_MS = options.idleRestartMs ?? 120_000;
49
+ this.BACKOFF_INITIAL_MS = options.backoffInitialMs ?? 500;
50
+ this.BACKOFF_MAX_MS = options.backoffMaxMs ?? 15_000;
51
+
52
+ this.open();
53
+ }
54
+
55
+ // ---- lifecycle -----------------------------------------------------------
56
+
57
+ private open() {
58
+ const ws = new WebSocket(this.url);
59
+
60
+ // patch close() so external callers (socket.connection.close()) stop reconnection
61
+ const originalClose = ws.close.bind(ws);
62
+ ws.close = (code?: number, reason?: string) => {
63
+ // this.manualClose = true;
64
+ return originalClose(code, reason);
65
+ };
66
+
67
+ this.connection = ws as any as IWebSocketCommon;
68
+
69
+ // connect-timeout guard
70
+ this.clearTimer(this.connectTimer);
71
+ this.connectTimer = window.setTimeout(() => {
72
+ if (
73
+ ws.readyState !== WebSocket.OPEN &&
74
+ ws.readyState !== WebSocket.CLOSED
75
+ ) {
76
+ try {
77
+ ws.close(4000, 'connect-timeout');
78
+ } catch {}
79
+ }
80
+ }, this.CONNECT_TIMEOUT_MS);
81
+
82
+ // listeners — attach first to avoid missing early events
83
+ ws.addEventListener('open', this.onOpen as any);
84
+ ws.addEventListener('message', this.onMessageEvent as any);
85
+ ws.addEventListener('error', this.onError as any);
86
+ ws.addEventListener('close', this.onClose as any);
87
+ }
88
+
89
+ private onOpen = () => {
90
+ this.reconnectAttempts = 0;
91
+ this.lastSeenAt = Date.now();
92
+
93
+ // flush queue
94
+ const toSend = this.queue.splice(0, this.queue.length);
95
+ for (const m of toSend) this._send(m);
96
+
97
+ this.startHeartbeat();
98
+ this.startIdleWatch();
99
+
100
+ this.emit('open', null);
101
+ };
102
+
103
+ private onMessageEvent = async (e: MessageEvent) => {
104
+ this.lastSeenAt = Date.now();
105
+ const data = e.data;
106
+
107
+ const messageStr =
108
+ typeof data === 'string'
109
+ ? data
110
+ : data instanceof ArrayBuffer
111
+ ? new TextDecoder().decode(data)
112
+ : data instanceof Blob
113
+ ? await data.text()
114
+ : '';
115
+
116
+ const parsedMessage: ILiveMessageDTO | string = parseRTCMessage(messageStr);
117
+ this.emit('message', parsedMessage);
118
+ };
119
+
120
+ private onError = (event: Event) => {
121
+ this.emit('error', event);
122
+ };
123
+
124
+ private onClose = (evt: CloseEvent) => {
125
+ this.stopHeartbeat();
126
+ this.stopIdleWatch();
127
+ this.clearTimer(this.connectTimer);
128
+
129
+ const code = evt.code;
130
+ const reason = (evt.reason ?? '').toString();
131
+
132
+ this.emit('closed', { code, reason });
133
+
134
+ if (this.manualClose) {
135
+ Logger.log('WebSocket closed manually, not reconnecting');
136
+ return
137
+ };
138
+
139
+ this.scheduleReconnect(`code=${code} reason=${reason}`);
140
+ };
141
+
142
+ // ---- resilience helpers --------------------------------------------------
143
+
144
+ private scheduleReconnect(debugReason: string) {
145
+ const base = Math.min(
146
+ this.BACKOFF_INITIAL_MS * 2 ** this.reconnectAttempts,
147
+ this.BACKOFF_MAX_MS
148
+ );
149
+ const jitter = Math.floor(Math.random() * 800);
150
+ const delay = base + jitter;
151
+ this.reconnectAttempts++;
152
+
153
+ Logger.log(`WebSocket disconnected, scheduling reconnect in: ${delay}ms ${debugReason}`);
154
+
155
+ window.setTimeout(() => this.open(), delay);
156
+
157
+ this.emit('reconnecting', {
158
+ attempt: this.reconnectAttempts,
159
+ delay,
160
+ reason: debugReason,
161
+ });
162
+ }
163
+
164
+ private startHeartbeat() {
165
+ this.stopHeartbeat();
166
+ this.heartbeatTimer = window.setInterval(() => {
167
+ // App-level ping; safe for API Gateway and browsers
168
+ try {
169
+ this.connection?.send?.(
170
+ JSON.stringify({ type: 'ping', t: Date.now() })
171
+ );
172
+ } catch {}
173
+ }, this.HEARTBEAT_MS);
174
+ }
175
+
176
+ private stopHeartbeat() {
177
+ this.clearTimer(this.heartbeatTimer);
178
+ this.heartbeatTimer = undefined;
179
+ }
180
+
181
+ private startIdleWatch() {
182
+ this.stopIdleWatch();
183
+ this.idleTimer = window.setInterval(() => {
184
+ const idleFor = Date.now() - this.lastSeenAt;
185
+ if (idleFor >= this.IDLE_RESTART_MS) {
186
+ try {
187
+ this.connection?.close?.(4001, 'idle-restart');
188
+ } catch {}
189
+ }
190
+ }, Math.min(5_000, this.IDLE_RESTART_MS / 2));
191
+ }
192
+
193
+ private stopIdleWatch() {
194
+ this.clearTimer(this.idleTimer);
195
+ this.idleTimer = undefined;
196
+ }
197
+
198
+ private clearTimer(t?: number) {
199
+ if (t) window.clearTimeout(t);
200
+ }
201
+
202
+ // ---- public send API -----------------------------------------------------
203
+
204
+ private _send(outgoingMessage: ILiveMessageDTO) {
205
+ if (!this.connection) {
206
+ if (this.queue.length >= this.MAX_QUEUE) {
207
+ this.emit('overflow', { dropped: 1, reason: 'no-connection' });
208
+ return;
209
+ }
210
+ this.queue.push(outgoingMessage);
211
+ return;
212
+ }
213
+
214
+ if (this.connection.readyState === WebSocket.OPEN) {
215
+ try {
216
+ this.connection.send(JSON.stringify(outgoingMessage));
217
+ } catch (err) {
218
+ if (this.queue.length >= this.MAX_QUEUE) {
219
+ this.emit('overflow', { dropped: 1, reason: 'send-error' });
220
+ } else {
221
+ this.queue.push(outgoingMessage);
222
+ }
223
+ }
224
+ } else {
225
+ if (this.queue.length >= this.MAX_QUEUE) {
226
+ this.emit('overflow', { dropped: 1, reason: 'not-open' });
227
+ } else {
228
+ this.queue.push(outgoingMessage);
229
+ }
230
+ }
231
+ }
232
+
233
+ public send(message: ILiveMessageDTO) {
234
+ // eslint-disable-next-line no-console
235
+ Logger.log('Sending websocket message:', message);
236
+ this._send(message);
237
+ }
238
+
239
+ // Optional: call to stop auto-reconnect + close
240
+ public shutdown(code = 1000, reason = 'client closing') {
241
+ this.manualClose = true;
242
+ this.stopHeartbeat();
243
+ this.stopIdleWatch();
244
+ try {
245
+ this.connection?.close?.(code, reason);
246
+ } catch {}
247
+ }
248
+ }
@@ -0,0 +1,10 @@
1
+ import { ILiveMessageDTO } from '@elyx-code/definitions';
2
+
3
+ export function parseRTCMessage(data: string): ILiveMessageDTO | string {
4
+ try {
5
+ const jsonObject = JSON.parse(data);
6
+ return jsonObject;
7
+ } catch (e) {
8
+ return data;
9
+ }
10
+ }
@@ -0,0 +1,12 @@
1
+ import { IWorkspace } from '@elyx-code/definitions';
2
+ import { create } from 'zustand';
3
+
4
+ interface WorkspaceStore {
5
+ activeWorkspace: IWorkspace | null;
6
+ setActiveWorkspace: (workspace: IWorkspace) => void;
7
+ }
8
+
9
+ export const useWorkspaceStore = create<WorkspaceStore>((set) => ({
10
+ activeWorkspace: null,
11
+ setActiveWorkspace: (workspace) => set({ activeWorkspace: workspace }),
12
+ }));
package/src/theme.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { createTheme } from '@mui/material';
2
+
3
+ // Initialize mui theme
4
+ export const theme = createTheme({
5
+ palette: {
6
+ primary: {
7
+ light: '#rgb(139, 94, 255)',
8
+ main: '#6F36FF',
9
+ dark: '#rgb(77, 37, 178)',
10
+ contrastText: '#FFFFFF',
11
+ },
12
+ secondary: {
13
+ light: 'rgb(51, 51, 51)',
14
+ main: '#000000',
15
+ dark: '#000000',
16
+ contrastText: '#fff',
17
+ },
18
+ },
19
+ });
@@ -0,0 +1,39 @@
1
+ export function onClickAway(
2
+ element: Element,
3
+ callback: (e: Event) => void,
4
+ ...targets: Element[]
5
+ ) {
6
+ const listener = (event: Event) => {
7
+ if (!element?.contains(event.target as Node)) {
8
+ callback(event);
9
+ return;
10
+ }
11
+ };
12
+
13
+ if (!targets.length) {
14
+ document.addEventListener('click', listener);
15
+ } else {
16
+ targets.forEach((target) => {
17
+ if (!!target) {
18
+ target.addEventListener('click', listener);
19
+ }
20
+ });
21
+ }
22
+
23
+ return () => {
24
+ if (!targets.length) {
25
+ document.removeEventListener('click', listener);
26
+ } else {
27
+ targets.forEach((target) => {
28
+ if (!!target) {
29
+ target.removeEventListener('click', listener);
30
+ }
31
+ });
32
+ }
33
+ };
34
+ }
35
+
36
+ export function hasAnimation(element: Element): boolean {
37
+ // @ts-ignore
38
+ return getComputedStyle(element, null)['animation-name'] !== 'none';
39
+ }
@@ -0,0 +1,169 @@
1
+ export function toHtmlDate(date: Date) {
2
+ const day = ('0' + date.getDate()).slice(-2);
3
+ const month = ('0' + (date.getMonth() + 1)).slice(-2);
4
+
5
+ const formattedDate = date.getFullYear() + '-' + month + '-' + day;
6
+
7
+ return formattedDate;
8
+ }
9
+
10
+ export function readableTimeFromNow(date: Date): string {
11
+ const now = new Date();
12
+ const diff = date.getTime() - now.getTime(); // difference in milliseconds
13
+ const absDiff = Math.abs(diff);
14
+
15
+ // Calculate time units
16
+ const seconds = Math.floor(absDiff / 1000);
17
+ const minutes = Math.floor(seconds / 60);
18
+ const hours = Math.floor(minutes / 60);
19
+ const days = Math.floor(hours / 24);
20
+
21
+ // Format the result
22
+ let result = '';
23
+
24
+ if (days > 0) {
25
+ result = `${days} day${days > 1 ? 's' : ''}`;
26
+ } else if (hours > 0) {
27
+ result = `${hours} hour${hours > 1 ? 's' : ''}`;
28
+ } else if (minutes > 0) {
29
+ result = `${minutes} min`;
30
+ } else if (seconds > 0) {
31
+ result = `${seconds} sec`;
32
+ } else {
33
+ // For cases where the difference is less than a second
34
+ return 'now';
35
+ }
36
+
37
+ // Prefix with "in" for future dates, "ago" for past dates
38
+ return diff > 0 ? `in ${result}` : `${result} ago`;
39
+ }
40
+
41
+
42
+ export function getMonthRange(referenceDate: Date): {
43
+ startDate: Date;
44
+ endDate: Date;
45
+ } {
46
+ const year = referenceDate.getFullYear();
47
+ const month = referenceDate.getMonth();
48
+ const dayOfTheMonth = 1;
49
+
50
+ const timezoneMinutesOffset = new Date(
51
+ year,
52
+ month,
53
+ dayOfTheMonth
54
+ ).getTimezoneOffset();
55
+ const timezoneHoursOffset = timezoneMinutesOffset / 60;
56
+
57
+ // We turn the current hours offset into an opposite number (positive to negative, or negative to positive)
58
+ // So it can be used to corrent for the offset and get the actual date value we need
59
+ const offset = timezoneHoursOffset * -1;
60
+
61
+ // Calculate the first day of the next month
62
+ const firstDayOfNextMonth = new Date(year, month, dayOfTheMonth, offset);
63
+
64
+ // Calculate the last day of the month
65
+ const lastDay = new Date(year, month + 1, 0, offset);
66
+
67
+ return {
68
+ startDate: firstDayOfNextMonth,
69
+ endDate: lastDay,
70
+ };
71
+ }
72
+
73
+ export function daysUntil(targetDate: Date): number {
74
+ const currentDate = new Date();
75
+ const timeDifference = targetDate.getTime() - currentDate.getTime();
76
+ const daysDifference = Math.ceil(timeDifference / (1000 * 3600 * 24));
77
+ return daysDifference;
78
+ }
79
+
80
+ export function firstDayOfCurrentMonth(): Date {
81
+ const currentDate = new Date();
82
+ const year = currentDate.getFullYear();
83
+ const month = currentDate.getMonth();
84
+ const dayOfTheMonth = 1;
85
+
86
+ const timezoneMinutesOffset = new Date(
87
+ year,
88
+ month,
89
+ dayOfTheMonth
90
+ ).getTimezoneOffset();
91
+ const timezoneHoursOffset = timezoneMinutesOffset / 60;
92
+
93
+ // We turn the current hours offset into an opposite number (positive to negative, or negative to positive)
94
+ // So it can be used to corrent for the offset and get the actual date value we need
95
+ const offset = timezoneHoursOffset * -1;
96
+
97
+ const resultDate = new Date(year, month, dayOfTheMonth, offset);
98
+
99
+ return resultDate;
100
+ }
101
+
102
+ export function firstDayOfNextMonth(): Date {
103
+ const currentDate = new Date();
104
+ const year = currentDate.getFullYear();
105
+ const month = currentDate.getMonth() + 1;
106
+ const dayOfTheMonth = 1;
107
+
108
+ const timezoneMinutesOffset = new Date(
109
+ year,
110
+ month,
111
+ dayOfTheMonth
112
+ ).getTimezoneOffset();
113
+ const timezoneHoursOffset = timezoneMinutesOffset / 60;
114
+
115
+ // We turn the current hours offset into an opposite number (positive to negative, or negative to positive)
116
+ // So it can be used to corrent for the offset and get the actual date value we need
117
+ const offset = timezoneHoursOffset * -1;
118
+
119
+ // Calculate the first day of the next month
120
+ const firstDayOfNextMonth = new Date(year, month, dayOfTheMonth, offset);
121
+
122
+ return firstDayOfNextMonth;
123
+ }
124
+
125
+ export function formatDateShort(date: Date): string {
126
+ const months = [
127
+ 'Jan',
128
+ 'Feb',
129
+ 'Mar',
130
+ 'Apr',
131
+ 'May',
132
+ 'Jun',
133
+ 'Jul',
134
+ 'Aug',
135
+ 'Sep',
136
+ 'Oct',
137
+ 'Nov',
138
+ 'Dec',
139
+ ];
140
+
141
+ const month = months[date.getMonth()];
142
+ const day = date.getDate();
143
+
144
+ return `${month} ${day}`;
145
+ }
146
+
147
+ export function calculatePercentageDifference(
148
+ num1: number,
149
+ num2: number
150
+ ): number | null {
151
+ if (num1 === 0) {
152
+ // Avoid division by zero if num1 is 0.
153
+ if (num2 === 0) {
154
+ return 0; // Both numbers are the same.
155
+ } else {
156
+ return 100; // Treat as a 100% increase from 0 to num2.
157
+ }
158
+ }
159
+
160
+ const difference = num2 - num1;
161
+ const percentageDifference = (difference / num1) * 100;
162
+
163
+ return percentageDifference;
164
+ }
165
+
166
+ // Returns a date in "YYYY-MM-DD" format
167
+ export function formatDate(date: Date): string {
168
+ return date.toISOString().split('T')[0];
169
+ }
@@ -0,0 +1,158 @@
1
+ // Download file from url
2
+ export async function download(url: string, filename?: string) {
3
+ const response = await fetch(url); // CORS is now handled by S3!
4
+ const blob = await response.blob();
5
+ const blobUrl = window.URL.createObjectURL(blob);
6
+
7
+ const a = document.createElement('a');
8
+ a.href = blobUrl;
9
+
10
+ // 1. Use the provided filename, OR
11
+ // 2. Parse the URL, grab the path (ignoring query params), and get the last piece
12
+ const derivedFilename = filename || new URL(url).pathname.split('/').pop();
13
+
14
+ // Only set the download attribute if we successfully resolved a name
15
+ if (derivedFilename) {
16
+ a.download = derivedFilename;
17
+ }
18
+
19
+ document.body.appendChild(a);
20
+ a.click();
21
+ document.body.removeChild(a);
22
+ window.URL.revokeObjectURL(blobUrl);
23
+ }
24
+
25
+ // Equivalent to lodash's or underscore's isEmpty, but with better typing and without the dependency
26
+ export function isEmpty(value: any): boolean {
27
+ if (value === null || value === undefined) {
28
+ return true;
29
+ }
30
+
31
+ if (typeof value === 'string' || Array.isArray(value)) {
32
+ return value.length === 0;
33
+ }
34
+
35
+ if (typeof value === 'object') {
36
+ return Object.keys(value).length === 0;
37
+ }
38
+
39
+ return false;
40
+ }
41
+
42
+ // Equivalent to lodash's or underscore's isEqual, but with better typing and without the dependency
43
+ export function isEqual(value1: any, value2: any): boolean {
44
+ if (value1 === value2) {
45
+ return true;
46
+ }
47
+
48
+ if (typeof value1 !== typeof value2) {
49
+ return false;
50
+ }
51
+
52
+ if (typeof value1 === 'object' && typeof value2 === 'object') {
53
+ const keys1 = Object.keys(value1);
54
+ const keys2 = Object.keys(value2);
55
+
56
+ if (keys1.length !== keys2.length) {
57
+ return false;
58
+ }
59
+
60
+ for (const key of keys1) {
61
+ if (!isEqual(value1[key], value2[key])) {
62
+ return false;
63
+ }
64
+ }
65
+
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ }
71
+
72
+ export function debounce(func: Function, duration: number, immediate = false) {
73
+ let timeout: any;
74
+
75
+ if (immediate) {
76
+ return function (...args: any[]) {
77
+ const callNow = !timeout;
78
+ clearTimeout(timeout);
79
+ timeout = setTimeout(() => {
80
+ timeout = null;
81
+ }, duration);
82
+ if (callNow) func.apply(this, args);
83
+ };
84
+ }
85
+
86
+ return function (...args: any[]) {
87
+ const effect = () => {
88
+ timeout = null;
89
+ return func.apply(this, args);
90
+ };
91
+
92
+ clearTimeout(timeout);
93
+ timeout = setTimeout(effect, duration);
94
+ };
95
+ }
96
+
97
+ // random uuid
98
+ export function makeId() {
99
+ let text = '';
100
+ const possible =
101
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
102
+
103
+ for (let i = 0; i < 5; i++) {
104
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
105
+ }
106
+
107
+ return text;
108
+ }
109
+
110
+ /**
111
+ * Returns true if the user is on macOS or an iOS device.
112
+ */
113
+ export function isMacPlatform(): boolean {
114
+ // 1. New Client Hints API (Chrome, Edge…)
115
+ const uaData = (navigator as any).userAgentData;
116
+ if (uaData && typeof uaData.platform === 'string') {
117
+ const sanitizedPlatform = uaData.platform.toLowerCase();
118
+ return sanitizedPlatform.startsWith('mac') || sanitizedPlatform.startsWith('iphone') || sanitizedPlatform.startsWith('ipad');
119
+ }
120
+
121
+ // 2. Classic navigator.platform (deprecated, but still widely supported)
122
+ const plat = navigator.platform || '';
123
+ const sanitizedPlat = plat.toLowerCase();
124
+ if (/^mac/i.test(plat) || /^ip(hone|od|ad)/i.test(plat)) {
125
+ return true;
126
+ }
127
+
128
+ // 3. Fallback to sniffing navigator.userAgent
129
+ const ua = navigator.userAgent || '';
130
+ const sanitizedUa = ua.toLowerCase();
131
+ return /\bmac\b/.test(ua) || /\b(iphone|ipad|ipod)\b/.test(sanitizedUa);
132
+ }
133
+
134
+ /**
135
+ * Extracts the simple Lambda function name from a full ARN or an API Gateway Integration URI.
136
+ */
137
+ export function getFunctionNameFromArn(arnOrName: string): string {
138
+ if (!arnOrName) return '';
139
+ if (arnOrName.startsWith('arn:aws:lambda:')) {
140
+ return arnOrName.split(':').pop() || '';
141
+ }
142
+ if (arnOrName.includes('/functions/arn:aws:lambda:')) {
143
+ const match = arnOrName.match(/\/functions\/(arn:aws:lambda:[^/]+)/);
144
+ if (match) {
145
+ return match[1].split(':').pop() || '';
146
+ }
147
+ }
148
+ if (arnOrName.includes('/functions/')) {
149
+ const parts = arnOrName.split('/functions/');
150
+ const funcPart = parts[1].split('/')[0];
151
+ if (funcPart.startsWith('arn:aws:')) {
152
+ return funcPart.split(':').pop() || '';
153
+ }
154
+ return funcPart;
155
+ }
156
+ return arnOrName;
157
+ }
158
+