@flowuent-org/diagramming-core 1.3.10 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (677) hide show
  1. package/.editorconfig +13 -13
  2. package/.eslintignore +1 -1
  3. package/.eslintrc.json +35 -35
  4. package/.prettierignore +3 -3
  5. package/.prettierrc +3 -3
  6. package/.vscode/settings.json +6 -6
  7. package/README.md +95 -95
  8. package/apps/authentication/tsconfig.app.json +23 -23
  9. package/apps/authentication/tsconfig.json +21 -21
  10. package/apps/authentication/tsconfig.spec.json +28 -28
  11. package/apps/diagramming/.eslintrc.json +18 -18
  12. package/apps/diagramming/index.html +16 -16
  13. package/apps/diagramming/project.json +53 -53
  14. package/apps/diagramming/public/aws-icons/compute/App Runner.svg +17 -17
  15. package/apps/diagramming/public/aws-icons/compute/Application Auto Scaling.svg +17 -17
  16. package/apps/diagramming/public/aws-icons/compute/Batch.svg +17 -17
  17. package/apps/diagramming/public/aws-icons/compute/Bottlerocket.svg +19 -19
  18. package/apps/diagramming/public/aws-icons/compute/Compute Optimizer.svg +17 -17
  19. package/apps/diagramming/public/aws-icons/compute/EC2 Auto Scaling.svg +17 -17
  20. package/apps/diagramming/public/aws-icons/compute/EC2 Image Builder.svg +17 -17
  21. package/apps/diagramming/public/aws-icons/compute/EC2.svg +17 -17
  22. package/apps/diagramming/public/aws-icons/compute/Elastic Beanstalk.svg +17 -17
  23. package/apps/diagramming/public/aws-icons/compute/Elastic Fabric Adapter.svg +17 -17
  24. package/apps/diagramming/public/aws-icons/compute/Fargate.svg +19 -19
  25. package/apps/diagramming/public/aws-icons/compute/Genomics CLI.svg +17 -17
  26. package/apps/diagramming/public/aws-icons/compute/Lambda.svg +17 -17
  27. package/apps/diagramming/public/aws-icons/compute/Local Zones.svg +17 -17
  28. package/apps/diagramming/public/aws-icons/compute/NICE DCV.svg +17 -17
  29. package/apps/diagramming/public/aws-icons/compute/NICE EnginFrame.svg +17 -17
  30. package/apps/diagramming/public/aws-icons/compute/Nitro Enclaves.svg +17 -17
  31. package/apps/diagramming/public/aws-icons/compute/Outposts family.svg +17 -17
  32. package/apps/diagramming/public/aws-icons/compute/Outposts rack.svg +17 -17
  33. package/apps/diagramming/public/aws-icons/compute/Outposts servers.svg +17 -17
  34. package/apps/diagramming/public/aws-icons/compute/ParallelCluster.svg +17 -17
  35. package/apps/diagramming/public/aws-icons/compute/Serverless Application Repository.svg +17 -17
  36. package/apps/diagramming/public/aws-icons/compute/SimSpace Weaver.svg +17 -17
  37. package/apps/diagramming/public/aws-icons/compute/Thinkbox Deadline.svg +17 -17
  38. package/apps/diagramming/public/aws-icons/compute/Thinkbox Frost.svg +17 -17
  39. package/apps/diagramming/public/aws-icons/compute/Thinkbox Sequoia.svg +17 -17
  40. package/apps/diagramming/public/aws-icons/compute/Thinkbox Stoke.svg +17 -17
  41. package/apps/diagramming/public/aws-icons/compute/Thinkbox XMesh.svg +17 -17
  42. package/apps/diagramming/public/aws-icons/compute/VMware Cloud on AWS.svg +17 -17
  43. package/apps/diagramming/public/aws-icons/compute/Wavelength.svg +17 -17
  44. package/apps/diagramming/public/aws-icons/container/ECS Anywhere.svg +17 -17
  45. package/apps/diagramming/public/aws-icons/container/EKS Anywhere.svg +17 -17
  46. package/apps/diagramming/public/aws-icons/container/EKS Cloud.svg +17 -17
  47. package/apps/diagramming/public/aws-icons/container/EKS Distro.svg +17 -17
  48. package/apps/diagramming/public/aws-icons/container/Elastic Container Registry.svg +17 -17
  49. package/apps/diagramming/public/aws-icons/container/Elastic Container Service.svg +17 -17
  50. package/apps/diagramming/public/aws-icons/container/Elastic Kubernetes Service.svg +17 -17
  51. package/apps/diagramming/public/aws-icons/container/Fargate.svg +19 -19
  52. package/apps/diagramming/public/aws-icons/container/Red Hat OpenShift Service on AWS.svg +17 -17
  53. package/apps/diagramming/public/aws-icons/database/Aurora.svg +17 -17
  54. package/apps/diagramming/public/aws-icons/database/Database Migration Service.svg +17 -17
  55. package/apps/diagramming/public/aws-icons/database/DocumentDB.svg +17 -17
  56. package/apps/diagramming/public/aws-icons/database/ElastiCache.svg +17 -17
  57. package/apps/diagramming/public/aws-icons/database/Keyspaces.svg +15 -15
  58. package/apps/diagramming/public/aws-icons/database/MemoryDB for Redis.svg +17 -17
  59. package/apps/diagramming/public/aws-icons/database/Neptune.svg +17 -17
  60. package/apps/diagramming/public/aws-icons/database/RDS on VMware.svg +17 -17
  61. package/apps/diagramming/public/aws-icons/database/RDS.svg +17 -17
  62. package/apps/diagramming/public/aws-icons/database/Timestream.svg +17 -17
  63. package/apps/diagramming/public/aws-icons/networking/App Mesh.svg +17 -17
  64. package/apps/diagramming/public/aws-icons/networking/Client VPN.svg +17 -17
  65. package/apps/diagramming/public/aws-icons/networking/Cloud Directory.svg +17 -17
  66. package/apps/diagramming/public/aws-icons/networking/Cloud Map.svg +17 -17
  67. package/apps/diagramming/public/aws-icons/networking/Cloud WAN.svg +17 -17
  68. package/apps/diagramming/public/aws-icons/networking/CloudFront.svg +17 -17
  69. package/apps/diagramming/public/aws-icons/networking/Direct Connect.svg +17 -17
  70. package/apps/diagramming/public/aws-icons/networking/Elastic Load Balancing.svg +17 -17
  71. package/apps/diagramming/public/aws-icons/networking/Global Accelerator.svg +17 -17
  72. package/apps/diagramming/public/aws-icons/networking/Private 5G.svg +17 -17
  73. package/apps/diagramming/public/aws-icons/networking/PrivateLink.svg +17 -17
  74. package/apps/diagramming/public/aws-icons/networking/Route 53.svg +17 -17
  75. package/apps/diagramming/public/aws-icons/networking/Site to Site VPN.svg +17 -17
  76. package/apps/diagramming/public/aws-icons/networking/Transit Gateway.svg +17 -17
  77. package/apps/diagramming/public/aws-icons/networking/VPC Lattice.svg +17 -17
  78. package/apps/diagramming/public/aws-icons/networking/Verified Access.svg +17 -17
  79. package/apps/diagramming/public/aws-icons/networking/Virtual Private Cloud.svg +17 -17
  80. package/apps/diagramming/public/aws-icons/security/Artifact.svg +17 -17
  81. package/apps/diagramming/public/aws-icons/security/Audit Manager.svg +17 -17
  82. package/apps/diagramming/public/aws-icons/security/Certificate Manager.svg +17 -17
  83. package/apps/diagramming/public/aws-icons/security/CloudHSM.svg +17 -17
  84. package/apps/diagramming/public/aws-icons/security/Cognito.svg +17 -17
  85. package/apps/diagramming/public/aws-icons/security/Detective.svg +17 -17
  86. package/apps/diagramming/public/aws-icons/security/Directory Service.svg +17 -17
  87. package/apps/diagramming/public/aws-icons/security/Firewall Manager.svg +17 -17
  88. package/apps/diagramming/public/aws-icons/security/GuardDuty.svg +17 -17
  89. package/apps/diagramming/public/aws-icons/security/IAM Identity Center.svg +17 -17
  90. package/apps/diagramming/public/aws-icons/security/Identity and Access Management.svg +17 -17
  91. package/apps/diagramming/public/aws-icons/security/Inspector.svg +17 -17
  92. package/apps/diagramming/public/aws-icons/security/Key Management Service.svg +17 -17
  93. package/apps/diagramming/public/aws-icons/security/Macie.svg +17 -17
  94. package/apps/diagramming/public/aws-icons/security/Network Firewall.svg +17 -17
  95. package/apps/diagramming/public/aws-icons/security/Resource Access Manager.svg +17 -17
  96. package/apps/diagramming/public/aws-icons/security/Secrets Manager.svg +17 -17
  97. package/apps/diagramming/public/aws-icons/security/Security Hub.svg +17 -17
  98. package/apps/diagramming/public/aws-icons/security/Security Lake.svg +17 -17
  99. package/apps/diagramming/public/aws-icons/security/Shield.svg +17 -17
  100. package/apps/diagramming/public/aws-icons/security/Signer.svg +17 -17
  101. package/apps/diagramming/public/aws-icons/security/Verified Permissions.svg +17 -17
  102. package/apps/diagramming/public/aws-icons/security/WAF.svg +17 -17
  103. package/apps/diagramming/public/aws-icons/storage/Backup.svg +17 -17
  104. package/apps/diagramming/public/aws-icons/storage/EFS.svg +17 -17
  105. package/apps/diagramming/public/aws-icons/storage/Elastic Block Store.svg +17 -17
  106. package/apps/diagramming/public/aws-icons/storage/Elastic Disaster Recovery.svg +15 -15
  107. package/apps/diagramming/public/aws-icons/storage/FSx for Lustre.svg +17 -17
  108. package/apps/diagramming/public/aws-icons/storage/FSx for NetApp ONTAP.svg +17 -17
  109. package/apps/diagramming/public/aws-icons/storage/FSx for OpenZFS.svg +17 -17
  110. package/apps/diagramming/public/aws-icons/storage/FSx for WFS.svg +17 -17
  111. package/apps/diagramming/public/aws-icons/storage/FSx.svg +17 -17
  112. package/apps/diagramming/public/aws-icons/storage/File Cache.svg +17 -17
  113. package/apps/diagramming/public/aws-icons/storage/S3 on Outposts.svg +17 -17
  114. package/apps/diagramming/public/aws-icons/storage/Simple Storage Service Glacier.svg +17 -17
  115. package/apps/diagramming/public/aws-icons/storage/Simple Storage Service.svg +17 -17
  116. package/apps/diagramming/public/aws-icons/storage/Snowball Edge.svg +17 -17
  117. package/apps/diagramming/public/aws-icons/storage/Snowball.svg +17 -17
  118. package/apps/diagramming/public/aws-icons/storage/Snowcone.svg +17 -17
  119. package/apps/diagramming/public/aws-icons/storage/Snowmobile.svg +17 -17
  120. package/apps/diagramming/public/aws-icons/storage/Storage Gateway.svg +17 -17
  121. package/apps/diagramming/public/azure-icons/compute/02112-icon-service-Automanaged-VM.svg +1 -1
  122. package/apps/diagramming/public/azure-icons/databases/02390-icon-service-Azure-SQL.svg +1 -1
  123. package/apps/diagramming/public/azure-icons/databases/02392-icon-service-SSIS-Lift-And-Shift-IR.svg +1 -1
  124. package/apps/diagramming/public/azure-icons/networking/02145-icon-service-Resource-Management-Private-Link.svg +1 -1
  125. package/apps/diagramming/public/azure-icons/security/02247-icon-service-Microsoft-Defender-for-IoT.svg +1 -1
  126. package/apps/diagramming/public/sample-node-complete.json +63 -63
  127. package/apps/diagramming/public/sample-node-data.json +63 -63
  128. package/apps/diagramming/src/AutomationDiagramData.ts +147 -480
  129. package/apps/diagramming/src/CollaborationDiagramData.ts +127 -127
  130. package/apps/diagramming/src/CustomIconExamples.ts +233 -233
  131. package/apps/diagramming/src/DiagramTabs.tsx +205 -205
  132. package/apps/diagramming/src/Pages/DevPlayground.tsx +3 -3
  133. package/apps/diagramming/src/Pages/Home.tsx +111 -111
  134. package/apps/diagramming/src/SequenceDiagramData.ts +215 -215
  135. package/apps/diagramming/src/StateMachineDiagramData.ts +64 -64
  136. package/apps/diagramming/src/UseCaseDiagramData.ts +52 -52
  137. package/apps/diagramming/src/cloud-data.ts +371 -371
  138. package/apps/diagramming/src/components/AddNodeView.tsx +252 -252
  139. package/apps/diagramming/src/createSelecors.tsx +17 -17
  140. package/apps/diagramming/src/index.scss +12 -12
  141. package/apps/diagramming/src/main.tsx +463 -463
  142. package/apps/diagramming/src/node-data.ts +664 -664
  143. package/apps/diagramming/src/sample-workflow-content.ts +55 -55
  144. package/apps/diagramming/src/stencil-items.ts +31 -31
  145. package/apps/diagramming/src/style.css +13 -13
  146. package/apps/diagramming/src/tabsStore.tsx +152 -152
  147. package/apps/diagramming/src/vite-env.d.ts +1 -1
  148. package/apps/diagramming/tsconfig.app.json +23 -23
  149. package/apps/diagramming/tsconfig.json +21 -21
  150. package/apps/diagramming/tsconfig.spec.json +28 -28
  151. package/apps/diagramming/vite.config.ts +34 -34
  152. package/apps/diagramming/webpack.config.js +13 -13
  153. package/apps/workflow/.eslintrc.json +18 -18
  154. package/apps/workflow/group/group-form-hooks/index.ts +3 -3
  155. package/apps/workflow/group/group-form-hooks/useFormValidation.ts +20 -20
  156. package/apps/workflow/group/group-form-schema/SettingsTabFormSchema.ts +7 -7
  157. package/apps/workflow/group/group-form-schema/index.ts +3 -3
  158. package/apps/workflow/i18n.ts +19 -19
  159. package/apps/workflow/index.html +16 -16
  160. package/apps/workflow/locales/en/translation.json +713 -713
  161. package/apps/workflow/project.json +8 -8
  162. package/apps/workflow/src/app/app.module.css +1 -1
  163. package/apps/workflow/src/app/app.spec.tsx +15 -15
  164. package/apps/workflow/src/app/app.tsx +370 -370
  165. package/apps/workflow/src/main.tsx +13 -13
  166. package/apps/workflow/src/styles.css +1 -1
  167. package/apps/workflow/src/theme/index.ts +546 -546
  168. package/apps/workflow/tsconfig.app.json +23 -23
  169. package/apps/workflow/tsconfig.json +21 -21
  170. package/apps/workflow/tsconfig.spec.json +28 -28
  171. package/apps/workflow/vite.config.ts +51 -51
  172. package/nx.json +58 -58
  173. package/package.json +1 -1
  174. package/packages/api/.babelrc +12 -12
  175. package/packages/api/.eslintrc.json +18 -18
  176. package/packages/api/README.md +7 -7
  177. package/packages/api/project.json +8 -8
  178. package/packages/api/src/index.ts +3 -3
  179. package/packages/api/src/lib/jsonPlaceholderService/endpoints.ts +3 -3
  180. package/packages/api/src/lib/jsonPlaceholderService/service.ts +13 -13
  181. package/packages/api/tsconfig.json +17 -17
  182. package/packages/api/tsconfig.lib.json +24 -24
  183. package/packages/atoms/.babelrc +12 -12
  184. package/packages/atoms/.eslintrc.json +18 -18
  185. package/packages/atoms/README.md +7 -7
  186. package/packages/atoms/forms/AuthenticationTabForm/authenticationTabForm.json +224 -224
  187. package/packages/atoms/forms/AuthenticationTabForm/index.tsx +255 -255
  188. package/packages/atoms/forms/SettingsTabForm/index.tsx +85 -85
  189. package/packages/atoms/forms/SettingsTabForm/settingTabForm.json +27 -27
  190. package/packages/atoms/forms/index.ts +4 -4
  191. package/packages/atoms/project.json +8 -8
  192. package/packages/atoms/src/index.ts +33 -33
  193. package/packages/atoms/src/lib/Accordion/Accordion.module.css +7 -7
  194. package/packages/atoms/src/lib/Accordion/Accordion.spec.tsx +13 -13
  195. package/packages/atoms/src/lib/Accordion/Accordion.tsx +29 -29
  196. package/packages/atoms/src/lib/Alert/Alert.module.css +7 -7
  197. package/packages/atoms/src/lib/Alert/Alert.spec.tsx +10 -10
  198. package/packages/atoms/src/lib/Alert/Alert.tsx +19 -19
  199. package/packages/atoms/src/lib/Avatar/Avatar.module.css +7 -7
  200. package/packages/atoms/src/lib/Avatar/Avatar.spec.tsx +10 -10
  201. package/packages/atoms/src/lib/Avatar/Avatar.tsx +22 -22
  202. package/packages/atoms/src/lib/Box/Box.module.css +7 -7
  203. package/packages/atoms/src/lib/Box/Box.spec.tsx +10 -10
  204. package/packages/atoms/src/lib/Box/Box.tsx +19 -19
  205. package/packages/atoms/src/lib/BulkEdit/BulkEdit.module.css +7 -7
  206. package/packages/atoms/src/lib/BulkEdit/BulkEdit.spec.tsx +10 -10
  207. package/packages/atoms/src/lib/BulkEdit/BulkEdit.tsx +15 -15
  208. package/packages/atoms/src/lib/Button/Button.module.css +7 -7
  209. package/packages/atoms/src/lib/Button/Button.spec.tsx +10 -10
  210. package/packages/atoms/src/lib/Button/Button.tsx +78 -78
  211. package/packages/atoms/src/lib/Card/Card.module.css +7 -7
  212. package/packages/atoms/src/lib/Card/Card.spec.tsx +10 -10
  213. package/packages/atoms/src/lib/Card/Card.tsx +19 -19
  214. package/packages/atoms/src/lib/CardContent/CardContent.module.css +7 -7
  215. package/packages/atoms/src/lib/CardContent/CardContent.spec.tsx +10 -10
  216. package/packages/atoms/src/lib/CardContent/CardContent.tsx +22 -22
  217. package/packages/atoms/src/lib/FormTextField/FormTextField.module.css +7 -7
  218. package/packages/atoms/src/lib/FormTextField/FormTextField.spec.tsx +10 -10
  219. package/packages/atoms/src/lib/FormTextField/FormTextField.tsx +35 -35
  220. package/packages/atoms/src/lib/Grid/Grid.module.css +7 -7
  221. package/packages/atoms/src/lib/Grid/Grid.spec.tsx +10 -10
  222. package/packages/atoms/src/lib/Grid/Grid.tsx +19 -19
  223. package/packages/atoms/src/lib/Stack/Stack.module.css +7 -7
  224. package/packages/atoms/src/lib/Stack/Stack.spec.tsx +10 -10
  225. package/packages/atoms/src/lib/Stack/Stack.tsx +19 -19
  226. package/packages/atoms/src/lib/Switch/Switch.module.css +7 -7
  227. package/packages/atoms/src/lib/Switch/Switch.spec.tsx +10 -10
  228. package/packages/atoms/src/lib/Switch/Switch.tsx +46 -46
  229. package/packages/atoms/src/lib/TableView/TableView.module.css +7 -7
  230. package/packages/atoms/src/lib/TableView/TableView.spec.tsx +10 -10
  231. package/packages/atoms/src/lib/TableView/TableView.tsx +88 -88
  232. package/packages/atoms/src/lib/TextField/TextField.module.css +7 -7
  233. package/packages/atoms/src/lib/TextField/TextField.spec.tsx +10 -10
  234. package/packages/atoms/src/lib/TextField/TextField.tsx +17 -17
  235. package/packages/atoms/src/lib/Typography/Typography.module.css +7 -7
  236. package/packages/atoms/src/lib/Typography/Typography.spec.tsx +10 -10
  237. package/packages/atoms/src/lib/Typography/Typography.tsx +22 -22
  238. package/packages/atoms/tsconfig.json +17 -17
  239. package/packages/atoms/tsconfig.lib.json +30 -30
  240. package/packages/common/.babelrc +12 -12
  241. package/packages/common/.eslintrc.json +18 -18
  242. package/packages/common/README.md +7 -7
  243. package/packages/common/project.json +8 -8
  244. package/packages/common/src/index.ts +4 -4
  245. package/packages/common/src/lib/generateRandomProfilePic.ts +3 -3
  246. package/packages/common/src/lib/generateValidationSchema.ts +46 -46
  247. package/packages/common/tsconfig.json +17 -17
  248. package/packages/common/tsconfig.lib.json +24 -24
  249. package/packages/contexts/.babelrc +12 -12
  250. package/packages/contexts/.eslintrc.json +18 -18
  251. package/packages/contexts/README.md +7 -7
  252. package/packages/contexts/project.json +8 -8
  253. package/packages/contexts/src/index.ts +2 -2
  254. package/packages/contexts/tsconfig.json +17 -17
  255. package/packages/contexts/tsconfig.lib.json +24 -24
  256. package/packages/diagrams/.babelrc +12 -12
  257. package/packages/diagrams/.ctirc +208 -208
  258. package/packages/diagrams/.eslintrc.json +17 -17
  259. package/packages/diagrams/CUSTOM_ICONS.md +232 -232
  260. package/packages/diagrams/GOOGLE_SHEETS_IMPLEMENTATION.md +233 -233
  261. package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
  262. package/packages/diagrams/README.md +7 -7
  263. package/packages/diagrams/UNDO_REDO_API.md +306 -306
  264. package/packages/diagrams/locales/en/translation.json +713 -713
  265. package/packages/diagrams/package.json +27 -27
  266. package/packages/diagrams/pnpm-lock.yaml +2606 -2606
  267. package/packages/diagrams/project.json +42 -42
  268. package/packages/diagrams/rollup.config.js +26 -26
  269. package/packages/diagrams/src/DiagramFlow.tsx +7 -7
  270. package/packages/diagrams/src/declarations.d.ts +7 -7
  271. package/packages/diagrams/src/index.ts +8 -1
  272. package/packages/diagrams/src/index.ts.bak +99 -99
  273. package/packages/diagrams/src/lib/assets/markers/markers.param.tsx +101 -101
  274. package/packages/diagrams/src/lib/assets/markers/markers.type.ts +10 -10
  275. package/packages/diagrams/src/lib/atoms/ActorNode.tsx +123 -123
  276. package/packages/diagrams/src/lib/atoms/AddParallelColButton.tsx +26 -26
  277. package/packages/diagrams/src/lib/atoms/BendpointNode.tsx +71 -71
  278. package/packages/diagrams/src/lib/atoms/CardBlockTypeSelector.tsx +35 -35
  279. package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
  280. package/packages/diagrams/src/lib/atoms/CardMainContent.tsx +19 -19
  281. package/packages/diagrams/src/lib/atoms/ConnectionPoints.tsx +149 -149
  282. package/packages/diagrams/src/lib/atoms/ContentAssist.tsx +341 -341
  283. package/packages/diagrams/src/lib/atoms/DiagramControls.tsx +56 -56
  284. package/packages/diagrams/src/lib/atoms/ExpressionInput.tsx +437 -437
  285. package/packages/diagrams/src/lib/atoms/FloatingConnectionLine.tsx +73 -73
  286. package/packages/diagrams/src/lib/atoms/LazyIcon.tsx +31 -31
  287. package/packages/diagrams/src/lib/atoms/MarkerSelector.tsx +106 -106
  288. package/packages/diagrams/src/lib/atoms/MultiSelectInput.tsx +87 -87
  289. package/packages/diagrams/src/lib/atoms/ParameterInput.tsx +199 -199
  290. package/packages/diagrams/src/lib/atoms/PropertyInput.tsx +114 -114
  291. package/packages/diagrams/src/lib/atoms/StyledBox.tsx +69 -69
  292. package/packages/diagrams/src/lib/atoms/ValidationError.tsx +37 -37
  293. package/packages/diagrams/src/lib/atoms/ValidationMessage.tsx +63 -63
  294. package/packages/diagrams/src/lib/components/AiButton.tsx +52 -52
  295. package/packages/diagrams/src/lib/components/ControlEdgeList.tsx +303 -303
  296. package/packages/diagrams/src/lib/components/CreateFunctionModal.tsx +264 -264
  297. package/packages/diagrams/src/lib/components/CustomCodeModal.tsx +287 -287
  298. package/packages/diagrams/src/lib/components/DiagramPanel.tsx +331 -331
  299. package/packages/diagrams/src/lib/components/FunctionModalTooltip.tsx +30 -30
  300. package/packages/diagrams/src/lib/components/GraphQLCustomCodeModal.tsx +210 -210
  301. package/packages/diagrams/src/lib/components/Header.tsx +143 -143
  302. package/packages/diagrams/src/lib/components/MiniMapCommon.tsx +24 -24
  303. package/packages/diagrams/src/lib/components/ResizeIcon.tsx +81 -81
  304. package/packages/diagrams/src/lib/components/SideBar.tsx +40 -40
  305. package/packages/diagrams/src/lib/components/automation/AISuggestionsModal.tsx +269 -269
  306. package/packages/diagrams/src/lib/components/automation/AISuggestionsPanel.tsx +28 -175
  307. package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +1 -1
  308. package/packages/diagrams/src/lib/components/automation/AutomationDecisionNode.tsx +94 -0
  309. package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +1 -1
  310. package/packages/diagrams/src/lib/components/automation/AutomationExecutionPanel.tsx +439 -439
  311. package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +1 -1
  312. package/packages/diagrams/src/lib/components/automation/AutomationInteractionNode.tsx +693 -693
  313. package/packages/diagrams/src/lib/components/automation/AutomationMonitoringNode.tsx +399 -399
  314. package/packages/diagrams/src/lib/components/automation/AutomationNavigationNode.tsx +1 -1
  315. package/packages/diagrams/src/lib/components/automation/AutomationNodeCard.tsx +414 -0
  316. package/packages/diagrams/src/lib/components/automation/AutomationSlackNode.tsx +694 -694
  317. package/packages/diagrams/src/lib/components/automation/AutomationSmsNode.tsx +62 -0
  318. package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +1 -1
  319. package/packages/diagrams/src/lib/components/automation/AutomationTelegramNode.tsx +664 -664
  320. package/packages/diagrams/src/lib/components/automation/AutomationVoiceCallNode.tsx +65 -0
  321. package/packages/diagrams/src/lib/components/automation/AutomationWorkflowNode.tsx +85 -0
  322. package/packages/diagrams/src/lib/components/automation/NodeAIAssistantPopup.tsx +504 -504
  323. package/packages/diagrams/src/lib/components/automation/index.ts +29 -19
  324. package/packages/diagrams/src/lib/components/automation/statusColors.ts +124 -124
  325. package/packages/diagrams/src/lib/contexts/CardDataProvider.tsx +111 -111
  326. package/packages/diagrams/src/lib/contexts/DiagramProvider.tsx +392 -391
  327. package/packages/diagrams/src/lib/contexts/diagramStoreTypes.tsx +134 -134
  328. package/packages/diagrams/src/lib/contexts/onConnect.ts +39 -39
  329. package/packages/diagrams/src/lib/contexts/onDragStart.ts +45 -45
  330. package/packages/diagrams/src/lib/contexts/onNodeDragEnd.ts +179 -179
  331. package/packages/diagrams/src/lib/contexts/onNodesChange.ts +406 -406
  332. package/packages/diagrams/src/lib/contexts/onReconnect.ts +59 -59
  333. package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +65 -65
  334. package/packages/diagrams/src/lib/contexts/setContentHeight.ts +14 -14
  335. package/packages/diagrams/src/lib/contexts/setDiagramType.ts +10 -10
  336. package/packages/diagrams/src/lib/contexts/setEdgeShapeType.ts +7 -7
  337. package/packages/diagrams/src/lib/contexts/setEdges.ts +9 -9
  338. package/packages/diagrams/src/lib/contexts/setLayoutDirection.ts +9 -9
  339. package/packages/diagrams/src/lib/contexts/setNodeSetting.ts +17 -17
  340. package/packages/diagrams/src/lib/contexts/setNodes.ts +10 -10
  341. package/packages/diagrams/src/lib/contexts/setPannable.ts +7 -7
  342. package/packages/diagrams/src/lib/contexts/setSelectedEdge.ts +7 -7
  343. package/packages/diagrams/src/lib/contexts/setSelectedNode.ts +7 -7
  344. package/packages/diagrams/src/lib/contexts/undo.ts +163 -163
  345. package/packages/diagrams/src/lib/contexts/updateNodeSetting.ts +17 -17
  346. package/packages/diagrams/src/lib/examples/TwilioWhatsAppConfigExample.ts +128 -128
  347. package/packages/diagrams/src/lib/externals.ts +4 -4
  348. package/packages/diagrams/src/lib/hooks/customUseReactFlow.tsx +90 -90
  349. package/packages/diagrams/src/lib/hooks/updateNodes.ts +45 -45
  350. package/packages/diagrams/src/lib/hooks/useAddChildButton.tsx +61 -61
  351. package/packages/diagrams/src/lib/hooks/useAddSwitchCase.ts +75 -75
  352. package/packages/diagrams/src/lib/hooks/useAutoRegisterFunctions.ts +135 -135
  353. package/packages/diagrams/src/lib/hooks/useAutoRegisterVariables.ts +286 -286
  354. package/packages/diagrams/src/lib/hooks/useDeleteNodeByEvent.ts +64 -64
  355. package/packages/diagrams/src/lib/hooks/useDragCallbacks.tsx +122 -122
  356. package/packages/diagrams/src/lib/hooks/useFormValidation.ts +349 -349
  357. package/packages/diagrams/src/lib/hooks/useFunctionFormCallbacks.ts +136 -136
  358. package/packages/diagrams/src/lib/hooks/useIsSelectedNode.ts +11 -11
  359. package/packages/diagrams/src/lib/hooks/useModalControls.ts +13 -13
  360. package/packages/diagrams/src/lib/hooks/useNodeDragHandlers.ts +43 -43
  361. package/packages/diagrams/src/lib/hooks/useNodeSelection.ts +55 -55
  362. package/packages/diagrams/src/lib/hooks/useRenderDividers.tsx +19 -19
  363. package/packages/diagrams/src/lib/hooks/useRenderPins.tsx +74 -74
  364. package/packages/diagrams/src/lib/hooks/useResizeObserver.ts +21 -21
  365. package/packages/diagrams/src/lib/hooks/useTreeChildNode.ts +536 -536
  366. package/packages/diagrams/src/lib/i18n.ts +42 -42
  367. package/packages/diagrams/src/lib/icons/icons.tsx +324 -0
  368. package/packages/diagrams/src/lib/icons/index.ts +29 -0
  369. package/packages/diagrams/src/lib/icons/types.ts +7 -0
  370. package/packages/diagrams/src/lib/molecules/AddingBlock.tsx +147 -147
  371. package/packages/diagrams/src/lib/molecules/AvailableVariablesDisplay.tsx +57 -57
  372. package/packages/diagrams/src/lib/molecules/Block.tsx +143 -143
  373. package/packages/diagrams/src/lib/molecules/BlockProvider.tsx +28 -28
  374. package/packages/diagrams/src/lib/molecules/BlockWrapper.tsx +14 -14
  375. package/packages/diagrams/src/lib/molecules/ConditionRule.tsx +131 -131
  376. package/packages/diagrams/src/lib/molecules/DraggablePane.tsx +198 -198
  377. package/packages/diagrams/src/lib/molecules/EntityNodeBlocks.tsx +66 -66
  378. package/packages/diagrams/src/lib/molecules/SideHandles.tsx +215 -215
  379. package/packages/diagrams/src/lib/molecules/StencilItem.tsx +85 -85
  380. package/packages/diagrams/src/lib/molecules/WorkflowNodeActionButtons.tsx +62 -62
  381. package/packages/diagrams/src/lib/molecules/animated-add-button.tsx +83 -83
  382. package/packages/diagrams/src/lib/molecules/json-viewer.tsx +107 -107
  383. package/packages/diagrams/src/lib/organisms/AddNodeView.tsx +102 -102
  384. package/packages/diagrams/src/lib/organisms/Card/EntityNode.tsx +259 -259
  385. package/packages/diagrams/src/lib/organisms/Card/card.params.ts +29 -29
  386. package/packages/diagrams/src/lib/organisms/Card/card.types.ts +5 -5
  387. package/packages/diagrams/src/lib/organisms/CodeModal.tsx +105 -105
  388. package/packages/diagrams/src/lib/organisms/ConditionRuleGroup.tsx +138 -138
  389. package/packages/diagrams/src/lib/organisms/CustomEdge/EdgeMarkers.tsx +51 -51
  390. package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge-generator.tsx +135 -135
  391. package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.params.ts +6 -6
  392. package/packages/diagrams/src/lib/organisms/CustomEdge/custom-edge.type.ts +15 -15
  393. package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -121
  394. package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgeModal.ts +37 -37
  395. package/packages/diagrams/src/lib/organisms/CustomEdge/useEdgePath.tsx +99 -99
  396. package/packages/diagrams/src/lib/organisms/DownloadPanel.tsx +345 -345
  397. package/packages/diagrams/src/lib/organisms/EdgeModal.tsx +243 -243
  398. package/packages/diagrams/src/lib/organisms/HistoryPane.tsx +118 -118
  399. package/packages/diagrams/src/lib/organisms/NodeContextMenu.tsx +259 -259
  400. package/packages/diagrams/src/lib/organisms/PropertiesPane.tsx +276 -276
  401. package/packages/diagrams/src/lib/organisms/SmartDynamicForm.tsx +226 -226
  402. package/packages/diagrams/src/lib/organisms/Stencil.tsx +60 -60
  403. package/packages/diagrams/src/lib/organisms/UseDiagramStore.tsx +4 -4
  404. package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +45 -45
  405. package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeTypeDisplay.tsx +114 -114
  406. package/packages/diagrams/src/lib/organisms/WorkFlowNode/WorkflowNodeIcons.tsx +21 -23
  407. package/packages/diagrams/src/lib/organisms/WorkflowNode.tsx +484 -484
  408. package/packages/diagrams/src/lib/services/GoogleSheetsService.ts +961 -961
  409. package/packages/diagrams/src/lib/services/SlackService.ts +134 -134
  410. package/packages/diagrams/src/lib/services/TwilioWhatsAppService.ts +273 -273
  411. package/packages/diagrams/src/lib/styles.css +55 -55
  412. package/packages/diagrams/src/lib/templates/PageLinks.tsx +13 -13
  413. package/packages/diagrams/src/lib/templates/arch/ArchDiagram.tsx +793 -793
  414. package/packages/diagrams/src/lib/templates/arch/components/EdgeDialog.tsx +82 -82
  415. package/packages/diagrams/src/lib/templates/arch/components/EdgeSettings.tsx +81 -81
  416. package/packages/diagrams/src/lib/templates/arch/components/GroupControls.tsx +59 -59
  417. package/packages/diagrams/src/lib/templates/arch/components/GroupSizeDialog.tsx +81 -81
  418. package/packages/diagrams/src/lib/templates/arch/components/NodeDialog.tsx +214 -214
  419. package/packages/diagrams/src/lib/templates/arch/components/nodeTypes.ts +91 -91
  420. package/packages/diagrams/src/lib/templates/arch/controls/ArchDiagramControls.tsx +349 -349
  421. package/packages/diagrams/src/lib/templates/arch/data/templatee-data.ts +212 -212
  422. package/packages/diagrams/src/lib/templates/cloud-arch/components/CloudArchitectureDiagram.tsx +3912 -3912
  423. package/packages/diagrams/src/lib/templates/cloud-arch/components/FormatConverter.tsx +809 -809
  424. package/packages/diagrams/src/lib/templates/cloud-arch/components/FragmentImporter.tsx +276 -276
  425. package/packages/diagrams/src/lib/templates/cloud-arch/components/PropertiesPanel.tsx +1063 -1063
  426. package/packages/diagrams/src/lib/templates/cloud-arch/components/ServiceIconPicker.tsx +138 -138
  427. package/packages/diagrams/src/lib/templates/cloud-arch/components/SettingsSidebar.tsx +656 -656
  428. package/packages/diagrams/src/lib/templates/cloud-arch/components/SubnetSelector.tsx +468 -468
  429. package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/ServiceNode.tsx +310 -310
  430. package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/SubnetNode.tsx +475 -475
  431. package/packages/diagrams/src/lib/templates/cloud-arch/components/nodes/UsersNode.tsx +277 -277
  432. package/packages/diagrams/src/lib/templates/cloud-arch/data/diagramManager.ts +364 -364
  433. package/packages/diagrams/src/lib/templates/cloud-arch/data/types.ts +183 -183
  434. package/packages/diagrams/src/lib/templates/cloud-arch/integration/diagramValidator.ts +379 -379
  435. package/packages/diagrams/src/lib/templates/cloud-arch/messages/errorMessages.json +95 -95
  436. package/packages/diagrams/src/lib/templates/cloud-arch/types/localization.ts +368 -368
  437. package/packages/diagrams/src/lib/templates/cloud-arch/types/validation.ts +72 -72
  438. package/packages/diagrams/src/lib/templates/cloud-arch/utils/aws-icons.ts +557 -557
  439. package/packages/diagrams/src/lib/templates/cloud-arch/utils/awsValidation.ts +446 -446
  440. package/packages/diagrams/src/lib/templates/cloud-arch/utils/azure-icons.ts +802 -802
  441. package/packages/diagrams/src/lib/templates/cloud-arch/utils/azureValidation.ts +495 -495
  442. package/packages/diagrams/src/lib/templates/cloud-arch/utils/cloudValidation.ts +929 -929
  443. package/packages/diagrams/src/lib/templates/cloud-arch/utils/errorMessages.ts +283 -283
  444. package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcp-icons.ts +186 -186
  445. package/packages/diagrams/src/lib/templates/cloud-arch/utils/gcpValidation.ts +312 -312
  446. package/packages/diagrams/src/lib/templates/cloud-arch/utils/genericValidation.ts +689 -689
  447. package/packages/diagrams/src/lib/templates/cloud-arch/utils/iconMapping.ts +383 -383
  448. package/packages/diagrams/src/lib/templates/cloud-arch/utils/idGenerator.ts +220 -220
  449. package/packages/diagrams/src/lib/templates/cloud-arch/utils/localizationManager.ts +300 -300
  450. package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionEngine.ts +550 -550
  451. package/packages/diagrams/src/lib/templates/cloud-arch/utils/restrictionValidator.ts +400 -400
  452. package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceIcons.tsx +129 -129
  453. package/packages/diagrams/src/lib/templates/cloud-arch/utils/serviceMapping.ts +330 -330
  454. package/packages/diagrams/src/lib/templates/cloud-arch/utils/translations.ts +54 -54
  455. package/packages/diagrams/src/lib/templates/cloud-arch/utils/validationExtractor.ts +342 -342
  456. package/packages/diagrams/src/lib/templates/collaborationDiagram/CollaborationDiagram.tsx +15 -15
  457. package/packages/diagrams/src/lib/templates/collaborationDiagram/components/AddCollabEdgeDialog.tsx +181 -181
  458. package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabLayout.ts +182 -182
  459. package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollabObjectNodeSettings.tsx +86 -86
  460. package/packages/diagrams/src/lib/templates/collaborationDiagram/components/CollaborationDiagramFlow.tsx +731 -731
  461. package/packages/diagrams/src/lib/templates/collaborationDiagram/components/DraggableEdgeLabel.tsx +123 -123
  462. package/packages/diagrams/src/lib/templates/collaborationDiagram/controls/CollaborationControls.tsx +131 -131
  463. package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabEdge.tsx +170 -170
  464. package/packages/diagrams/src/lib/templates/collaborationDiagram/nodes/CollabObjectNode.tsx +178 -178
  465. package/packages/diagrams/src/lib/templates/home.style.css +16 -16
  466. package/packages/diagrams/src/lib/templates/node-forms/ApiForm.tsx +416 -416
  467. package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
  468. package/packages/diagrams/src/lib/templates/node-forms/ForLoopNode.tsx +313 -313
  469. package/packages/diagrams/src/lib/templates/node-forms/FunctionForm.tsx +211 -211
  470. package/packages/diagrams/src/lib/templates/node-forms/GraphQLForm.tsx +679 -679
  471. package/packages/diagrams/src/lib/templates/node-forms/IfNodeForm.tsx +97 -97
  472. package/packages/diagrams/src/lib/templates/node-forms/LetNodeForm.tsx +533 -533
  473. package/packages/diagrams/src/lib/templates/node-forms/LoopNode.tsx +149 -149
  474. package/packages/diagrams/src/lib/templates/node-forms/NodeForm.tsx +383 -383
  475. package/packages/diagrams/src/lib/templates/node-forms/ReturnNodeForm.tsx +96 -96
  476. package/packages/diagrams/src/lib/templates/node-forms/SetNodeForm.tsx +141 -141
  477. package/packages/diagrams/src/lib/templates/node-forms/SwitchNodeForm.tsx +249 -249
  478. package/packages/diagrams/src/lib/templates/node-forms/TryCatchForm.tsx +167 -167
  479. package/packages/diagrams/src/lib/templates/nodeFormSchema.json +84 -84
  480. package/packages/diagrams/src/lib/templates/sequence/SequenceDiagram.tsx +22 -22
  481. package/packages/diagrams/src/lib/templates/sequence/components/ActivationBarNode.tsx +33 -33
  482. package/packages/diagrams/src/lib/templates/sequence/components/AddMessageDialog.tsx +302 -302
  483. package/packages/diagrams/src/lib/templates/sequence/components/CombinedFragmentNode.tsx +65 -65
  484. package/packages/diagrams/src/lib/templates/sequence/components/EntitySettings.tsx +559 -559
  485. package/packages/diagrams/src/lib/templates/sequence/components/FragmentSettings.tsx +116 -116
  486. package/packages/diagrams/src/lib/templates/sequence/components/SequenceComponents.tsx +14 -14
  487. package/packages/diagrams/src/lib/templates/sequence/components/SequenceDiagramFlow.tsx +1361 -1361
  488. package/packages/diagrams/src/lib/templates/sequence/components/SequenceEntityNode.tsx +394 -394
  489. package/packages/diagrams/src/lib/templates/sequence/components/SequenceMessageEdge.tsx +272 -272
  490. package/packages/diagrams/src/lib/templates/sequence/components/SimpleEntitySettings.tsx +89 -89
  491. package/packages/diagrams/src/lib/templates/sequence/controls/DiagramControls.tsx +707 -707
  492. package/packages/diagrams/src/lib/templates/sequence/data/template-data.ts +635 -635
  493. package/packages/diagrams/src/lib/templates/stateMachine/StateMachineDiagram.tsx +66 -66
  494. package/packages/diagrams/src/lib/templates/stateMachine/components/CompositeStateNodeSettings.tsx +638 -638
  495. package/packages/diagrams/src/lib/templates/stateMachine/components/CustomEdge.tsx +220 -220
  496. package/packages/diagrams/src/lib/templates/stateMachine/components/EdgeSettings.tsx +193 -193
  497. package/packages/diagrams/src/lib/templates/stateMachine/components/SelfConnectingEdge.tsx +41 -41
  498. package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineComponents.tsx +49 -49
  499. package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineDiagramFlow.tsx +1238 -1238
  500. package/packages/diagrams/src/lib/templates/stateMachine/components/StateMachineLayout.ts +350 -350
  501. package/packages/diagrams/src/lib/templates/stateMachine/components/StateNodeSettings.tsx +188 -188
  502. package/packages/diagrams/src/lib/templates/stateMachine/components/useSelfTransition.ts +114 -114
  503. package/packages/diagrams/src/lib/templates/stateMachine/controls/StateDiagramControls.tsx +488 -488
  504. package/packages/diagrams/src/lib/templates/stateMachine/data/template-data.ts +4 -4
  505. package/packages/diagrams/src/lib/templates/stateMachine/nodes/ChoicePointNode.tsx +54 -54
  506. package/packages/diagrams/src/lib/templates/stateMachine/nodes/CompositeStateNode.tsx +225 -225
  507. package/packages/diagrams/src/lib/templates/stateMachine/nodes/EntryPointNode.tsx +31 -31
  508. package/packages/diagrams/src/lib/templates/stateMachine/nodes/ExitPointNode.tsx +44 -44
  509. package/packages/diagrams/src/lib/templates/stateMachine/nodes/FinalStateNode.tsx +41 -41
  510. package/packages/diagrams/src/lib/templates/stateMachine/nodes/ForkJoinNode.tsx +53 -53
  511. package/packages/diagrams/src/lib/templates/stateMachine/nodes/HistoryStateNode.tsx +36 -36
  512. package/packages/diagrams/src/lib/templates/stateMachine/nodes/InitialStateNode.tsx +29 -29
  513. package/packages/diagrams/src/lib/templates/stateMachine/nodes/JunctionPointNode.tsx +33 -33
  514. package/packages/diagrams/src/lib/templates/stateMachine/nodes/PinPointNode.tsx +111 -111
  515. package/packages/diagrams/src/lib/templates/stateMachine/nodes/StateNode.tsx +124 -124
  516. package/packages/diagrams/src/lib/templates/stateMachine/nodes/bendPoint.tsx +71 -71
  517. package/packages/diagrams/src/lib/templates/systemFlow/SystemFlowDiagram.tsx +67 -67
  518. package/packages/diagrams/src/lib/templates/systemFlow/components/EdgeSettings.tsx +330 -330
  519. package/packages/diagrams/src/lib/templates/systemFlow/components/FloatingEdge.tsx +219 -219
  520. package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowComponents.tsx +28 -28
  521. package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowDiagramFlow.tsx +1179 -1179
  522. package/packages/diagrams/src/lib/templates/systemFlow/components/SystemFlowNodeSettings.tsx +151 -151
  523. package/packages/diagrams/src/lib/templates/systemFlow/controls/SystemFlowControls.tsx +435 -435
  524. package/packages/diagrams/src/lib/templates/systemFlow/data/template-data.ts +308 -308
  525. package/packages/diagrams/src/lib/templates/systemFlow/demo.tsx +91 -91
  526. package/packages/diagrams/src/lib/templates/systemFlow/index.ts +5 -5
  527. package/packages/diagrams/src/lib/templates/systemFlow/nodes/BendpointNode.tsx +80 -80
  528. package/packages/diagrams/src/lib/templates/systemFlow/nodes/SystemNode.tsx +92 -92
  529. package/packages/diagrams/src/lib/templates/systemFlow/nodes/TreeSystemNode.tsx +755 -755
  530. package/packages/diagrams/src/lib/templates/useCaseDiagram/UseCaseDiagram.tsx +16 -16
  531. package/packages/diagrams/src/lib/templates/useCaseDiagram/components/ActorNodeSettings.tsx +103 -103
  532. package/packages/diagrams/src/lib/templates/useCaseDiagram/components/AddRelationshipDialog.tsx +186 -186
  533. package/packages/diagrams/src/lib/templates/useCaseDiagram/components/PackageNodeSettings.tsx +205 -205
  534. package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseDiagramFlow.tsx +637 -637
  535. package/packages/diagrams/src/lib/templates/useCaseDiagram/components/UseCaseNodeSettings.tsx +120 -120
  536. package/packages/diagrams/src/lib/templates/useCaseDiagram/controls/UseCaseControls.tsx +289 -289
  537. package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/PackageNode.tsx +83 -83
  538. package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseEdge.tsx +115 -115
  539. package/packages/diagrams/src/lib/templates/useCaseDiagram/nodes/UseCaseNode.tsx +230 -230
  540. package/packages/diagrams/src/lib/templates/validationSchema.json +277 -277
  541. package/packages/diagrams/src/lib/theme.ts +439 -439
  542. package/packages/diagrams/src/lib/types/FunctionSignature.ts +11 -11
  543. package/packages/diagrams/src/lib/types/SmartDynamicFormField.ts +37 -37
  544. package/packages/diagrams/src/lib/types/automation-node-data-types.ts +45 -131
  545. package/packages/diagrams/src/lib/types/available-variables.ts +18 -18
  546. package/packages/diagrams/src/lib/types/card-node.ts +68 -68
  547. package/packages/diagrams/src/lib/types/collaboration-types.ts +114 -114
  548. package/packages/diagrams/src/lib/types/colors.ts +25 -25
  549. package/packages/diagrams/src/lib/types/condition-builder.ts +18 -18
  550. package/packages/diagrams/src/lib/types/diagram-types.ts +14 -14
  551. package/packages/diagrams/src/lib/types/edge-types.ts +39 -39
  552. package/packages/diagrams/src/lib/types/function-execution.ts +35 -35
  553. package/packages/diagrams/src/lib/types/hooks.types.ts +6 -6
  554. package/packages/diagrams/src/lib/types/ndoe-form-types.ts +139 -139
  555. package/packages/diagrams/src/lib/types/node-types.ts +13 -23
  556. package/packages/diagrams/src/lib/types/sequence-types.ts +178 -178
  557. package/packages/diagrams/src/lib/types/shared-node-types.ts +21 -21
  558. package/packages/diagrams/src/lib/types/state-machine-types.ts +225 -225
  559. package/packages/diagrams/src/lib/types/stencil-item.ts +7 -7
  560. package/packages/diagrams/src/lib/types/structures.ts +80 -80
  561. package/packages/diagrams/src/lib/types/system-flow-types.ts +129 -129
  562. package/packages/diagrams/src/lib/types/usecase-types.ts +84 -84
  563. package/packages/diagrams/src/lib/types/validation-types.ts +134 -134
  564. package/packages/diagrams/src/lib/types/workflow-content-dynamic-form-type.ts +23 -23
  565. package/packages/diagrams/src/lib/types/workflow-node-data-types.ts +172 -172
  566. package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +658 -1179
  567. package/packages/diagrams/src/lib/utils/add-new-block.ts +34 -34
  568. package/packages/diagrams/src/lib/utils/add-new-node.ts +52 -52
  569. package/packages/diagrams/src/lib/utils/addToHistory.ts +15 -15
  570. package/packages/diagrams/src/lib/utils/automation-flow-processor.ts +556 -619
  571. package/packages/diagrams/src/lib/utils/closestPoint.ts +45 -45
  572. package/packages/diagrams/src/lib/utils/color-options.tsx +26 -26
  573. package/packages/diagrams/src/lib/utils/compress-img.ts +59 -59
  574. package/packages/diagrams/src/lib/utils/configLoader.ts +329 -329
  575. package/packages/diagrams/src/lib/utils/constant-lengths.ts +8 -8
  576. package/packages/diagrams/src/lib/utils/create-updated.tsx +40 -40
  577. package/packages/diagrams/src/lib/utils/createHistoryChange.ts +3 -3
  578. package/packages/diagrams/src/lib/utils/dividerUtils.tsx +59 -59
  579. package/packages/diagrams/src/lib/utils/edge-hooks.ts +53 -53
  580. package/packages/diagrams/src/lib/utils/elkLayout.ts +297 -297
  581. package/packages/diagrams/src/lib/utils/event-hooks.ts +69 -69
  582. package/packages/diagrams/src/lib/utils/event-store.ts +58 -58
  583. package/packages/diagrams/src/lib/utils/flow-node-hooks.ts +28 -28
  584. package/packages/diagrams/src/lib/utils/flow-to-js.ts +1465 -1465
  585. package/packages/diagrams/src/lib/utils/functionGenerator.ts +38 -38
  586. package/packages/diagrams/src/lib/utils/generateEdgesFromNodeOrder.ts +113 -113
  587. package/packages/diagrams/src/lib/utils/helpers.types.ts +10 -10
  588. package/packages/diagrams/src/lib/utils/highlightText.tsx +93 -93
  589. package/packages/diagrams/src/lib/utils/iconMapper.tsx +76 -76
  590. package/packages/diagrams/src/lib/utils/logger.ts +5 -5
  591. package/packages/diagrams/src/lib/utils/model-hooks.ts +129 -129
  592. package/packages/diagrams/src/lib/utils/node-hooks.ts +78 -78
  593. package/packages/diagrams/src/lib/utils/nodeAIAssistantConfig.ts +54 -54
  594. package/packages/diagrams/src/lib/utils/nodeOrderByEdges.ts +437 -437
  595. package/packages/diagrams/src/lib/utils/nodeutils.ts +242 -242
  596. package/packages/diagrams/src/lib/utils/object.ts +13 -13
  597. package/packages/diagrams/src/lib/utils/useDebounce.ts +19 -19
  598. package/packages/diagrams/src/lib/utils/utilities.ts +105 -105
  599. package/packages/diagrams/src/lib/utils/validationEngine.ts +610 -610
  600. package/packages/diagrams/src/lib/utils/vhToPixels.ts +9 -9
  601. package/packages/diagrams/tsconfig.json +21 -21
  602. package/packages/diagrams/tsconfig.lib.json +26 -25
  603. package/packages/diagrams/webpack.config.js +17 -17
  604. package/packages/interfaces/.babelrc +12 -12
  605. package/packages/interfaces/.eslintrc.json +18 -18
  606. package/packages/interfaces/README.md +7 -7
  607. package/packages/interfaces/project.json +8 -8
  608. package/packages/interfaces/src/index.ts +21 -21
  609. package/packages/interfaces/src/lib/Button.tsx +1 -1
  610. package/packages/interfaces/src/lib/DataGrid.ts +14 -14
  611. package/packages/interfaces/src/lib/StyledBox.tsx +1 -1
  612. package/packages/interfaces/src/lib/ToolbarItem.ts +7 -7
  613. package/packages/interfaces/src/lib/UserCard.ts +8 -8
  614. package/packages/interfaces/src/lib/yup.ts +3 -3
  615. package/packages/interfaces/tsconfig.json +17 -17
  616. package/packages/interfaces/tsconfig.lib.json +24 -24
  617. package/packages/molecules/.babelrc +12 -12
  618. package/packages/molecules/.eslintrc.json +18 -18
  619. package/packages/molecules/README.md +7 -7
  620. package/packages/molecules/project.json +8 -8
  621. package/packages/molecules/src/index.ts +47 -41
  622. package/packages/molecules/src/lib/ActionTextField/ActionTextField.module.css +7 -7
  623. package/packages/molecules/src/lib/ActionTextField/ActionTextField.spec.tsx +10 -10
  624. package/packages/molecules/src/lib/ActionTextField/ActionTextField.tsx +33 -33
  625. package/packages/molecules/src/lib/ClosableButton/CloseableButton.module.css +7 -7
  626. package/packages/molecules/src/lib/ClosableButton/CloseableButton.spec.tsx +11 -11
  627. package/packages/molecules/src/lib/ClosableButton/CloseableButton.tsx +69 -69
  628. package/packages/molecules/src/lib/EditorTab/EditorTab.module.css +7 -7
  629. package/packages/molecules/src/lib/EditorTab/EditorTab.spec.tsx +10 -10
  630. package/packages/molecules/src/lib/EditorTab/EditorTab.tsx +42 -42
  631. package/packages/molecules/src/lib/EditorTab/TabPanel.tsx +25 -25
  632. package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.module.css +7 -7
  633. package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.spec.tsx +10 -10
  634. package/packages/molecules/src/lib/ParamsActionField/ParamsActionField.tsx +24 -24
  635. package/packages/molecules/src/lib/SvgIcons/icons.tsx +323 -291
  636. package/packages/molecules/src/lib/SvgIcons/index.ts +31 -25
  637. package/packages/molecules/src/lib/SvgIcons/types.ts +7 -7
  638. package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.module.css +7 -7
  639. package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.spec.tsx +10 -10
  640. package/packages/molecules/src/lib/TableWithInlineView/TableWithInlineView.tsx +47 -47
  641. package/packages/molecules/src/lib/UserCard/UserCard.module.css +7 -7
  642. package/packages/molecules/src/lib/UserCard/UserCard.spec.tsx +11 -11
  643. package/packages/molecules/src/lib/UserCard/UserCard.tsx +22 -22
  644. package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.module.css +7 -7
  645. package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.spec.tsx +10 -10
  646. package/packages/molecules/src/lib/VerbSelection/HTTPVerbSelection.tsx +72 -72
  647. package/packages/molecules/tsconfig.json +17 -17
  648. package/packages/molecules/tsconfig.lib.json +30 -30
  649. package/packages/organisms/.babelrc +12 -12
  650. package/packages/organisms/.eslintrc.json +18 -18
  651. package/packages/organisms/README.md +7 -7
  652. package/packages/organisms/project.json +8 -8
  653. package/packages/organisms/src/index.ts +4 -4
  654. package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.module.css +7 -7
  655. package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.spec.tsx +10 -10
  656. package/packages/organisms/src/lib/EditorToolbar/EditorToolbar.tsx +117 -117
  657. package/packages/organisms/src/lib/EditorToolbar/SortableItem.tsx +51 -51
  658. package/packages/organisms/src/lib/UserList/UserList.module.css +7 -7
  659. package/packages/organisms/src/lib/UserList/UserList.spec.tsx +11 -11
  660. package/packages/organisms/src/lib/UserList/UserList.tsx +48 -48
  661. package/packages/organisms/src/lib/UserList/store.ts +49 -49
  662. package/packages/organisms/tsconfig.json +17 -17
  663. package/packages/organisms/tsconfig.lib.json +24 -24
  664. package/packages/zustand/.babelrc +12 -12
  665. package/packages/zustand/.eslintrc.json +18 -18
  666. package/packages/zustand/README.md +7 -7
  667. package/packages/zustand/project.json +8 -8
  668. package/packages/zustand/src/index.ts +4 -4
  669. package/packages/zustand/tsconfig.json +17 -17
  670. package/packages/zustand/tsconfig.lib.json +24 -24
  671. package/tsconfig.base.json +29 -29
  672. package/packages/diagrams/src/lib/components/automation/AutomationAISuggestionNode.tsx +0 -304
  673. package/packages/diagrams/src/lib/components/automation/AutomationEmailNode.tsx +0 -773
  674. package/packages/diagrams/src/lib/components/automation/AutomationGoogleServicesNode.tsx +0 -779
  675. package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +0 -422
  676. package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +0 -1135
  677. package/packages/diagrams/src/lib/examples/GoogleSheetsConfigurationExamples.ts +0 -306
@@ -1,961 +1,961 @@
1
- // Browser-compatible Google Sheets service
2
- // Note: This is a simplified version for browser environments
3
- // For production use, consider using a backend API to handle Google Sheets operations
4
-
5
- import * as XLSX from 'xlsx';
6
- import { saveAs } from 'file-saver';
7
-
8
- // GIS global injected by `https://accounts.google.com/gsi/client`
9
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- declare const google: any;
11
-
12
- // Mock Google Sheets API for browser environment
13
- const mockGoogleSheetsAPI = {
14
- spreadsheets: {
15
- values: {
16
- update: async (params: any) => {
17
- // Simulate API call delay
18
- await new Promise((resolve) => setTimeout(resolve, 1000));
19
- return {
20
- data: {
21
- updatedRows: params.requestBody.values.length,
22
- updatedColumns: params.requestBody.values[0]?.length || 0,
23
- updatedCells:
24
- params.requestBody.values.length *
25
- (params.requestBody.values[0]?.length || 0),
26
- },
27
- };
28
- },
29
- get: async (params: any) => {
30
- await new Promise((resolve) => setTimeout(resolve, 500));
31
- return {
32
- data: {
33
- values: [],
34
- },
35
- };
36
- },
37
- clear: async (params: any) => {
38
- await new Promise((resolve) => setTimeout(resolve, 500));
39
- return {
40
- data: {
41
- clearedRange: params.range,
42
- },
43
- };
44
- },
45
- },
46
- },
47
- };
48
-
49
- export interface GoogleSheetsConfig {
50
- spreadsheetId: string;
51
- sheetName: string;
52
- range: string;
53
- credentials: {
54
- type: 'service-account' | 'oauth' | 'api-key';
55
- serviceAccountKey?: string;
56
- oauthToken?: string;
57
- apiKey?: string;
58
- clientEmail?: string;
59
- privateKey?: string;
60
- // OAuth client flow (Google Identity Services)
61
- clientId?: string;
62
- scopes?: string[];
63
- };
64
- }
65
-
66
- export interface DataMapping {
67
- headers: Array<{
68
- column: string;
69
- sourceField: string;
70
- dataType: 'string' | 'number' | 'date' | 'boolean';
71
- }>;
72
- appendMode: boolean;
73
- clearSheet: boolean;
74
- }
75
-
76
- export interface SheetsExportOptions {
77
- emailRecipients?: string[];
78
- fileName?: string;
79
- exportFormat?: 'sheets' | 'excel';
80
- includeHeaders?: boolean;
81
- }
82
-
83
- export interface SheetsResponse {
84
- spreadsheetId: string;
85
- sheetName: string;
86
- range: string;
87
- rowsAdded: number;
88
- columnsMapped: number;
89
- data: any[];
90
- exportTime: string;
91
- success: boolean;
92
- spreadsheetUrl?: string;
93
- downloadUrl?: string;
94
- emailSent?: boolean;
95
- }
96
-
97
- export class GoogleSheetsService {
98
- private sheets: any = null;
99
- private auth: any = null;
100
- private isBrowserEnvironment: boolean;
101
- private accessToken: string | null = null;
102
- private gisLoaded: boolean = false;
103
- private hasRequestedConsent: boolean = false;
104
- private requestedScopes: Set<string> = new Set();
105
-
106
- constructor() {
107
- // Detect if we're in a browser environment
108
- this.isBrowserEnvironment = typeof window !== 'undefined';
109
- }
110
-
111
- /**
112
- * Initialize Google Sheets API with authentication
113
- * Note: In browser environment, this uses a mock API for demonstration
114
- */
115
- async initialize(config: GoogleSheetsConfig): Promise<void> {
116
- try {
117
- if (this.isBrowserEnvironment) {
118
- // If OAuth credentials are provided, initialize Google Identity Services
119
- if (
120
- config.credentials?.type === 'oauth' &&
121
- (config.credentials.clientEmail ||
122
- config.credentials.oauthToken ||
123
- config.credentials.clientId)
124
- ) {
125
- // Prefer OAuth clientId flow (GIS)
126
- if (config.credentials.clientId) {
127
- await this.ensureGisLoaded();
128
- await this.requestAccessToken(
129
- config.credentials.clientId,
130
- config.credentials.scopes || [
131
- 'https://www.googleapis.com/auth/spreadsheets',
132
- ],
133
- );
134
- this.sheets = 'rest';
135
- this.auth = {
136
- type: 'oauth',
137
- clientId: config.credentials.clientId,
138
- scopes: config.credentials.scopes || [
139
- 'https://www.googleapis.com/auth/spreadsheets',
140
- ],
141
- };
142
- return;
143
- }
144
-
145
- // Fallback: if oauthToken is provided directly (e.g., injected), use it
146
- if (config.credentials.oauthToken) {
147
- this.accessToken = config.credentials.oauthToken;
148
- this.sheets = 'rest';
149
- this.auth = {
150
- type: 'oauth',
151
- clientId: config.credentials.clientId,
152
- scopes: config.credentials.scopes || [
153
- 'https://www.googleapis.com/auth/spreadsheets',
154
- ],
155
- };
156
- return;
157
- }
158
- }
159
-
160
- // Browser environment without OAuth clientId – use mock API
161
- console.log(
162
- 'Browser environment detected - using mock Google Sheets API',
163
- );
164
- this.sheets = mockGoogleSheetsAPI;
165
- this.auth = { type: config.credentials?.type || 'mock' };
166
- return;
167
- }
168
-
169
- // Node.js environment - would use real Google APIs
170
- // This would require server-side implementation
171
- throw new Error(
172
- 'Real Google Sheets API integration requires server-side implementation',
173
- );
174
- } catch (error) {
175
- throw new Error(
176
- `Failed to initialize Google Sheets API: ${error.message}`,
177
- );
178
- }
179
- }
180
-
181
- /**
182
- * Ensure Google Identity Services script is loaded
183
- */
184
- private async ensureGisLoaded(): Promise<void> {
185
- if (!this.isBrowserEnvironment) return;
186
- if (this.gisLoaded) return;
187
-
188
- await new Promise<void>((resolve, reject) => {
189
- const existing = document.querySelector(
190
- 'script[src="https://accounts.google.com/gsi/client"]',
191
- );
192
- if (existing) {
193
- this.gisLoaded = true;
194
- resolve();
195
- return;
196
- }
197
-
198
- const script = document.createElement('script');
199
- script.src = 'https://accounts.google.com/gsi/client';
200
- script.async = true;
201
- script.defer = true;
202
- script.onload = () => {
203
- this.gisLoaded = true;
204
- resolve();
205
- };
206
- script.onerror = () => reject(new Error('Failed to load GIS script'));
207
- document.head.appendChild(script);
208
- });
209
- }
210
-
211
- /**
212
- * Request an OAuth access token using GIS token client
213
- */
214
- private async requestAccessToken(
215
- clientId: string,
216
- scopes: string[],
217
- forceConsent: boolean = false,
218
- ): Promise<string> {
219
- if (!this.isBrowserEnvironment) {
220
- throw new Error('OAuth is only available in browser environment');
221
- }
222
-
223
- await this.ensureGisLoaded();
224
-
225
- const token = await new Promise<string>((resolve, reject) => {
226
- try {
227
- // @ts-ignore - google global injected by GIS
228
- const tokenClient = google.accounts.oauth2.initTokenClient({
229
- client_id: clientId,
230
- scope: scopes.join(' '),
231
- callback: (response: any) => {
232
- // Handle both success and error shapes
233
- if (response && response.access_token) {
234
- this.hasRequestedConsent = true;
235
- // Track that we've requested these scopes
236
- scopes.forEach((s) => this.requestedScopes.add(s));
237
- resolve(response.access_token);
238
- return;
239
- }
240
- const err = response?.error || 'unknown_error';
241
- const desc = response?.error_description || 'No description';
242
- reject(new Error(`OAuth token error: ${err} - ${desc}`));
243
- },
244
- });
245
-
246
- // First-time call must show consent; subsequent calls can be silent
247
- tokenClient.requestAccessToken({
248
- prompt: forceConsent
249
- ? 'consent'
250
- : this.hasRequestedConsent
251
- ? ''
252
- : 'consent',
253
- });
254
- } catch (e) {
255
- reject(e);
256
- }
257
- });
258
-
259
- this.accessToken = token;
260
- // Persist clientId and union of scopes in auth cache for later scope upgrades
261
- if (this.auth && typeof this.auth === 'object') {
262
- (this.auth as any).clientId = clientId;
263
- const union = Array.from(
264
- new Set([...(this.auth.scopes || []), ...scopes]),
265
- );
266
- (this.auth as any).scopes = union;
267
- }
268
- return token;
269
- }
270
-
271
- /**
272
- * Ensure the active token includes the given scopes. If not, request a new token with the union.
273
- */
274
- private async ensureScopes(requiredScopes: string[]): Promise<void> {
275
- if (!this.isBrowserEnvironment) return;
276
- if (!requiredScopes || requiredScopes.length === 0) return;
277
- // If we don't have OAuth client flow, nothing to do
278
- const clientId = (this as any).pendingClientId || undefined;
279
- // We infer clientId from last initialize call by reading from DOM script params is not reliable.
280
- // Instead, try to reuse the last known clientId from token creation by caching it in auth.
281
- const authClientId: string | undefined =
282
- (this.auth && this.auth.clientId) || undefined;
283
- const effectiveClientId = authClientId || clientId;
284
- if (!effectiveClientId) return;
285
-
286
- const missing = requiredScopes.filter((s) => !this.requestedScopes.has(s));
287
- if (missing.length === 0) return;
288
-
289
- const union = Array.from(
290
- new Set([...Array.from(this.requestedScopes), ...requiredScopes]),
291
- );
292
- await this.requestAccessToken(effectiveClientId, union, true);
293
- if (this.auth && typeof this.auth === 'object') {
294
- (this.auth as any).scopes = union;
295
- }
296
- }
297
-
298
- /**
299
- * Build a minimal RFC 2822 MIME message (plain text) and return base64url string.
300
- */
301
- private buildMimeMessage(params: {
302
- from?: string;
303
- to: string[];
304
- subject?: string;
305
- body?: string;
306
- }): string {
307
- const headers: string[] = [];
308
- if (params.from) headers.push(`From: ${params.from}`);
309
- headers.push(`To: ${params.to.join(', ')}`);
310
- if (params.subject) headers.push(`Subject: ${params.subject}`);
311
- headers.push('MIME-Version: 1.0');
312
- headers.push('Content-Type: text/plain; charset=UTF-8');
313
-
314
- const lines = [...headers, '', params.body || ''];
315
- const raw = lines.join('\r\n');
316
- return this.encodeBase64Url(raw);
317
- }
318
-
319
- /**
320
- * Encode string to base64url (RFC 4648 §5), as required by Gmail API.
321
- */
322
- private encodeBase64Url(input: string): string {
323
- // btoa works with Latin1; for UTF-8 we need to encode first
324
- const utf8 = unescape(encodeURIComponent(input));
325
- const b64 = btoa(utf8);
326
- return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
327
- }
328
-
329
- /**
330
- * Attempt to send an email via Gmail API using the current OAuth token.
331
- */
332
- private async sendViaGmailApi(params: {
333
- from?: string;
334
- to: string[];
335
- subject?: string;
336
- message?: string;
337
- spreadsheetUrl?: string;
338
- // attachments are not implemented in this client-side example
339
- }): Promise<boolean> {
340
- const requiredScope = 'https://www.googleapis.com/auth/gmail.send';
341
- await this.ensureScopes([requiredScope]);
342
-
343
- if (!this.accessToken) {
344
- throw new Error('Not authenticated to Google APIs');
345
- }
346
-
347
- const bodyParts: string[] = [];
348
- if (params.message) bodyParts.push(params.message);
349
- if (params.spreadsheetUrl)
350
- bodyParts.push(`Spreadsheet: ${params.spreadsheetUrl}`);
351
- const body = bodyParts.join('\n\n');
352
-
353
- const raw = this.buildMimeMessage({
354
- from: params.from,
355
- to: params.to,
356
- subject: params.subject || 'Automation Output',
357
- body,
358
- });
359
-
360
- const res = await fetch(
361
- 'https://gmail.googleapis.com/gmail/v1/users/me/messages/send',
362
- {
363
- method: 'POST',
364
- headers: {
365
- 'Content-Type': 'application/json',
366
- Authorization: `Bearer ${this.accessToken}`,
367
- },
368
- body: JSON.stringify({ raw }),
369
- },
370
- );
371
-
372
- if (!res.ok) {
373
- const text = await res.text();
374
- throw new Error(
375
- `Gmail send error ${res.status}: ${res.statusText} - ${text}`,
376
- );
377
- }
378
- return true;
379
- }
380
-
381
- /**
382
- * Helper: call Google Sheets REST API using fetch
383
- */
384
- private async apiFetch(
385
- path: string,
386
- options: {
387
- method?: string;
388
- body?: any;
389
- params?: Record<string, string>;
390
- } = {},
391
- ): Promise<any> {
392
- if (!this.accessToken) {
393
- throw new Error('Not authenticated to Google APIs');
394
- }
395
-
396
- const base = 'https://sheets.googleapis.com/v4';
397
- const url = new URL(base + path);
398
- if (options.params) {
399
- Object.entries(options.params).forEach(([k, v]) =>
400
- url.searchParams.set(k, v),
401
- );
402
- }
403
-
404
- const res = await fetch(url.toString(), {
405
- method: options.method || 'GET',
406
- headers: {
407
- 'Content-Type': 'application/json',
408
- Authorization: `Bearer ${this.accessToken}`,
409
- },
410
- body: options.body ? JSON.stringify(options.body) : undefined,
411
- });
412
-
413
- if (!res.ok) {
414
- const text = await res.text();
415
- throw new Error(
416
- `Google API error ${res.status}: ${res.statusText} - ${text}`,
417
- );
418
- }
419
- return res.json();
420
- }
421
-
422
- /**
423
- * Send email via Gmail API if authorized; fallback to mailto for simple cases
424
- */
425
- public async sendEmail(params: {
426
- from?: string;
427
- to: string[];
428
- subject?: string;
429
- message?: string;
430
- spreadsheetUrl?: string;
431
- attachExcelBlob?: Blob;
432
- attachExcelFileName?: string;
433
- disableUiFallback?: boolean;
434
- }): Promise<boolean> {
435
- // If we have OAuth token, try Gmail API (request scope on-demand)
436
- const hasOauth = this.auth?.type === 'oauth' && this.accessToken;
437
- if (hasOauth) {
438
- try {
439
- const sent = await this.sendViaGmailApi({
440
- from: params.from,
441
- to: params.to,
442
- subject: params.subject,
443
- message: params.message,
444
- spreadsheetUrl: params.spreadsheetUrl,
445
- });
446
- if (sent) return true;
447
- } catch (e) {
448
- // Fall through to UI-based flow if API send fails (e.g., insufficient permissions)
449
- console.warn(
450
- 'Gmail API send failed, falling back to UI:',
451
- (e as any).message || e,
452
- );
453
- }
454
- }
455
-
456
- // Prefer: open Gmail compose in a new tab (more reliable than OS mailto handler)
457
- if (this.isBrowserEnvironment && !params.disableUiFallback) {
458
- const to = encodeURIComponent(params.to.join(','));
459
- const subject = encodeURIComponent(params.subject || 'Automation Output');
460
- const bodyParts: string[] = [];
461
- if (params.message) bodyParts.push(params.message);
462
- if (params.spreadsheetUrl)
463
- bodyParts.push(`Spreadsheet: ${params.spreadsheetUrl}`);
464
- const body = encodeURIComponent(bodyParts.join('\n\n'));
465
-
466
- // Try Gmail compose
467
- const gmailUrl = `https://mail.google.com/mail/?view=cm&fs=1&to=${to}&su=${subject}&body=${body}`;
468
- const win = window.open(gmailUrl, '_blank', 'noopener,noreferrer');
469
- if (win) {
470
- return true;
471
- }
472
-
473
- // Fallback: OS handler via mailto
474
- // Note: attachments are not supported via mailto; advise using Gmail scope for API send
475
- const a = document.createElement('a');
476
- a.href = `mailto:${to}?subject=${subject}&body=${body}`;
477
- a.style.display = 'none';
478
- document.body.appendChild(a);
479
- a.click();
480
- document.body.removeChild(a);
481
-
482
- return true;
483
- }
484
-
485
- return false;
486
- }
487
-
488
- /**
489
- * Export data to Google Sheets
490
- * Note: In browser environment, this simulates the export process
491
- */
492
- async exportToSheets(
493
- data: any[],
494
- config: GoogleSheetsConfig,
495
- dataMapping: DataMapping,
496
- options: SheetsExportOptions = {},
497
- ): Promise<SheetsResponse> {
498
- if (!this.sheets) {
499
- throw new Error('Google Sheets API not initialized');
500
- }
501
-
502
- try {
503
- // Prepare data for export
504
- const mappedData = this.mapDataToColumns(data, dataMapping);
505
- const includeHeaders = options.includeHeaders !== false;
506
-
507
- // If using real OAuth flow, call REST API; otherwise, use mock behavior
508
- const usingRest =
509
- this.auth?.type === 'oauth' &&
510
- this.accessToken &&
511
- this.sheets === 'rest';
512
-
513
- // Ensure spreadsheet exists when using REST
514
- let spreadsheetId = config.spreadsheetId;
515
- if (usingRest && !spreadsheetId) {
516
- const created = await this.apiFetch('/spreadsheets', {
517
- method: 'POST',
518
- body: {
519
- properties: { title: options.fileName || 'Automation Export' },
520
- sheets: [
521
- {
522
- properties: { title: config.sheetName || 'Sheet1' },
523
- },
524
- ],
525
- },
526
- });
527
- spreadsheetId = created.spreadsheetId;
528
- config.spreadsheetId = spreadsheetId;
529
- }
530
-
531
- // Ensure sheet exists
532
- if (usingRest && spreadsheetId && config.sheetName) {
533
- const meta = await this.apiFetch(`/spreadsheets/${spreadsheetId}`, {
534
- params: { fields: 'sheets.properties.title' },
535
- });
536
- const hasSheet = (meta.sheets || []).some(
537
- (s: any) => s.properties && s.properties.title === config.sheetName,
538
- );
539
- if (!hasSheet) {
540
- await this.apiFetch(`/spreadsheets/${spreadsheetId}:batchUpdate`, {
541
- method: 'POST',
542
- body: {
543
- requests: [
544
- {
545
- addSheet: { properties: { title: config.sheetName } },
546
- },
547
- ],
548
- },
549
- });
550
- }
551
- }
552
-
553
- // Clear sheet if requested
554
- if (dataMapping.clearSheet) {
555
- await this.clearSheet(config);
556
- }
557
-
558
- // Prepare range for writing (account for header row if included)
559
- const totalRows = mappedData.length + (includeHeaders ? 1 : 0);
560
- const range = this.prepareRange(config, dataMapping, totalRows);
561
-
562
- // Prepare values array
563
- const values = this.prepareValues(
564
- mappedData,
565
- dataMapping,
566
- includeHeaders,
567
- );
568
-
569
- if (usingRest) {
570
- await this.apiFetch(
571
- `/spreadsheets/${config.spreadsheetId}/values/${encodeURIComponent(
572
- range,
573
- )}`,
574
- {
575
- method: 'PUT',
576
- params: { valueInputOption: 'RAW' },
577
- body: { values },
578
- },
579
- );
580
- } else {
581
- // Mock behavior
582
- await this.sheets.spreadsheets.values.update({
583
- spreadsheetId: config.spreadsheetId,
584
- range: range,
585
- valueInputOption: 'RAW',
586
- requestBody: { values },
587
- });
588
- }
589
-
590
- // Get spreadsheet URL
591
- const spreadsheetUrl = `https://docs.google.com/spreadsheets/d/${config.spreadsheetId}`;
592
-
593
- // Send email if recipients provided
594
- let emailSent = false;
595
- if (options.emailRecipients && options.emailRecipients.length > 0) {
596
- emailSent = await this.sendEmailNotification(
597
- options.emailRecipients,
598
- spreadsheetUrl,
599
- options.fileName || 'Google Sheets Export',
600
- );
601
- }
602
-
603
- return {
604
- spreadsheetId: config.spreadsheetId,
605
- sheetName: config.sheetName,
606
- range: range,
607
- rowsAdded: mappedData.length,
608
- columnsMapped: dataMapping.headers.length,
609
- data: mappedData,
610
- exportTime: new Date().toISOString(),
611
- success: true,
612
- spreadsheetUrl,
613
- emailSent,
614
- };
615
- } catch (error) {
616
- throw new Error(`Failed to export to Google Sheets: ${error.message}`);
617
- }
618
- }
619
-
620
- /**
621
- * Export data to Excel file and download
622
- */
623
- async exportToExcel(
624
- data: any[],
625
- dataMapping: DataMapping,
626
- options: SheetsExportOptions = {},
627
- ): Promise<SheetsResponse> {
628
- try {
629
- // Prepare data for export
630
- const mappedData = this.mapDataToColumns(data, dataMapping);
631
-
632
- // Create workbook
633
- const wb = XLSX.utils.book_new();
634
-
635
- // Prepare worksheet data
636
- const wsData = this.prepareExcelData(
637
- mappedData,
638
- dataMapping,
639
- options.includeHeaders !== false,
640
- );
641
-
642
- // Create worksheet
643
- const ws = XLSX.utils.aoa_to_sheet(wsData);
644
-
645
- // Add worksheet to workbook
646
- XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
647
-
648
- // Generate file name
649
- const fileName =
650
- options.fileName ||
651
- `export_${new Date().toISOString().split('T')[0]}.xlsx`;
652
-
653
- // Save file
654
- const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
655
- const blob = new Blob([excelBuffer], {
656
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
657
- });
658
- saveAs(blob, fileName);
659
-
660
- // Send email if recipients provided
661
- let emailSent = false;
662
- if (options.emailRecipients && options.emailRecipients.length > 0) {
663
- emailSent = await this.sendEmailWithAttachment(
664
- options.emailRecipients,
665
- blob,
666
- fileName,
667
- );
668
- }
669
-
670
- return {
671
- spreadsheetId: '',
672
- sheetName: 'Sheet1',
673
- range: '',
674
- rowsAdded: mappedData.length,
675
- columnsMapped: dataMapping.headers.length,
676
- data: mappedData,
677
- exportTime: new Date().toISOString(),
678
- success: true,
679
- downloadUrl: URL.createObjectURL(blob),
680
- emailSent,
681
- };
682
- } catch (error) {
683
- throw new Error(`Failed to export to Excel: ${error.message}`);
684
- }
685
- }
686
-
687
- /**
688
- * Map data according to column configuration
689
- */
690
- private mapDataToColumns(data: any[], dataMapping: DataMapping): any[] {
691
- return data.map((item: any) => {
692
- const row: any = {};
693
- dataMapping.headers.forEach((header) => {
694
- const value = this.getNestedValue(item, header.sourceField);
695
- row[header.column] = this.formatValueForSheets(value, header.dataType);
696
- });
697
- return row;
698
- });
699
- }
700
-
701
- /**
702
- * Get nested value from object using dot notation
703
- */
704
- private getNestedValue(obj: any, path: string): any {
705
- return path.split('.').reduce((current, key) => current?.[key], obj);
706
- }
707
-
708
- /**
709
- * Format value according to data type
710
- */
711
- private formatValueForSheets(value: any, dataType: string): any {
712
- if (value === null || value === undefined) {
713
- return '';
714
- }
715
-
716
- switch (dataType) {
717
- case 'number':
718
- return typeof value === 'number' ? value : parseFloat(value) || 0;
719
- case 'date':
720
- return value instanceof Date
721
- ? value.toISOString().split('T')[0]
722
- : value;
723
- case 'boolean':
724
- return Boolean(value);
725
- case 'string':
726
- default:
727
- return String(value);
728
- }
729
- }
730
-
731
- /**
732
- * Prepare range for writing data
733
- */
734
- private prepareRange(
735
- config: GoogleSheetsConfig,
736
- dataMapping: DataMapping,
737
- rowCount: number,
738
- ): string {
739
- const startColumn = dataMapping.headers[0]?.column || 'A';
740
- const endColumn =
741
- dataMapping.headers[dataMapping.headers.length - 1]?.column || 'Z';
742
- const startRow = dataMapping.clearSheet ? 1 : 1; // Simplified for browser
743
- const endRow = startRow + rowCount - 1;
744
-
745
- return `${config.sheetName}!${startColumn}${startRow}:${endColumn}${endRow}`;
746
- }
747
-
748
- /**
749
- * Clear sheet content
750
- */
751
- private async clearSheet(config: GoogleSheetsConfig): Promise<void> {
752
- if (!this.sheets) return;
753
-
754
- try {
755
- const usingRest =
756
- this.auth?.type === 'oauth' &&
757
- this.accessToken &&
758
- this.sheets === 'rest';
759
- const range = `${config.sheetName}!A:Z`;
760
- if (usingRest) {
761
- await this.apiFetch(
762
- `/spreadsheets/${config.spreadsheetId}/values/${encodeURIComponent(
763
- range,
764
- )}:clear`,
765
- { method: 'POST' },
766
- );
767
- } else {
768
- await this.sheets.spreadsheets.values.clear({
769
- spreadsheetId: config.spreadsheetId,
770
- range,
771
- });
772
- }
773
- } catch (error) {
774
- console.warn('Failed to clear sheet:', (error as any).message || error);
775
- }
776
- }
777
-
778
- /**
779
- * Prepare values array for Google Sheets API
780
- */
781
- private prepareValues(
782
- mappedData: any[],
783
- dataMapping: DataMapping,
784
- includeHeaders: boolean,
785
- ): any[][] {
786
- const values: any[][] = [];
787
-
788
- // Add headers if requested
789
- if (includeHeaders && dataMapping.headers.length > 0) {
790
- const headers = dataMapping.headers.map((h) => h.column);
791
- values.push(headers);
792
- }
793
-
794
- // Add data rows
795
- mappedData.forEach((row) => {
796
- const rowValues = dataMapping.headers.map(
797
- (header) => row[header.column] || '',
798
- );
799
- values.push(rowValues);
800
- });
801
-
802
- return values;
803
- }
804
-
805
- /**
806
- * Prepare data for Excel export
807
- */
808
- private prepareExcelData(
809
- mappedData: any[],
810
- dataMapping: DataMapping,
811
- includeHeaders: boolean,
812
- ): any[][] {
813
- const data: any[][] = [];
814
-
815
- // Add headers if requested
816
- if (includeHeaders && dataMapping.headers.length > 0) {
817
- const headers = dataMapping.headers.map((h) => h.column);
818
- data.push(headers);
819
- }
820
-
821
- // Add data rows
822
- mappedData.forEach((row) => {
823
- const rowValues = dataMapping.headers.map(
824
- (header) => row[header.column] || '',
825
- );
826
- data.push(rowValues);
827
- });
828
-
829
- return data;
830
- }
831
-
832
- /**
833
- * Send email notification with spreadsheet link
834
- */
835
- private async sendEmailNotification(
836
- recipients: string[],
837
- spreadsheetUrl: string,
838
- fileName: string,
839
- ): Promise<boolean> {
840
- try {
841
- // In browser environment, we'll simulate email sending
842
- console.log(
843
- `📧 Email notification would be sent to: ${recipients.join(', ')}`,
844
- );
845
- console.log(`📊 Spreadsheet URL: ${spreadsheetUrl}`);
846
- console.log(`📁 File: ${fileName}`);
847
-
848
- // Show a browser notification or alert
849
- if (this.isBrowserEnvironment && 'Notification' in window) {
850
- if (Notification.permission === 'granted') {
851
- new Notification('Google Sheets Export', {
852
- body: `Data exported successfully! Sent to ${recipients.length} recipient(s).`,
853
- icon: '/favicon.ico',
854
- });
855
- }
856
- }
857
-
858
- return true;
859
- } catch (error) {
860
- console.error('Failed to send email notification:', error);
861
- return false;
862
- }
863
- }
864
-
865
- /**
866
- * Send email with Excel attachment
867
- */
868
- private async sendEmailWithAttachment(
869
- recipients: string[],
870
- fileBlob: Blob,
871
- fileName: string,
872
- ): Promise<boolean> {
873
- try {
874
- // In browser environment, we'll simulate email sending
875
- console.log(
876
- `📧 Email with attachment would be sent to: ${recipients.join(', ')}`,
877
- );
878
- console.log(`📎 Attachment: ${fileName}`);
879
- console.log(`📊 File size: ${(fileBlob.size / 1024).toFixed(2)} KB`);
880
-
881
- // Show a browser notification
882
- if (this.isBrowserEnvironment && 'Notification' in window) {
883
- if (Notification.permission === 'granted') {
884
- new Notification('Excel Export', {
885
- body: `Excel file "${fileName}" exported successfully! Sent to ${recipients.length} recipient(s).`,
886
- icon: '/favicon.ico',
887
- });
888
- }
889
- }
890
-
891
- return true;
892
- } catch (error) {
893
- console.error('Failed to send email with attachment:', error);
894
- return false;
895
- }
896
- }
897
-
898
- /**
899
- * Validate configuration
900
- */
901
- validateConfig(config: GoogleSheetsConfig): {
902
- valid: boolean;
903
- errors: string[];
904
- } {
905
- const errors: string[] = [];
906
-
907
- if (!config.spreadsheetId) {
908
- // Allow creating a new spreadsheet when using OAuth clientId
909
- if (
910
- !(config.credentials?.type === 'oauth' && config.credentials.clientId)
911
- ) {
912
- errors.push(
913
- 'Spreadsheet ID is required (or provide OAuth clientId to create a new one)',
914
- );
915
- }
916
- }
917
-
918
- if (!config.sheetName) {
919
- errors.push('Sheet name is required');
920
- }
921
-
922
- if (!config.credentials) {
923
- errors.push('Credentials are required');
924
- } else {
925
- if (config.credentials.type === 'service-account') {
926
- if (
927
- !config.credentials.serviceAccountKey &&
928
- !config.credentials.clientEmail
929
- ) {
930
- errors.push('Service account key or client email is required');
931
- }
932
- if (
933
- !config.credentials.serviceAccountKey &&
934
- !config.credentials.privateKey
935
- ) {
936
- errors.push('Service account key or private key is required');
937
- }
938
- } else if (config.credentials.type === 'api-key') {
939
- if (!config.credentials.apiKey) {
940
- errors.push('API key is required');
941
- }
942
- } else if (config.credentials.type === 'oauth') {
943
- // Accept either a provided token or clientId for GIS
944
- if (!config.credentials.oauthToken && !config.credentials.clientId) {
945
- errors.push('OAuth clientId or oauthToken is required');
946
- }
947
- if (config.credentials.clientId && !config.credentials.scopes) {
948
- // Provide default scope if not present
949
- config.credentials.scopes = [
950
- 'https://www.googleapis.com/auth/spreadsheets',
951
- ];
952
- }
953
- }
954
- }
955
-
956
- return {
957
- valid: errors.length === 0,
958
- errors,
959
- };
960
- }
961
- }
1
+ // Browser-compatible Google Sheets service
2
+ // Note: This is a simplified version for browser environments
3
+ // For production use, consider using a backend API to handle Google Sheets operations
4
+
5
+ import * as XLSX from 'xlsx';
6
+ import { saveAs } from 'file-saver';
7
+
8
+ // GIS global injected by `https://accounts.google.com/gsi/client`
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ declare const google: any;
11
+
12
+ // Mock Google Sheets API for browser environment
13
+ const mockGoogleSheetsAPI = {
14
+ spreadsheets: {
15
+ values: {
16
+ update: async (params: any) => {
17
+ // Simulate API call delay
18
+ await new Promise((resolve) => setTimeout(resolve, 1000));
19
+ return {
20
+ data: {
21
+ updatedRows: params.requestBody.values.length,
22
+ updatedColumns: params.requestBody.values[0]?.length || 0,
23
+ updatedCells:
24
+ params.requestBody.values.length *
25
+ (params.requestBody.values[0]?.length || 0),
26
+ },
27
+ };
28
+ },
29
+ get: async (params: any) => {
30
+ await new Promise((resolve) => setTimeout(resolve, 500));
31
+ return {
32
+ data: {
33
+ values: [],
34
+ },
35
+ };
36
+ },
37
+ clear: async (params: any) => {
38
+ await new Promise((resolve) => setTimeout(resolve, 500));
39
+ return {
40
+ data: {
41
+ clearedRange: params.range,
42
+ },
43
+ };
44
+ },
45
+ },
46
+ },
47
+ };
48
+
49
+ export interface GoogleSheetsConfig {
50
+ spreadsheetId: string;
51
+ sheetName: string;
52
+ range: string;
53
+ credentials: {
54
+ type: 'service-account' | 'oauth' | 'api-key';
55
+ serviceAccountKey?: string;
56
+ oauthToken?: string;
57
+ apiKey?: string;
58
+ clientEmail?: string;
59
+ privateKey?: string;
60
+ // OAuth client flow (Google Identity Services)
61
+ clientId?: string;
62
+ scopes?: string[];
63
+ };
64
+ }
65
+
66
+ export interface DataMapping {
67
+ headers: Array<{
68
+ column: string;
69
+ sourceField: string;
70
+ dataType: 'string' | 'number' | 'date' | 'boolean';
71
+ }>;
72
+ appendMode: boolean;
73
+ clearSheet: boolean;
74
+ }
75
+
76
+ export interface SheetsExportOptions {
77
+ emailRecipients?: string[];
78
+ fileName?: string;
79
+ exportFormat?: 'sheets' | 'excel';
80
+ includeHeaders?: boolean;
81
+ }
82
+
83
+ export interface SheetsResponse {
84
+ spreadsheetId: string;
85
+ sheetName: string;
86
+ range: string;
87
+ rowsAdded: number;
88
+ columnsMapped: number;
89
+ data: any[];
90
+ exportTime: string;
91
+ success: boolean;
92
+ spreadsheetUrl?: string;
93
+ downloadUrl?: string;
94
+ emailSent?: boolean;
95
+ }
96
+
97
+ export class GoogleSheetsService {
98
+ private sheets: any = null;
99
+ private auth: any = null;
100
+ private isBrowserEnvironment: boolean;
101
+ private accessToken: string | null = null;
102
+ private gisLoaded: boolean = false;
103
+ private hasRequestedConsent: boolean = false;
104
+ private requestedScopes: Set<string> = new Set();
105
+
106
+ constructor() {
107
+ // Detect if we're in a browser environment
108
+ this.isBrowserEnvironment = typeof window !== 'undefined';
109
+ }
110
+
111
+ /**
112
+ * Initialize Google Sheets API with authentication
113
+ * Note: In browser environment, this uses a mock API for demonstration
114
+ */
115
+ async initialize(config: GoogleSheetsConfig): Promise<void> {
116
+ try {
117
+ if (this.isBrowserEnvironment) {
118
+ // If OAuth credentials are provided, initialize Google Identity Services
119
+ if (
120
+ config.credentials?.type === 'oauth' &&
121
+ (config.credentials.clientEmail ||
122
+ config.credentials.oauthToken ||
123
+ config.credentials.clientId)
124
+ ) {
125
+ // Prefer OAuth clientId flow (GIS)
126
+ if (config.credentials.clientId) {
127
+ await this.ensureGisLoaded();
128
+ await this.requestAccessToken(
129
+ config.credentials.clientId,
130
+ config.credentials.scopes || [
131
+ 'https://www.googleapis.com/auth/spreadsheets',
132
+ ],
133
+ );
134
+ this.sheets = 'rest';
135
+ this.auth = {
136
+ type: 'oauth',
137
+ clientId: config.credentials.clientId,
138
+ scopes: config.credentials.scopes || [
139
+ 'https://www.googleapis.com/auth/spreadsheets',
140
+ ],
141
+ };
142
+ return;
143
+ }
144
+
145
+ // Fallback: if oauthToken is provided directly (e.g., injected), use it
146
+ if (config.credentials.oauthToken) {
147
+ this.accessToken = config.credentials.oauthToken;
148
+ this.sheets = 'rest';
149
+ this.auth = {
150
+ type: 'oauth',
151
+ clientId: config.credentials.clientId,
152
+ scopes: config.credentials.scopes || [
153
+ 'https://www.googleapis.com/auth/spreadsheets',
154
+ ],
155
+ };
156
+ return;
157
+ }
158
+ }
159
+
160
+ // Browser environment without OAuth clientId – use mock API
161
+ console.log(
162
+ 'Browser environment detected - using mock Google Sheets API',
163
+ );
164
+ this.sheets = mockGoogleSheetsAPI;
165
+ this.auth = { type: config.credentials?.type || 'mock' };
166
+ return;
167
+ }
168
+
169
+ // Node.js environment - would use real Google APIs
170
+ // This would require server-side implementation
171
+ throw new Error(
172
+ 'Real Google Sheets API integration requires server-side implementation',
173
+ );
174
+ } catch (error) {
175
+ throw new Error(
176
+ `Failed to initialize Google Sheets API: ${error.message}`,
177
+ );
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Ensure Google Identity Services script is loaded
183
+ */
184
+ private async ensureGisLoaded(): Promise<void> {
185
+ if (!this.isBrowserEnvironment) return;
186
+ if (this.gisLoaded) return;
187
+
188
+ await new Promise<void>((resolve, reject) => {
189
+ const existing = document.querySelector(
190
+ 'script[src="https://accounts.google.com/gsi/client"]',
191
+ );
192
+ if (existing) {
193
+ this.gisLoaded = true;
194
+ resolve();
195
+ return;
196
+ }
197
+
198
+ const script = document.createElement('script');
199
+ script.src = 'https://accounts.google.com/gsi/client';
200
+ script.async = true;
201
+ script.defer = true;
202
+ script.onload = () => {
203
+ this.gisLoaded = true;
204
+ resolve();
205
+ };
206
+ script.onerror = () => reject(new Error('Failed to load GIS script'));
207
+ document.head.appendChild(script);
208
+ });
209
+ }
210
+
211
+ /**
212
+ * Request an OAuth access token using GIS token client
213
+ */
214
+ private async requestAccessToken(
215
+ clientId: string,
216
+ scopes: string[],
217
+ forceConsent: boolean = false,
218
+ ): Promise<string> {
219
+ if (!this.isBrowserEnvironment) {
220
+ throw new Error('OAuth is only available in browser environment');
221
+ }
222
+
223
+ await this.ensureGisLoaded();
224
+
225
+ const token = await new Promise<string>((resolve, reject) => {
226
+ try {
227
+ // @ts-ignore - google global injected by GIS
228
+ const tokenClient = google.accounts.oauth2.initTokenClient({
229
+ client_id: clientId,
230
+ scope: scopes.join(' '),
231
+ callback: (response: any) => {
232
+ // Handle both success and error shapes
233
+ if (response && response.access_token) {
234
+ this.hasRequestedConsent = true;
235
+ // Track that we've requested these scopes
236
+ scopes.forEach((s) => this.requestedScopes.add(s));
237
+ resolve(response.access_token);
238
+ return;
239
+ }
240
+ const err = response?.error || 'unknown_error';
241
+ const desc = response?.error_description || 'No description';
242
+ reject(new Error(`OAuth token error: ${err} - ${desc}`));
243
+ },
244
+ });
245
+
246
+ // First-time call must show consent; subsequent calls can be silent
247
+ tokenClient.requestAccessToken({
248
+ prompt: forceConsent
249
+ ? 'consent'
250
+ : this.hasRequestedConsent
251
+ ? ''
252
+ : 'consent',
253
+ });
254
+ } catch (e) {
255
+ reject(e);
256
+ }
257
+ });
258
+
259
+ this.accessToken = token;
260
+ // Persist clientId and union of scopes in auth cache for later scope upgrades
261
+ if (this.auth && typeof this.auth === 'object') {
262
+ (this.auth as any).clientId = clientId;
263
+ const union = Array.from(
264
+ new Set([...(this.auth.scopes || []), ...scopes]),
265
+ );
266
+ (this.auth as any).scopes = union;
267
+ }
268
+ return token;
269
+ }
270
+
271
+ /**
272
+ * Ensure the active token includes the given scopes. If not, request a new token with the union.
273
+ */
274
+ private async ensureScopes(requiredScopes: string[]): Promise<void> {
275
+ if (!this.isBrowserEnvironment) return;
276
+ if (!requiredScopes || requiredScopes.length === 0) return;
277
+ // If we don't have OAuth client flow, nothing to do
278
+ const clientId = (this as any).pendingClientId || undefined;
279
+ // We infer clientId from last initialize call by reading from DOM script params is not reliable.
280
+ // Instead, try to reuse the last known clientId from token creation by caching it in auth.
281
+ const authClientId: string | undefined =
282
+ (this.auth && this.auth.clientId) || undefined;
283
+ const effectiveClientId = authClientId || clientId;
284
+ if (!effectiveClientId) return;
285
+
286
+ const missing = requiredScopes.filter((s) => !this.requestedScopes.has(s));
287
+ if (missing.length === 0) return;
288
+
289
+ const union = Array.from(
290
+ new Set([...Array.from(this.requestedScopes), ...requiredScopes]),
291
+ );
292
+ await this.requestAccessToken(effectiveClientId, union, true);
293
+ if (this.auth && typeof this.auth === 'object') {
294
+ (this.auth as any).scopes = union;
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Build a minimal RFC 2822 MIME message (plain text) and return base64url string.
300
+ */
301
+ private buildMimeMessage(params: {
302
+ from?: string;
303
+ to: string[];
304
+ subject?: string;
305
+ body?: string;
306
+ }): string {
307
+ const headers: string[] = [];
308
+ if (params.from) headers.push(`From: ${params.from}`);
309
+ headers.push(`To: ${params.to.join(', ')}`);
310
+ if (params.subject) headers.push(`Subject: ${params.subject}`);
311
+ headers.push('MIME-Version: 1.0');
312
+ headers.push('Content-Type: text/plain; charset=UTF-8');
313
+
314
+ const lines = [...headers, '', params.body || ''];
315
+ const raw = lines.join('\r\n');
316
+ return this.encodeBase64Url(raw);
317
+ }
318
+
319
+ /**
320
+ * Encode string to base64url (RFC 4648 §5), as required by Gmail API.
321
+ */
322
+ private encodeBase64Url(input: string): string {
323
+ // btoa works with Latin1; for UTF-8 we need to encode first
324
+ const utf8 = unescape(encodeURIComponent(input));
325
+ const b64 = btoa(utf8);
326
+ return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
327
+ }
328
+
329
+ /**
330
+ * Attempt to send an email via Gmail API using the current OAuth token.
331
+ */
332
+ private async sendViaGmailApi(params: {
333
+ from?: string;
334
+ to: string[];
335
+ subject?: string;
336
+ message?: string;
337
+ spreadsheetUrl?: string;
338
+ // attachments are not implemented in this client-side example
339
+ }): Promise<boolean> {
340
+ const requiredScope = 'https://www.googleapis.com/auth/gmail.send';
341
+ await this.ensureScopes([requiredScope]);
342
+
343
+ if (!this.accessToken) {
344
+ throw new Error('Not authenticated to Google APIs');
345
+ }
346
+
347
+ const bodyParts: string[] = [];
348
+ if (params.message) bodyParts.push(params.message);
349
+ if (params.spreadsheetUrl)
350
+ bodyParts.push(`Spreadsheet: ${params.spreadsheetUrl}`);
351
+ const body = bodyParts.join('\n\n');
352
+
353
+ const raw = this.buildMimeMessage({
354
+ from: params.from,
355
+ to: params.to,
356
+ subject: params.subject || 'Automation Output',
357
+ body,
358
+ });
359
+
360
+ const res = await fetch(
361
+ 'https://gmail.googleapis.com/gmail/v1/users/me/messages/send',
362
+ {
363
+ method: 'POST',
364
+ headers: {
365
+ 'Content-Type': 'application/json',
366
+ Authorization: `Bearer ${this.accessToken}`,
367
+ },
368
+ body: JSON.stringify({ raw }),
369
+ },
370
+ );
371
+
372
+ if (!res.ok) {
373
+ const text = await res.text();
374
+ throw new Error(
375
+ `Gmail send error ${res.status}: ${res.statusText} - ${text}`,
376
+ );
377
+ }
378
+ return true;
379
+ }
380
+
381
+ /**
382
+ * Helper: call Google Sheets REST API using fetch
383
+ */
384
+ private async apiFetch(
385
+ path: string,
386
+ options: {
387
+ method?: string;
388
+ body?: any;
389
+ params?: Record<string, string>;
390
+ } = {},
391
+ ): Promise<any> {
392
+ if (!this.accessToken) {
393
+ throw new Error('Not authenticated to Google APIs');
394
+ }
395
+
396
+ const base = 'https://sheets.googleapis.com/v4';
397
+ const url = new URL(base + path);
398
+ if (options.params) {
399
+ Object.entries(options.params).forEach(([k, v]) =>
400
+ url.searchParams.set(k, v),
401
+ );
402
+ }
403
+
404
+ const res = await fetch(url.toString(), {
405
+ method: options.method || 'GET',
406
+ headers: {
407
+ 'Content-Type': 'application/json',
408
+ Authorization: `Bearer ${this.accessToken}`,
409
+ },
410
+ body: options.body ? JSON.stringify(options.body) : undefined,
411
+ });
412
+
413
+ if (!res.ok) {
414
+ const text = await res.text();
415
+ throw new Error(
416
+ `Google API error ${res.status}: ${res.statusText} - ${text}`,
417
+ );
418
+ }
419
+ return res.json();
420
+ }
421
+
422
+ /**
423
+ * Send email via Gmail API if authorized; fallback to mailto for simple cases
424
+ */
425
+ public async sendEmail(params: {
426
+ from?: string;
427
+ to: string[];
428
+ subject?: string;
429
+ message?: string;
430
+ spreadsheetUrl?: string;
431
+ attachExcelBlob?: Blob;
432
+ attachExcelFileName?: string;
433
+ disableUiFallback?: boolean;
434
+ }): Promise<boolean> {
435
+ // If we have OAuth token, try Gmail API (request scope on-demand)
436
+ const hasOauth = this.auth?.type === 'oauth' && this.accessToken;
437
+ if (hasOauth) {
438
+ try {
439
+ const sent = await this.sendViaGmailApi({
440
+ from: params.from,
441
+ to: params.to,
442
+ subject: params.subject,
443
+ message: params.message,
444
+ spreadsheetUrl: params.spreadsheetUrl,
445
+ });
446
+ if (sent) return true;
447
+ } catch (e) {
448
+ // Fall through to UI-based flow if API send fails (e.g., insufficient permissions)
449
+ console.warn(
450
+ 'Gmail API send failed, falling back to UI:',
451
+ (e as any).message || e,
452
+ );
453
+ }
454
+ }
455
+
456
+ // Prefer: open Gmail compose in a new tab (more reliable than OS mailto handler)
457
+ if (this.isBrowserEnvironment && !params.disableUiFallback) {
458
+ const to = encodeURIComponent(params.to.join(','));
459
+ const subject = encodeURIComponent(params.subject || 'Automation Output');
460
+ const bodyParts: string[] = [];
461
+ if (params.message) bodyParts.push(params.message);
462
+ if (params.spreadsheetUrl)
463
+ bodyParts.push(`Spreadsheet: ${params.spreadsheetUrl}`);
464
+ const body = encodeURIComponent(bodyParts.join('\n\n'));
465
+
466
+ // Try Gmail compose
467
+ const gmailUrl = `https://mail.google.com/mail/?view=cm&fs=1&to=${to}&su=${subject}&body=${body}`;
468
+ const win = window.open(gmailUrl, '_blank', 'noopener,noreferrer');
469
+ if (win) {
470
+ return true;
471
+ }
472
+
473
+ // Fallback: OS handler via mailto
474
+ // Note: attachments are not supported via mailto; advise using Gmail scope for API send
475
+ const a = document.createElement('a');
476
+ a.href = `mailto:${to}?subject=${subject}&body=${body}`;
477
+ a.style.display = 'none';
478
+ document.body.appendChild(a);
479
+ a.click();
480
+ document.body.removeChild(a);
481
+
482
+ return true;
483
+ }
484
+
485
+ return false;
486
+ }
487
+
488
+ /**
489
+ * Export data to Google Sheets
490
+ * Note: In browser environment, this simulates the export process
491
+ */
492
+ async exportToSheets(
493
+ data: any[],
494
+ config: GoogleSheetsConfig,
495
+ dataMapping: DataMapping,
496
+ options: SheetsExportOptions = {},
497
+ ): Promise<SheetsResponse> {
498
+ if (!this.sheets) {
499
+ throw new Error('Google Sheets API not initialized');
500
+ }
501
+
502
+ try {
503
+ // Prepare data for export
504
+ const mappedData = this.mapDataToColumns(data, dataMapping);
505
+ const includeHeaders = options.includeHeaders !== false;
506
+
507
+ // If using real OAuth flow, call REST API; otherwise, use mock behavior
508
+ const usingRest =
509
+ this.auth?.type === 'oauth' &&
510
+ this.accessToken &&
511
+ this.sheets === 'rest';
512
+
513
+ // Ensure spreadsheet exists when using REST
514
+ let spreadsheetId = config.spreadsheetId;
515
+ if (usingRest && !spreadsheetId) {
516
+ const created = await this.apiFetch('/spreadsheets', {
517
+ method: 'POST',
518
+ body: {
519
+ properties: { title: options.fileName || 'Automation Export' },
520
+ sheets: [
521
+ {
522
+ properties: { title: config.sheetName || 'Sheet1' },
523
+ },
524
+ ],
525
+ },
526
+ });
527
+ spreadsheetId = created.spreadsheetId;
528
+ config.spreadsheetId = spreadsheetId;
529
+ }
530
+
531
+ // Ensure sheet exists
532
+ if (usingRest && spreadsheetId && config.sheetName) {
533
+ const meta = await this.apiFetch(`/spreadsheets/${spreadsheetId}`, {
534
+ params: { fields: 'sheets.properties.title' },
535
+ });
536
+ const hasSheet = (meta.sheets || []).some(
537
+ (s: any) => s.properties && s.properties.title === config.sheetName,
538
+ );
539
+ if (!hasSheet) {
540
+ await this.apiFetch(`/spreadsheets/${spreadsheetId}:batchUpdate`, {
541
+ method: 'POST',
542
+ body: {
543
+ requests: [
544
+ {
545
+ addSheet: { properties: { title: config.sheetName } },
546
+ },
547
+ ],
548
+ },
549
+ });
550
+ }
551
+ }
552
+
553
+ // Clear sheet if requested
554
+ if (dataMapping.clearSheet) {
555
+ await this.clearSheet(config);
556
+ }
557
+
558
+ // Prepare range for writing (account for header row if included)
559
+ const totalRows = mappedData.length + (includeHeaders ? 1 : 0);
560
+ const range = this.prepareRange(config, dataMapping, totalRows);
561
+
562
+ // Prepare values array
563
+ const values = this.prepareValues(
564
+ mappedData,
565
+ dataMapping,
566
+ includeHeaders,
567
+ );
568
+
569
+ if (usingRest) {
570
+ await this.apiFetch(
571
+ `/spreadsheets/${config.spreadsheetId}/values/${encodeURIComponent(
572
+ range,
573
+ )}`,
574
+ {
575
+ method: 'PUT',
576
+ params: { valueInputOption: 'RAW' },
577
+ body: { values },
578
+ },
579
+ );
580
+ } else {
581
+ // Mock behavior
582
+ await this.sheets.spreadsheets.values.update({
583
+ spreadsheetId: config.spreadsheetId,
584
+ range: range,
585
+ valueInputOption: 'RAW',
586
+ requestBody: { values },
587
+ });
588
+ }
589
+
590
+ // Get spreadsheet URL
591
+ const spreadsheetUrl = `https://docs.google.com/spreadsheets/d/${config.spreadsheetId}`;
592
+
593
+ // Send email if recipients provided
594
+ let emailSent = false;
595
+ if (options.emailRecipients && options.emailRecipients.length > 0) {
596
+ emailSent = await this.sendEmailNotification(
597
+ options.emailRecipients,
598
+ spreadsheetUrl,
599
+ options.fileName || 'Google Sheets Export',
600
+ );
601
+ }
602
+
603
+ return {
604
+ spreadsheetId: config.spreadsheetId,
605
+ sheetName: config.sheetName,
606
+ range: range,
607
+ rowsAdded: mappedData.length,
608
+ columnsMapped: dataMapping.headers.length,
609
+ data: mappedData,
610
+ exportTime: new Date().toISOString(),
611
+ success: true,
612
+ spreadsheetUrl,
613
+ emailSent,
614
+ };
615
+ } catch (error) {
616
+ throw new Error(`Failed to export to Google Sheets: ${error.message}`);
617
+ }
618
+ }
619
+
620
+ /**
621
+ * Export data to Excel file and download
622
+ */
623
+ async exportToExcel(
624
+ data: any[],
625
+ dataMapping: DataMapping,
626
+ options: SheetsExportOptions = {},
627
+ ): Promise<SheetsResponse> {
628
+ try {
629
+ // Prepare data for export
630
+ const mappedData = this.mapDataToColumns(data, dataMapping);
631
+
632
+ // Create workbook
633
+ const wb = XLSX.utils.book_new();
634
+
635
+ // Prepare worksheet data
636
+ const wsData = this.prepareExcelData(
637
+ mappedData,
638
+ dataMapping,
639
+ options.includeHeaders !== false,
640
+ );
641
+
642
+ // Create worksheet
643
+ const ws = XLSX.utils.aoa_to_sheet(wsData);
644
+
645
+ // Add worksheet to workbook
646
+ XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
647
+
648
+ // Generate file name
649
+ const fileName =
650
+ options.fileName ||
651
+ `export_${new Date().toISOString().split('T')[0]}.xlsx`;
652
+
653
+ // Save file
654
+ const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
655
+ const blob = new Blob([excelBuffer], {
656
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
657
+ });
658
+ saveAs(blob, fileName);
659
+
660
+ // Send email if recipients provided
661
+ let emailSent = false;
662
+ if (options.emailRecipients && options.emailRecipients.length > 0) {
663
+ emailSent = await this.sendEmailWithAttachment(
664
+ options.emailRecipients,
665
+ blob,
666
+ fileName,
667
+ );
668
+ }
669
+
670
+ return {
671
+ spreadsheetId: '',
672
+ sheetName: 'Sheet1',
673
+ range: '',
674
+ rowsAdded: mappedData.length,
675
+ columnsMapped: dataMapping.headers.length,
676
+ data: mappedData,
677
+ exportTime: new Date().toISOString(),
678
+ success: true,
679
+ downloadUrl: URL.createObjectURL(blob),
680
+ emailSent,
681
+ };
682
+ } catch (error) {
683
+ throw new Error(`Failed to export to Excel: ${error.message}`);
684
+ }
685
+ }
686
+
687
+ /**
688
+ * Map data according to column configuration
689
+ */
690
+ private mapDataToColumns(data: any[], dataMapping: DataMapping): any[] {
691
+ return data.map((item: any) => {
692
+ const row: any = {};
693
+ dataMapping.headers.forEach((header) => {
694
+ const value = this.getNestedValue(item, header.sourceField);
695
+ row[header.column] = this.formatValueForSheets(value, header.dataType);
696
+ });
697
+ return row;
698
+ });
699
+ }
700
+
701
+ /**
702
+ * Get nested value from object using dot notation
703
+ */
704
+ private getNestedValue(obj: any, path: string): any {
705
+ return path.split('.').reduce((current, key) => current?.[key], obj);
706
+ }
707
+
708
+ /**
709
+ * Format value according to data type
710
+ */
711
+ private formatValueForSheets(value: any, dataType: string): any {
712
+ if (value === null || value === undefined) {
713
+ return '';
714
+ }
715
+
716
+ switch (dataType) {
717
+ case 'number':
718
+ return typeof value === 'number' ? value : parseFloat(value) || 0;
719
+ case 'date':
720
+ return value instanceof Date
721
+ ? value.toISOString().split('T')[0]
722
+ : value;
723
+ case 'boolean':
724
+ return Boolean(value);
725
+ case 'string':
726
+ default:
727
+ return String(value);
728
+ }
729
+ }
730
+
731
+ /**
732
+ * Prepare range for writing data
733
+ */
734
+ private prepareRange(
735
+ config: GoogleSheetsConfig,
736
+ dataMapping: DataMapping,
737
+ rowCount: number,
738
+ ): string {
739
+ const startColumn = dataMapping.headers[0]?.column || 'A';
740
+ const endColumn =
741
+ dataMapping.headers[dataMapping.headers.length - 1]?.column || 'Z';
742
+ const startRow = dataMapping.clearSheet ? 1 : 1; // Simplified for browser
743
+ const endRow = startRow + rowCount - 1;
744
+
745
+ return `${config.sheetName}!${startColumn}${startRow}:${endColumn}${endRow}`;
746
+ }
747
+
748
+ /**
749
+ * Clear sheet content
750
+ */
751
+ private async clearSheet(config: GoogleSheetsConfig): Promise<void> {
752
+ if (!this.sheets) return;
753
+
754
+ try {
755
+ const usingRest =
756
+ this.auth?.type === 'oauth' &&
757
+ this.accessToken &&
758
+ this.sheets === 'rest';
759
+ const range = `${config.sheetName}!A:Z`;
760
+ if (usingRest) {
761
+ await this.apiFetch(
762
+ `/spreadsheets/${config.spreadsheetId}/values/${encodeURIComponent(
763
+ range,
764
+ )}:clear`,
765
+ { method: 'POST' },
766
+ );
767
+ } else {
768
+ await this.sheets.spreadsheets.values.clear({
769
+ spreadsheetId: config.spreadsheetId,
770
+ range,
771
+ });
772
+ }
773
+ } catch (error) {
774
+ console.warn('Failed to clear sheet:', (error as any).message || error);
775
+ }
776
+ }
777
+
778
+ /**
779
+ * Prepare values array for Google Sheets API
780
+ */
781
+ private prepareValues(
782
+ mappedData: any[],
783
+ dataMapping: DataMapping,
784
+ includeHeaders: boolean,
785
+ ): any[][] {
786
+ const values: any[][] = [];
787
+
788
+ // Add headers if requested
789
+ if (includeHeaders && dataMapping.headers.length > 0) {
790
+ const headers = dataMapping.headers.map((h) => h.column);
791
+ values.push(headers);
792
+ }
793
+
794
+ // Add data rows
795
+ mappedData.forEach((row) => {
796
+ const rowValues = dataMapping.headers.map(
797
+ (header) => row[header.column] || '',
798
+ );
799
+ values.push(rowValues);
800
+ });
801
+
802
+ return values;
803
+ }
804
+
805
+ /**
806
+ * Prepare data for Excel export
807
+ */
808
+ private prepareExcelData(
809
+ mappedData: any[],
810
+ dataMapping: DataMapping,
811
+ includeHeaders: boolean,
812
+ ): any[][] {
813
+ const data: any[][] = [];
814
+
815
+ // Add headers if requested
816
+ if (includeHeaders && dataMapping.headers.length > 0) {
817
+ const headers = dataMapping.headers.map((h) => h.column);
818
+ data.push(headers);
819
+ }
820
+
821
+ // Add data rows
822
+ mappedData.forEach((row) => {
823
+ const rowValues = dataMapping.headers.map(
824
+ (header) => row[header.column] || '',
825
+ );
826
+ data.push(rowValues);
827
+ });
828
+
829
+ return data;
830
+ }
831
+
832
+ /**
833
+ * Send email notification with spreadsheet link
834
+ */
835
+ private async sendEmailNotification(
836
+ recipients: string[],
837
+ spreadsheetUrl: string,
838
+ fileName: string,
839
+ ): Promise<boolean> {
840
+ try {
841
+ // In browser environment, we'll simulate email sending
842
+ console.log(
843
+ `📧 Email notification would be sent to: ${recipients.join(', ')}`,
844
+ );
845
+ console.log(`📊 Spreadsheet URL: ${spreadsheetUrl}`);
846
+ console.log(`📁 File: ${fileName}`);
847
+
848
+ // Show a browser notification or alert
849
+ if (this.isBrowserEnvironment && 'Notification' in window) {
850
+ if (Notification.permission === 'granted') {
851
+ new Notification('Google Sheets Export', {
852
+ body: `Data exported successfully! Sent to ${recipients.length} recipient(s).`,
853
+ icon: '/favicon.ico',
854
+ });
855
+ }
856
+ }
857
+
858
+ return true;
859
+ } catch (error) {
860
+ console.error('Failed to send email notification:', error);
861
+ return false;
862
+ }
863
+ }
864
+
865
+ /**
866
+ * Send email with Excel attachment
867
+ */
868
+ private async sendEmailWithAttachment(
869
+ recipients: string[],
870
+ fileBlob: Blob,
871
+ fileName: string,
872
+ ): Promise<boolean> {
873
+ try {
874
+ // In browser environment, we'll simulate email sending
875
+ console.log(
876
+ `📧 Email with attachment would be sent to: ${recipients.join(', ')}`,
877
+ );
878
+ console.log(`📎 Attachment: ${fileName}`);
879
+ console.log(`📊 File size: ${(fileBlob.size / 1024).toFixed(2)} KB`);
880
+
881
+ // Show a browser notification
882
+ if (this.isBrowserEnvironment && 'Notification' in window) {
883
+ if (Notification.permission === 'granted') {
884
+ new Notification('Excel Export', {
885
+ body: `Excel file "${fileName}" exported successfully! Sent to ${recipients.length} recipient(s).`,
886
+ icon: '/favicon.ico',
887
+ });
888
+ }
889
+ }
890
+
891
+ return true;
892
+ } catch (error) {
893
+ console.error('Failed to send email with attachment:', error);
894
+ return false;
895
+ }
896
+ }
897
+
898
+ /**
899
+ * Validate configuration
900
+ */
901
+ validateConfig(config: GoogleSheetsConfig): {
902
+ valid: boolean;
903
+ errors: string[];
904
+ } {
905
+ const errors: string[] = [];
906
+
907
+ if (!config.spreadsheetId) {
908
+ // Allow creating a new spreadsheet when using OAuth clientId
909
+ if (
910
+ !(config.credentials?.type === 'oauth' && config.credentials.clientId)
911
+ ) {
912
+ errors.push(
913
+ 'Spreadsheet ID is required (or provide OAuth clientId to create a new one)',
914
+ );
915
+ }
916
+ }
917
+
918
+ if (!config.sheetName) {
919
+ errors.push('Sheet name is required');
920
+ }
921
+
922
+ if (!config.credentials) {
923
+ errors.push('Credentials are required');
924
+ } else {
925
+ if (config.credentials.type === 'service-account') {
926
+ if (
927
+ !config.credentials.serviceAccountKey &&
928
+ !config.credentials.clientEmail
929
+ ) {
930
+ errors.push('Service account key or client email is required');
931
+ }
932
+ if (
933
+ !config.credentials.serviceAccountKey &&
934
+ !config.credentials.privateKey
935
+ ) {
936
+ errors.push('Service account key or private key is required');
937
+ }
938
+ } else if (config.credentials.type === 'api-key') {
939
+ if (!config.credentials.apiKey) {
940
+ errors.push('API key is required');
941
+ }
942
+ } else if (config.credentials.type === 'oauth') {
943
+ // Accept either a provided token or clientId for GIS
944
+ if (!config.credentials.oauthToken && !config.credentials.clientId) {
945
+ errors.push('OAuth clientId or oauthToken is required');
946
+ }
947
+ if (config.credentials.clientId && !config.credentials.scopes) {
948
+ // Provide default scope if not present
949
+ config.credentials.scopes = [
950
+ 'https://www.googleapis.com/auth/spreadsheets',
951
+ ];
952
+ }
953
+ }
954
+ }
955
+
956
+ return {
957
+ valid: errors.length === 0,
958
+ errors,
959
+ };
960
+ }
961
+ }