ecoportal-api-graphql 1.3.5 → 1.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +934 -477
  3. data/lib/ecoportal/api/common/graphql/CLAUDE.md +36 -0
  4. data/lib/ecoportal/api/common/graphql/client.rb +1 -1
  5. data/lib/ecoportal/api/common/graphql/http_client.rb +195 -145
  6. data/lib/ecoportal/api/common/graphql/model/CLAUDE.md +28 -0
  7. data/lib/ecoportal/api/common/graphql/model/as_input.rb +8 -5
  8. data/lib/ecoportal/api/common/graphql/model/diffable/classic_diff_service.rb +3 -1
  9. data/lib/ecoportal/api/common/graphql/model/diffable/diff_service.rb +31 -23
  10. data/lib/ecoportal/api/common/graphql/model/diffable/hash_diff_nesting.rb +54 -1
  11. data/lib/ecoportal/api/common/graphql/model/diffable.rb +54 -54
  12. data/lib/ecoportal/api/graphql/CLAUDE.md +37 -0
  13. data/lib/ecoportal/api/graphql/base/CLAUDE.md +50 -0
  14. data/lib/ecoportal/api/graphql/base/action.rb +43 -43
  15. data/lib/ecoportal/api/graphql/base/ai_summary_version.rb +17 -0
  16. data/lib/ecoportal/api/graphql/base/contractor_entity/member_changes.rb +67 -67
  17. data/lib/ecoportal/api/graphql/base/delta_result.rb +16 -0
  18. data/lib/ecoportal/api/graphql/base/file_container.rb +14 -14
  19. data/lib/ecoportal/api/graphql/base/force/binding.rb +19 -0
  20. data/lib/ecoportal/api/graphql/base/force/binding_collection.rb +62 -0
  21. data/lib/ecoportal/api/graphql/base/force/collection.rb +47 -0
  22. data/lib/ecoportal/api/graphql/base/force.rb +65 -0
  23. data/lib/ecoportal/api/graphql/base/kickstand/job.rb +17 -0
  24. data/lib/ecoportal/api/graphql/base/kickstand/workflow.rb +18 -0
  25. data/lib/ecoportal/api/graphql/base/kickstand.rb +13 -0
  26. data/lib/ecoportal/api/graphql/base/location_classification_type.rb +15 -15
  27. data/lib/ecoportal/api/graphql/base/location_structure.rb +27 -27
  28. data/lib/ecoportal/api/graphql/base/organization.rb +15 -15
  29. data/lib/ecoportal/api/graphql/base/page/basic.rb +38 -0
  30. data/lib/ecoportal/api/graphql/base/page/data_field/actions_list.rb +9 -0
  31. data/lib/ecoportal/api/graphql/base/page/data_field/ai_summary.rb +18 -0
  32. data/lib/ecoportal/api/graphql/base/page/data_field/checklist.rb +29 -0
  33. data/lib/ecoportal/api/graphql/base/page/data_field/collection.rb +119 -0
  34. data/lib/ecoportal/api/graphql/base/page/data_field/contractor_entities.rb +28 -0
  35. data/lib/ecoportal/api/graphql/base/page/data_field/cross_reference.rb +54 -0
  36. data/lib/ecoportal/api/graphql/base/page/data_field/date_field.rb +23 -0
  37. data/lib/ecoportal/api/graphql/base/page/data_field/file_field.rb +25 -0
  38. data/lib/ecoportal/api/graphql/base/page/data_field/gauge.rb +19 -0
  39. data/lib/ecoportal/api/graphql/base/page/data_field/geo.rb +24 -0
  40. data/lib/ecoportal/api/graphql/base/page/data_field/image_gallery.rb +24 -0
  41. data/lib/ecoportal/api/graphql/base/page/data_field/law.rb +8 -0
  42. data/lib/ecoportal/api/graphql/base/page/data_field/mailbox.rb +9 -0
  43. data/lib/ecoportal/api/graphql/base/page/data_field/number.rb +20 -0
  44. data/lib/ecoportal/api/graphql/base/page/data_field/people.rb +35 -0
  45. data/lib/ecoportal/api/graphql/base/page/data_field/plain_text.rb +17 -0
  46. data/lib/ecoportal/api/graphql/base/page/data_field/rich_text.rb +26 -0
  47. data/lib/ecoportal/api/graphql/base/page/data_field/select.rb +41 -0
  48. data/lib/ecoportal/api/graphql/base/page/data_field/signature.rb +9 -0
  49. data/lib/ecoportal/api/graphql/base/page/data_field/smart_fill.rb +17 -0
  50. data/lib/ecoportal/api/graphql/base/page/data_field/table.rb +9 -0
  51. data/lib/ecoportal/api/graphql/base/page/data_field/tag_field.rb +21 -0
  52. data/lib/ecoportal/api/graphql/base/page/data_field.rb +137 -12
  53. data/lib/ecoportal/api/graphql/base/page/phased/stage.rb +68 -14
  54. data/lib/ecoportal/api/graphql/base/page/phased.rb +1 -0
  55. data/lib/ecoportal/api/graphql/base/page/section.rb +36 -0
  56. data/lib/ecoportal/api/graphql/base/page/section_collection.rb +85 -0
  57. data/lib/ecoportal/api/graphql/base/page/task.rb +24 -0
  58. data/lib/ecoportal/api/graphql/base/page.rb +17 -14
  59. data/lib/ecoportal/api/graphql/base/pages_workflow/action_type_selection.rb +17 -0
  60. data/lib/ecoportal/api/graphql/base/pages_workflow/callback_type.rb +28 -0
  61. data/lib/ecoportal/api/graphql/base/pages_workflow/command_change.rb +17 -0
  62. data/lib/ecoportal/api/graphql/base/pages_workflow/command_change_message.rb +15 -0
  63. data/lib/ecoportal/api/graphql/base/pages_workflow/command_es_change.rb +17 -0
  64. data/lib/ecoportal/api/graphql/base/pages_workflow/command_interface.rb +36 -0
  65. data/lib/ecoportal/api/graphql/base/pages_workflow/email_config.rb +18 -0
  66. data/lib/ecoportal/api/graphql/base/pages_workflow/escalation_level.rb +19 -0
  67. data/lib/ecoportal/api/graphql/base/pages_workflow/in_system_config.rb +16 -0
  68. data/lib/ecoportal/api/graphql/base/pages_workflow/mailbox_field_selection.rb +17 -0
  69. data/lib/ecoportal/api/graphql/base/pages_workflow/operation_interface.rb +39 -0
  70. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/assign_to.rb +27 -0
  71. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/create_page.rb +21 -0
  72. data/lib/ecoportal/api/graphql/base/pages_workflow/operations/send_notification.rb +30 -0
  73. data/lib/ecoportal/api/graphql/base/pages_workflow/people_field_selection.rb +17 -0
  74. data/lib/ecoportal/api/graphql/base/pages_workflow/recipient_config.rb +34 -0
  75. data/lib/ecoportal/api/graphql/base/pages_workflow/register_field.rb +17 -0
  76. data/lib/ecoportal/api/graphql/base/pages_workflow/task_config_selection.rb +17 -0
  77. data/lib/ecoportal/api/graphql/base/pages_workflow/time_delay_config.rb +16 -0
  78. data/lib/ecoportal/api/graphql/base/pages_workflow/trigger_interface.rb +26 -0
  79. data/lib/ecoportal/api/graphql/base/pages_workflow/triggers/conditional_logic.rb +17 -0
  80. data/lib/ecoportal/api/graphql/base/pages_workflow/user_selection.rb +16 -0
  81. data/lib/ecoportal/api/graphql/base/pages_workflow.rb +35 -0
  82. data/lib/ecoportal/api/graphql/base/preset_view.rb +17 -0
  83. data/lib/ecoportal/api/graphql/base/preview_page.rb +23 -0
  84. data/lib/ecoportal/api/graphql/base/register.rb +18 -0
  85. data/lib/ecoportal/api/graphql/base/template.rb +35 -0
  86. data/lib/ecoportal/api/graphql/base.rb +37 -24
  87. data/lib/ecoportal/api/graphql/builder/CLAUDE.md +65 -0
  88. data/lib/ecoportal/api/graphql/builder/contractor_entity.rb +41 -41
  89. data/lib/ecoportal/api/graphql/builder/kickstand.rb +73 -0
  90. data/lib/ecoportal/api/graphql/builder/page.rb +210 -41
  91. data/lib/ecoportal/api/graphql/builder/register/preset_view.rb +84 -0
  92. data/lib/ecoportal/api/graphql/builder/register.rb +27 -19
  93. data/lib/ecoportal/api/graphql/builder/template.rb +80 -0
  94. data/lib/ecoportal/api/graphql/builder/template_builder.rb +174 -0
  95. data/lib/ecoportal/api/graphql/builder.rb +17 -14
  96. data/lib/ecoportal/api/graphql/compat/filter_translator.rb +142 -0
  97. data/lib/ecoportal/api/graphql/compat/page_reference.rb +23 -0
  98. data/lib/ecoportal/api/graphql/compat/pages.rb +212 -0
  99. data/lib/ecoportal/api/graphql/compat/registers.rb +84 -0
  100. data/lib/ecoportal/api/graphql/compat/response.rb +35 -0
  101. data/lib/ecoportal/api/graphql/compat/search_results.rb +33 -0
  102. data/lib/ecoportal/api/graphql/compat/stage_collection.rb +70 -0
  103. data/lib/ecoportal/api/graphql/compat/stage_view.rb +76 -0
  104. data/lib/ecoportal/api/graphql/compat.rb +17 -0
  105. data/lib/ecoportal/api/graphql/concerns/data_field_access.rb +71 -0
  106. data/lib/ecoportal/api/graphql/concerns/deprecation.rb +20 -0
  107. data/lib/ecoportal/api/graphql/concerns/fragment_definitions.rb +21 -28
  108. data/lib/ecoportal/api/graphql/concerns/page_compat.rb +51 -0
  109. data/lib/ecoportal/api/graphql/concerns/snake_camel_access.rb +60 -0
  110. data/lib/ecoportal/api/graphql/concerns.rb +14 -10
  111. data/lib/ecoportal/api/graphql/connection/action.rb +11 -11
  112. data/lib/ecoportal/api/graphql/connection/action_category.rb +11 -11
  113. data/lib/ecoportal/api/graphql/connection/contractor_entity.rb +11 -11
  114. data/lib/ecoportal/api/graphql/connection/page.rb +11 -0
  115. data/lib/ecoportal/api/graphql/connection/pages_workflow_command.rb +13 -0
  116. data/lib/ecoportal/api/graphql/connection/person_member.rb +11 -11
  117. data/lib/ecoportal/api/graphql/connection/preset_view.rb +11 -0
  118. data/lib/ecoportal/api/graphql/connection/preview_page.rb +11 -0
  119. data/lib/ecoportal/api/graphql/connection.rb +17 -13
  120. data/lib/ecoportal/api/graphql/diff/change.rb +59 -0
  121. data/lib/ecoportal/api/graphql/diff/command_synthesizer.rb +329 -0
  122. data/lib/ecoportal/api/graphql/diff/cross_object_diff.rb +165 -0
  123. data/lib/ecoportal/api/graphql/diff/deploy.rb +121 -0
  124. data/lib/ecoportal/api/graphql/diff/id_resolver.rb +64 -0
  125. data/lib/ecoportal/api/graphql/diff/pairing/candidate.rb +32 -0
  126. data/lib/ecoportal/api/graphql/diff/pairing/engine.rb +173 -0
  127. data/lib/ecoportal/api/graphql/diff/pairing/ledger.rb +119 -0
  128. data/lib/ecoportal/api/graphql/diff/pairing/signals.rb +104 -0
  129. data/lib/ecoportal/api/graphql/diff/strategy.rb +113 -0
  130. data/lib/ecoportal/api/graphql/diff/version_diff.rb +332 -0
  131. data/lib/ecoportal/api/graphql/diff.rb +34 -0
  132. data/lib/ecoportal/api/graphql/file_upload/client.rb +192 -0
  133. data/lib/ecoportal/api/graphql/file_upload.rb +10 -0
  134. data/lib/ecoportal/api/graphql/fragment/action.rb +1 -1
  135. data/lib/ecoportal/api/graphql/fragment/action_category.rb +1 -1
  136. data/lib/ecoportal/api/graphql/fragment/contractor_entity.rb +1 -1
  137. data/lib/ecoportal/api/graphql/fragment/field_configuration.rb +38 -0
  138. data/lib/ecoportal/api/graphql/fragment/force.rb +34 -0
  139. data/lib/ecoportal/api/graphql/fragment/location_draft.rb +53 -53
  140. data/lib/ecoportal/api/graphql/fragment/location_node.rb +26 -26
  141. data/lib/ecoportal/api/graphql/fragment/locations_error.rb +1 -1
  142. data/lib/ecoportal/api/graphql/fragment/page.rb +85 -0
  143. data/lib/ecoportal/api/graphql/fragment/page_task.rb +39 -0
  144. data/lib/ecoportal/api/graphql/fragment/pages/common_page_union.rb +396 -0
  145. data/lib/ecoportal/api/graphql/fragment/pages.rb +15 -0
  146. data/lib/ecoportal/api/graphql/fragment/pages_workflow.rb +172 -0
  147. data/lib/ecoportal/api/graphql/fragment/pagination.rb +1 -1
  148. data/lib/ecoportal/api/graphql/fragment/template.rb +51 -0
  149. data/lib/ecoportal/api/graphql/fragment.rb +40 -27
  150. data/lib/ecoportal/api/graphql/input/action/update.rb +14 -14
  151. data/lib/ecoportal/api/graphql/input/contractor_entity/update.rb +41 -16
  152. data/lib/ecoportal/api/graphql/input/contractor_entity.rb +14 -14
  153. data/lib/ecoportal/api/graphql/input/delta_input.rb +16 -0
  154. data/lib/ecoportal/api/graphql/input/location_structure/apply_commands.rb +47 -47
  155. data/lib/ecoportal/api/graphql/input/location_structure/draft/add_commands.rb +49 -49
  156. data/lib/ecoportal/api/graphql/input/location_structure/update_command.rb +27 -27
  157. data/lib/ecoportal/api/graphql/input/page/archive.rb +14 -0
  158. data/lib/ecoportal/api/graphql/input/page/build_from_template.rb +13 -0
  159. data/lib/ecoportal/api/graphql/input/page/create_draft.rb +13 -0
  160. data/lib/ecoportal/api/graphql/input/page/create_from_template.rb +18 -0
  161. data/lib/ecoportal/api/graphql/input/page/delete_draft.rb +13 -0
  162. data/lib/ecoportal/api/graphql/input/page/publish_draft.rb +13 -0
  163. data/lib/ecoportal/api/graphql/input/page/review_task.rb +14 -0
  164. data/lib/ecoportal/api/graphql/input/page/unarchive.rb +14 -0
  165. data/lib/ecoportal/api/graphql/input/page/update.rb +140 -0
  166. data/lib/ecoportal/api/graphql/input/page.rb +26 -0
  167. data/lib/ecoportal/api/graphql/input/preset_view/create.rb +18 -0
  168. data/lib/ecoportal/api/graphql/input/preset_view/permission.rb +16 -0
  169. data/lib/ecoportal/api/graphql/input/preset_view/update.rb +16 -0
  170. data/lib/ecoportal/api/graphql/input/preset_view.rb +14 -0
  171. data/lib/ecoportal/api/graphql/input/register/create.rb +18 -0
  172. data/lib/ecoportal/api/graphql/input/register/update.rb +15 -0
  173. data/lib/ecoportal/api/graphql/input/register.rb +13 -0
  174. data/lib/ecoportal/api/graphql/input/search_conf/ai_generator.rb +234 -0
  175. data/lib/ecoportal/api/graphql/input/search_conf.rb +436 -0
  176. data/lib/ecoportal/api/graphql/input/variable_binding.rb +20 -0
  177. data/lib/ecoportal/api/graphql/input/workflow_command/add_action_tag.rb +18 -0
  178. data/lib/ecoportal/api/graphql/input/workflow_command/add_binding.rb +18 -0
  179. data/lib/ecoportal/api/graphql/input/workflow_command/add_comment_tagging_user_group.rb +18 -0
  180. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_direct_strategy_user.rb +18 -0
  181. data/lib/ecoportal/api/graphql/input/workflow_command/add_default_strategy.rb +18 -0
  182. data/lib/ecoportal/api/graphql/input/workflow_command/add_direct_strategy_user.rb +18 -0
  183. data/lib/ecoportal/api/graphql/input/workflow_command/add_field.rb +27 -0
  184. data/lib/ecoportal/api/graphql/input/workflow_command/add_force.rb +18 -0
  185. data/lib/ecoportal/api/graphql/input/workflow_command/add_gauge_field_stop.rb +19 -0
  186. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_field_config.rb +23 -0
  187. data/lib/ecoportal/api/graphql/input/workflow_command/add_linked_helper.rb +18 -0
  188. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation.rb +18 -0
  189. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_direct_strategy_user.rb +18 -0
  190. data/lib/ecoportal/api/graphql/input/workflow_command/add_operation_strategy.rb +18 -0
  191. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_action_type.rb +18 -0
  192. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_filter.rb +18 -0
  193. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_people_field.rb +18 -0
  194. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_task_config.rb +18 -0
  195. data/lib/ecoportal/api/graphql/input/workflow_command/add_recipient_user.rb +18 -0
  196. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback.rb +23 -0
  197. data/lib/ecoportal/api/graphql/input/workflow_command/add_scheduled_callback_action.rb +18 -0
  198. data/lib/ecoportal/api/graphql/input/workflow_command/add_section.rb +18 -0
  199. data/lib/ecoportal/api/graphql/input/workflow_command/add_select_field_option.rb +19 -0
  200. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage.rb +18 -0
  201. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_section.rb +18 -0
  202. data/lib/ecoportal/api/graphql/input/workflow_command/add_stage_tag.rb +18 -0
  203. data/lib/ecoportal/api/graphql/input/workflow_command/add_strategy.rb +18 -0
  204. data/lib/ecoportal/api/graphql/input/workflow_command/add_task.rb +18 -0
  205. data/lib/ecoportal/api/graphql/input/workflow_command/add_task_assignment_user_group.rb +18 -0
  206. data/lib/ecoportal/api/graphql/input/workflow_command/add_workflow_callback.rb +18 -0
  207. data/lib/ecoportal/api/graphql/input/workflow_command/collapse_section.rb +18 -0
  208. data/lib/ecoportal/api/graphql/input/workflow_command/edit_binding.rb +18 -0
  209. data/lib/ecoportal/api/graphql/input/workflow_command/edit_creator_permissions.rb +18 -0
  210. data/lib/ecoportal/api/graphql/input/workflow_command/edit_default_strategy.rb +18 -0
  211. data/lib/ecoportal/api/graphql/input/workflow_command/edit_field_configuration.rb +21 -0
  212. data/lib/ecoportal/api/graphql/input/workflow_command/edit_force.rb +18 -0
  213. data/lib/ecoportal/api/graphql/input/workflow_command/edit_gauge_field_stop.rb +19 -0
  214. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_field_config.rb +19 -0
  215. data/lib/ecoportal/api/graphql/input/workflow_command/edit_linked_helper.rb +18 -0
  216. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation.rb +18 -0
  217. data/lib/ecoportal/api/graphql/input/workflow_command/edit_operation_strategy.rb +18 -0
  218. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page.rb +28 -0
  219. data/lib/ecoportal/api/graphql/input/workflow_command/edit_page_creator_permissions.rb +18 -0
  220. data/lib/ecoportal/api/graphql/input/workflow_command/edit_reminder.rb +18 -0
  221. data/lib/ecoportal/api/graphql/input/workflow_command/edit_required_sign_offs.rb +18 -0
  222. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_comment_tagging.rb +18 -0
  223. data/lib/ecoportal/api/graphql/input/workflow_command/edit_restrict_task_assignment.rb +18 -0
  224. data/lib/ecoportal/api/graphql/input/workflow_command/edit_scheduled_callback.rb +22 -0
  225. data/lib/ecoportal/api/graphql/input/workflow_command/edit_section_header.rb +18 -0
  226. data/lib/ecoportal/api/graphql/input/workflow_command/edit_select_field_option.rb +19 -0
  227. data/lib/ecoportal/api/graphql/input/workflow_command/edit_stage.rb +18 -0
  228. data/lib/ecoportal/api/graphql/input/workflow_command/edit_strategy.rb +18 -0
  229. data/lib/ecoportal/api/graphql/input/workflow_command/edit_task_due.rb +18 -0
  230. data/lib/ecoportal/api/graphql/input/workflow_command/edit_trigger.rb +18 -0
  231. data/lib/ecoportal/api/graphql/input/workflow_command/expand_section.rb +18 -0
  232. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/contractor_entities.rb +24 -0
  233. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/cross_reference.rb +23 -0
  234. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/date.rb +20 -0
  235. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/gauge.rb +20 -0
  236. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/image_gallery.rb +20 -0
  237. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/location_field.rb +24 -0
  238. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/people.rb +24 -0
  239. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/plain_text.rb +20 -0
  240. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/rich_text.rb +20 -0
  241. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/select.rb +20 -0
  242. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/signature.rb +20 -0
  243. data/lib/ecoportal/api/graphql/input/workflow_command/field_config/table.rb +25 -0
  244. data/lib/ecoportal/api/graphql/input/workflow_command/move_field.rb +18 -0
  245. data/lib/ecoportal/api/graphql/input/workflow_command/move_stage.rb +18 -0
  246. data/lib/ecoportal/api/graphql/input/workflow_command/remove_action_tag.rb +18 -0
  247. data/lib/ecoportal/api/graphql/input/workflow_command/remove_binding.rb +18 -0
  248. data/lib/ecoportal/api/graphql/input/workflow_command/remove_callback.rb +18 -0
  249. data/lib/ecoportal/api/graphql/input/workflow_command/remove_comment_tagging_user_group.rb +18 -0
  250. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_direct_strategy_user.rb +18 -0
  251. data/lib/ecoportal/api/graphql/input/workflow_command/remove_default_strategy.rb +18 -0
  252. data/lib/ecoportal/api/graphql/input/workflow_command/remove_direct_strategy_user.rb +18 -0
  253. data/lib/ecoportal/api/graphql/input/workflow_command/remove_field.rb +18 -0
  254. data/lib/ecoportal/api/graphql/input/workflow_command/remove_force.rb +18 -0
  255. data/lib/ecoportal/api/graphql/input/workflow_command/remove_gauge_field_stop.rb +17 -0
  256. data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_field_config.rb +17 -0
  257. data/lib/ecoportal/api/graphql/input/workflow_command/remove_linked_helper.rb +18 -0
  258. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation.rb +18 -0
  259. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_direct_strategy_user.rb +18 -0
  260. data/lib/ecoportal/api/graphql/input/workflow_command/remove_operation_strategy.rb +18 -0
  261. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_action_type.rb +18 -0
  262. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_filter.rb +18 -0
  263. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_people_field.rb +18 -0
  264. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_task_config.rb +18 -0
  265. data/lib/ecoportal/api/graphql/input/workflow_command/remove_recipient_user.rb +18 -0
  266. data/lib/ecoportal/api/graphql/input/workflow_command/remove_scheduled_callback.rb +18 -0
  267. data/lib/ecoportal/api/graphql/input/workflow_command/remove_section.rb +18 -0
  268. data/lib/ecoportal/api/graphql/input/workflow_command/remove_select_field_option.rb +17 -0
  269. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage.rb +18 -0
  270. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_section.rb +18 -0
  271. data/lib/ecoportal/api/graphql/input/workflow_command/remove_stage_tag.rb +18 -0
  272. data/lib/ecoportal/api/graphql/input/workflow_command/remove_strategy.rb +18 -0
  273. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task.rb +18 -0
  274. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_assignment_user_group.rb +18 -0
  275. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_due.rb +18 -0
  276. data/lib/ecoportal/api/graphql/input/workflow_command/remove_task_priority_level.rb +18 -0
  277. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_forces.rb +18 -0
  278. data/lib/ecoportal/api/graphql/input/workflow_command/reorder_section.rb +18 -0
  279. data/lib/ecoportal/api/graphql/input/workflow_command.rb +251 -0
  280. data/lib/ecoportal/api/graphql/input.rb +24 -16
  281. data/lib/ecoportal/api/graphql/interface/base_page.rb +100 -58
  282. data/lib/ecoportal/api/graphql/interface/location_structure/command.rb +30 -30
  283. data/lib/ecoportal/api/graphql/interface/location_structure/nodes.rb +27 -28
  284. data/lib/ecoportal/api/graphql/logic/base_model.rb +2 -0
  285. data/lib/ecoportal/api/graphql/logic/base_query.rb +45 -2
  286. data/lib/ecoportal/api/graphql/logic/connection.rb +34 -34
  287. data/lib/ecoportal/api/graphql/logic/input.rb +26 -11
  288. data/lib/ecoportal/api/graphql/model/ai_summary_version.rb +10 -0
  289. data/lib/ecoportal/api/graphql/model/organization.rb +65 -55
  290. data/lib/ecoportal/api/graphql/model/page/basic.rb +14 -0
  291. data/lib/ecoportal/api/graphql/model/page/phased.rb +82 -20
  292. data/lib/ecoportal/api/graphql/model/page/task.rb +16 -0
  293. data/lib/ecoportal/api/graphql/model/page.rb +16 -14
  294. data/lib/ecoportal/api/graphql/model/page_union.rb +21 -0
  295. data/lib/ecoportal/api/graphql/model/pages_workflow.rb +20 -0
  296. data/lib/ecoportal/api/graphql/model/person_member.rb +15 -15
  297. data/lib/ecoportal/api/graphql/model/preset_view.rb +10 -0
  298. data/lib/ecoportal/api/graphql/model/preview_page.rb +10 -0
  299. data/lib/ecoportal/api/graphql/model/register.rb +10 -0
  300. data/lib/ecoportal/api/graphql/model/template.rb +15 -0
  301. data/lib/ecoportal/api/graphql/model.rb +32 -22
  302. data/lib/ecoportal/api/graphql/mutation/action/archive.rb +1 -1
  303. data/lib/ecoportal/api/graphql/mutation/action/create.rb +1 -1
  304. data/lib/ecoportal/api/graphql/mutation/action/update.rb +1 -1
  305. data/lib/ecoportal/api/graphql/mutation/ai_summary/generate.rb +45 -0
  306. data/lib/ecoportal/api/graphql/mutation/ai_summary/submit_feedback.rb +40 -0
  307. data/lib/ecoportal/api/graphql/mutation/ai_summary.rb +13 -0
  308. data/lib/ecoportal/api/graphql/mutation/contractor_entity/create.rb +1 -1
  309. data/lib/ecoportal/api/graphql/mutation/contractor_entity/destroy.rb +1 -1
  310. data/lib/ecoportal/api/graphql/mutation/contractor_entity/update.rb +1 -1
  311. data/lib/ecoportal/api/graphql/mutation/contractor_entity.rb +14 -14
  312. data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_jobs.rb +43 -0
  313. data/lib/ecoportal/api/graphql/mutation/kickstand/bulk_update_workflows.rb +43 -0
  314. data/lib/ecoportal/api/graphql/mutation/kickstand/fail_job.rb +39 -0
  315. data/lib/ecoportal/api/graphql/mutation/kickstand/fail_workflow.rb +39 -0
  316. data/lib/ecoportal/api/graphql/mutation/kickstand/start_job.rb +39 -0
  317. data/lib/ecoportal/api/graphql/mutation/kickstand/start_workflow.rb +39 -0
  318. data/lib/ecoportal/api/graphql/mutation/kickstand/stop_workflow.rb +39 -0
  319. data/lib/ecoportal/api/graphql/mutation/kickstand.rb +18 -0
  320. data/lib/ecoportal/api/graphql/mutation/location_structure/apply_commands.rb +3 -3
  321. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/add_commands.rb +2 -2
  322. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/create.rb +2 -2
  323. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/drop_bad_commands.rb +3 -3
  324. data/lib/ecoportal/api/graphql/mutation/location_structure/draft/publish.rb +3 -3
  325. data/lib/ecoportal/api/graphql/mutation/page/approve_review_task.rb +40 -0
  326. data/lib/ecoportal/api/graphql/mutation/page/archive.rb +40 -0
  327. data/lib/ecoportal/api/graphql/mutation/page/batch_update_review_task.rb +38 -0
  328. data/lib/ecoportal/api/graphql/mutation/page/build_from_template.rb +50 -0
  329. data/lib/ecoportal/api/graphql/mutation/page/create_draft.rb +38 -0
  330. data/lib/ecoportal/api/graphql/mutation/page/create_from_template.rb +43 -0
  331. data/lib/ecoportal/api/graphql/mutation/page/delete_draft.rb +38 -0
  332. data/lib/ecoportal/api/graphql/mutation/page/execute_force_commands.rb +69 -0
  333. data/lib/ecoportal/api/graphql/mutation/page/execute_workflow_commands.rb +52 -0
  334. data/lib/ecoportal/api/graphql/mutation/page/publish_draft.rb +38 -0
  335. data/lib/ecoportal/api/graphql/mutation/page/reject_review_task.rb +40 -0
  336. data/lib/ecoportal/api/graphql/mutation/page/restart_review_task.rb +40 -0
  337. data/lib/ecoportal/api/graphql/mutation/page/unarchive.rb +40 -0
  338. data/lib/ecoportal/api/graphql/mutation/page/undo_review_task.rb +40 -0
  339. data/lib/ecoportal/api/graphql/mutation/page/update.rb +40 -0
  340. data/lib/ecoportal/api/graphql/mutation/page/update_variable_bindings.rb +44 -0
  341. data/lib/ecoportal/api/graphql/mutation/page.rb +28 -0
  342. data/lib/ecoportal/api/graphql/mutation/preset_view/create.rb +35 -0
  343. data/lib/ecoportal/api/graphql/mutation/preset_view/destroy.rb +34 -0
  344. data/lib/ecoportal/api/graphql/mutation/preset_view/permission.rb +37 -0
  345. data/lib/ecoportal/api/graphql/mutation/preset_view/update.rb +35 -0
  346. data/lib/ecoportal/api/graphql/mutation/preset_view.rb +15 -0
  347. data/lib/ecoportal/api/graphql/mutation/register/create.rb +35 -0
  348. data/lib/ecoportal/api/graphql/mutation/register/destroy.rb +35 -0
  349. data/lib/ecoportal/api/graphql/mutation/register/update.rb +35 -0
  350. data/lib/ecoportal/api/graphql/mutation/register.rb +14 -0
  351. data/lib/ecoportal/api/graphql/mutation/smart_fill/generate.rb +36 -0
  352. data/lib/ecoportal/api/graphql/mutation/smart_fill/submit_feedback.rb +40 -0
  353. data/lib/ecoportal/api/graphql/mutation/smart_fill.rb +13 -0
  354. data/lib/ecoportal/api/graphql/mutation/template/create.rb +39 -0
  355. data/lib/ecoportal/api/graphql/mutation/template/create_related_page.rb +46 -0
  356. data/lib/ecoportal/api/graphql/mutation/template/destroy_related_page.rb +43 -0
  357. data/lib/ecoportal/api/graphql/mutation/template/publish.rb +39 -0
  358. data/lib/ecoportal/api/graphql/mutation/template/unpublish.rb +39 -0
  359. data/lib/ecoportal/api/graphql/mutation/template/update.rb +43 -0
  360. data/lib/ecoportal/api/graphql/mutation/template/update_information.rb +43 -0
  361. data/lib/ecoportal/api/graphql/mutation/template.rb +18 -0
  362. data/lib/ecoportal/api/graphql/mutation.rb +20 -12
  363. data/lib/ecoportal/api/graphql/payload/ai_summary_generate.rb +12 -0
  364. data/lib/ecoportal/api/graphql/payload/contractor_entity.rb +14 -14
  365. data/lib/ecoportal/api/graphql/payload/execute_workflow_commands.rb +36 -0
  366. data/lib/ecoportal/api/graphql/payload/force_commands.rb +31 -0
  367. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_jobs.rb +36 -0
  368. data/lib/ecoportal/api/graphql/payload/kickstand/bulk_update_workflows.rb +36 -0
  369. data/lib/ecoportal/api/graphql/payload/kickstand/job.rb +13 -0
  370. data/lib/ecoportal/api/graphql/payload/kickstand/workflow.rb +13 -0
  371. data/lib/ecoportal/api/graphql/payload/kickstand.rb +15 -0
  372. data/lib/ecoportal/api/graphql/payload/location_structure/draft/create.rb +33 -34
  373. data/lib/ecoportal/api/graphql/payload/ok_payload.rb +36 -0
  374. data/lib/ecoportal/api/graphql/payload/page/archive.rb +13 -0
  375. data/lib/ecoportal/api/graphql/payload/page/build_from_template.rb +13 -0
  376. data/lib/ecoportal/api/graphql/payload/page/create_from_template.rb +13 -0
  377. data/lib/ecoportal/api/graphql/payload/page/draft.rb +26 -0
  378. data/lib/ecoportal/api/graphql/payload/page/review_task.rb +13 -0
  379. data/lib/ecoportal/api/graphql/payload/page/review_task_batch.rb +23 -0
  380. data/lib/ecoportal/api/graphql/payload/page/unarchive.rb +13 -0
  381. data/lib/ecoportal/api/graphql/payload/page/update.rb +13 -0
  382. data/lib/ecoportal/api/graphql/payload/page/update_variable_bindings.rb +13 -0
  383. data/lib/ecoportal/api/graphql/payload/page.rb +20 -0
  384. data/lib/ecoportal/api/graphql/payload/preset_view.rb +15 -0
  385. data/lib/ecoportal/api/graphql/payload/register.rb +15 -0
  386. data/lib/ecoportal/api/graphql/payload/template/create.rb +13 -0
  387. data/lib/ecoportal/api/graphql/payload/template/create_related_page.rb +13 -0
  388. data/lib/ecoportal/api/graphql/payload/template/destroy_related_page.rb +13 -0
  389. data/lib/ecoportal/api/graphql/payload/template/publish.rb +13 -0
  390. data/lib/ecoportal/api/graphql/payload/template/unpublish.rb +13 -0
  391. data/lib/ecoportal/api/graphql/payload/template/update.rb +13 -0
  392. data/lib/ecoportal/api/graphql/payload/template/update_information.rb +13 -0
  393. data/lib/ecoportal/api/graphql/payload/template.rb +18 -0
  394. data/lib/ecoportal/api/graphql/payload.rb +23 -12
  395. data/lib/ecoportal/api/graphql/query/action.rb +1 -1
  396. data/lib/ecoportal/api/graphql/query/action_categories.rb +1 -1
  397. data/lib/ecoportal/api/graphql/query/actions.rb +2 -2
  398. data/lib/ecoportal/api/graphql/query/contractor_entities.rb +1 -1
  399. data/lib/ecoportal/api/graphql/query/file_upload_signature.rb +76 -0
  400. data/lib/ecoportal/api/graphql/query/location_structure/draft.rb +62 -62
  401. data/lib/ecoportal/api/graphql/query/location_structure.rb +61 -61
  402. data/lib/ecoportal/api/graphql/query/location_structures.rb +57 -57
  403. data/lib/ecoportal/api/graphql/query/page.rb +45 -0
  404. data/lib/ecoportal/api/graphql/query/page_delta.rb +47 -0
  405. data/lib/ecoportal/api/graphql/query/page_with_forces.rb +49 -0
  406. data/lib/ecoportal/api/graphql/query/pages.rb +59 -0
  407. data/lib/ecoportal/api/graphql/query/pages_workflow_commands.rb +65 -0
  408. data/lib/ecoportal/api/graphql/query/register_preset_views.rb +78 -0
  409. data/lib/ecoportal/api/graphql/query/register_preview_pages.rb +83 -0
  410. data/lib/ecoportal/api/graphql/query/templates.rb +53 -0
  411. data/lib/ecoportal/api/graphql/query.rb +27 -16
  412. data/lib/ecoportal/api/graphql.rb +143 -80
  413. data/lib/ecoportal/api/graphql_version.rb +5 -5
  414. metadata +333 -25
  415. data/.gitignore +0 -24
  416. data/.markdownlint.json +0 -4
  417. data/.rspec +0 -3
  418. data/.rubocop.yml +0 -97
  419. data/.ruby-version +0 -1
  420. data/.yardopts +0 -10
  421. data/Gemfile +0 -6
  422. data/Rakefile +0 -38
  423. data/bin/console +0 -14
  424. data/bin/setup +0 -8
  425. data/bin/setup.ps1 +0 -6
  426. data/ecoportal-api-graphql.gemspec +0 -40
  427. data/tests/actions_get.rb +0 -7
  428. data/tests/contractor_entities_get.rb +0 -20
  429. data/tests/contractor_entity_create.rb +0 -19
  430. data/tests/contractor_entity_udpate.rb +0 -20
  431. data/tests/loc_structure_get.rb +0 -11
  432. data/tests/loc_structure_update.rb +0 -51
  433. data/tests/loc_structures_get.rb +0 -15
  434. data/tests/local_libs.rb +0 -20
@@ -0,0 +1,36 @@
1
+ # common/graphql
2
+
3
+ Shared HTTP transport, authentication, and base model infrastructure used by the gem — nothing here is EcoPortal-domain-specific.
4
+
5
+ ## Contents
6
+
7
+ | File / class | Purpose |
8
+ |---|---|
9
+ | `auth_service.rb` / `AuthService` | OAuth2 password + refresh-token flow; included in both client classes |
10
+ | `client.rb` / `Client` | Graphlient-based GraphQL client (builds bearer-token headers, constructs endpoint URL) |
11
+ | `http_client.rb` / `HttpClient` | Raw HTTP client (extends `Common::Client`); `execute` sends query strings + variables; supports v0–v3 + graphql API version modes |
12
+ | `class_helpers.rb` / `ClassHelpers` | `becomes(klass)` instance casting + `const?` class helper |
13
+ | `hash_helpers.rb` / `HashHelpers` | Deep key transforms (`keys_to_sym_deep`, `deep_dup`, `remove_nil_keys_deep`) — used by diff and input serialisation |
14
+ | `query_integration.rb` / `QueryIntegration` | Class macro `query(:method, query_klass:)` that wires a named query method on `Model::Organization` |
15
+ | `model.rb` / `Model` | Base model class: `DoubleModel` + `Diffable` + `AsInput`; all GraphQL models ultimately inherit this |
16
+ | `patches.rb` | Reserved placeholder (empty) |
17
+ | `model/diffable.rb` | `as_update` / `dirty?` — delegates to `DiffService` |
18
+ | `model/as_input.rb` | `as_input` (instance) and `as_input(hash)` (class method) — converts diff to GraphQL mutation variables |
19
+ | `model/diffable/diff_service.rb` | Main diff engine: flat classic diff + cascaded reduce through nested `GraphQL::Model` objects |
20
+ | `model/diffable/classic_diff_service.rb` | Low-level change-data extraction (compares `curr_doc` vs `prev_doc`) |
21
+ | `model/diffable/hash_diff.rb` | Hash equality / change detection helpers |
22
+ | `model/diffable/hash_diff_nesting.rb` | Nested key path helpers (`dig_set!`, `dig_delete!`, `dig_path?`) |
23
+
24
+ ## Conventions
25
+
26
+ - `Client` is graphlient-based and used for schema introspection; `HttpClient` is the actual request sender used in production (set as `client.http_client`).
27
+ - `HashHelpers` is used as both a module mixin (include) and directly via `HashHelpers.keys_to_sym_deep(...)`.
28
+ - `DiffService` handles the `flat:` flag: `flat: true` does a single-level diff; `flat: false` (default) cascades through nested `GraphQL::Model` objects.
29
+ - Root-class objects (`root!` declared) are excluded from cascaded diffs — they represent independent server entities.
30
+ - `AsInput#as_input(target_class:)` delegates to `Input::X.from_model(self)` when a target class is given.
31
+
32
+ ## Related
33
+
34
+ - `../graphql/logic/base_model.rb` — adds `SnakeCamelAccess` on top of `Common::GraphQL::Model`
35
+ - `../graphql/logic/input.rb` — `Logic::Input` base class built on top of `Model`
36
+ - `../graphql/logic/base_query.rb` — consumes `HttpClient#execute` and `HashHelpers`
@@ -6,7 +6,7 @@ module Ecoportal
6
6
  class Client < ::Graphlient::Client
7
7
  ENDPOINT_PATH = 'external/graphql'.freeze
8
8
 
9
- attr_accessor :host
9
+ attr_accessor :host, :http_client
10
10
 
11
11
  READ_TIMEOUT = 90
12
12
  WRITE_TIMEOUT = 90
@@ -1,145 +1,195 @@
1
- module Ecoportal
2
- module API
3
- module Common
4
- module GraphQL
5
- class HttpClient < Common::Client
6
- class << self
7
- def base_url(host)
8
- "#{protocol(host)}://#{host}"
9
- end
10
-
11
- def protocol(host)
12
- host.match(/^localhost|^127\.0\.0\.1/)? 'http' : 'https'
13
- end
14
- end
15
-
16
- READ_TIMEOUT = 90
17
- WRITE_TIMEOUT = 90
18
-
19
- attr_reader :host, :version
20
-
21
- include Ecoportal::API::Common::GraphQL::AuthService
22
-
23
- def initialize(
24
- email: nil,
25
- pass: nil,
26
- org_id: nil,
27
- api_key: nil,
28
- version: 'graphql',
29
- host: 'live.ecoportal.com',
30
- logger: ::Logger.new(IO::NULL),
31
- deep_logging: false,
32
- no_schema: true
33
- )
34
- @org_id = org_id
35
- @user_email = email
36
- @user_pass = pass
37
- @no_schema = no_schema
38
- @version = version
39
-
40
- super(
41
- api_key: api_key,
42
- host: host,
43
- logger: logger,
44
- deep_logging: deep_logging
45
- )
46
- end
47
-
48
- # Creates a HTTP object adding the `X-ApiKey` or `X-ECOPORTAL-API-KEY` param to the header, depending on the API version.
49
- # @note It configures HTTP so it only allows body data in json format.
50
- # @return [HTTP] HTTP object.
51
- def base_request
52
- @base_request ||=
53
- case @version
54
- when NilClass, 'http'
55
- HTTP
56
- when 'v1', 'v0'
57
- HTTP.headers('X-ApiKey' => key_token)
58
- when 'v2', 'v3'
59
- HTTP.headers('X-ECOPORTAL-API-KEY' => key_token)
60
- when 'graphql'
61
- HTTP.headers('Authorization' => "Bearer #{key_token}")
62
- end.then do |request|
63
- request.accept(:json).timeout(
64
- read: READ_TIMEOUT,
65
- write: WRITE_TIMEOUT
66
- )
67
- end
68
- end
69
-
70
- def org_id
71
- @org_id || fetch_env_required('ORGANIZATION_ID')
72
- end
73
-
74
- # Full URl builder of the request
75
- # @param path [String] the tail that completes the url of the request.
76
- # @return [String] the final url.
77
- def url_for(path)
78
- "#{api_url}#{path}"
79
- end
80
-
81
- private
82
-
83
- def key_token
84
- return if http?
85
- return session_token(host: host) if graphql?
86
- return @api_key if api_key?
87
- return ENV['ORG_INT_KEY'] if v0?
88
-
89
- puts 'Api-key missing!'
90
- end
91
-
92
- def api_url
93
- base_url.then do |url|
94
- next "#{url}/api/#{version}" if v1_0? || v2_3?
95
- next "#{url}/api/#{org_id}/graphql" if graphql?
96
-
97
- url
98
- end
99
- end
100
-
101
- def base_url
102
- @base_url ||= self.class.base_url(host)
103
- end
104
-
105
- def protocol
106
- @protocol ||= self.class.protocol(host)
107
- end
108
-
109
- def http?
110
- return true if @version.nil?
111
-
112
- @version == 'http'
113
- end
114
-
115
- def api_key?
116
- @api_key && !@api_key.match(/\A\W*\z/)
117
- end
118
-
119
- def v1_0?
120
- v1? || v0?
121
- end
122
-
123
- def v1?
124
- @version == 'v1'
125
- end
126
-
127
- def v0?
128
- @version == 'v0'
129
- end
130
-
131
- def v2_3?
132
- return true if @version == 'v2'
133
- return true if @version == 'v3'
134
-
135
- false
136
- end
137
-
138
- def graphql?
139
- @version == 'graphql'
140
- end
141
- end
142
- end
143
- end
144
- end
145
- end
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module GraphQL
5
+ class ResponseError < StandardError; end
6
+
7
+ class HttpClient < Common::Client
8
+ class << self
9
+ def base_url(host)
10
+ "#{protocol(host)}://#{host}"
11
+ end
12
+
13
+ def protocol(host)
14
+ host.match(/^localhost|^127\.0\.0\.1/)? 'http' : 'https'
15
+ end
16
+ end
17
+
18
+ ENDPOINT_PATH = 'external/graphql'.freeze
19
+ READ_TIMEOUT = 90
20
+ WRITE_TIMEOUT = 90
21
+
22
+ attr_reader :host, :version
23
+
24
+ # Publicly exposes the configured api_key (inherited as `private` from
25
+ # `Common::Client`) — `FileUpload::Client` needs it directly to authenticate
26
+ # against the v2 REST endpoints, independent of this client's own `@version`
27
+ # (which stays `'graphql'` and therefore always builds a Bearer `key_token`).
28
+ public :api_key
29
+
30
+ include Ecoportal::API::Common::GraphQL::AuthService
31
+
32
+ def initialize(
33
+ email: nil,
34
+ pass: nil,
35
+ org_id: nil,
36
+ api_key: nil,
37
+ version: 'graphql',
38
+ host: 'live.ecoportal.com',
39
+ logger: ::Logger.new(IO::NULL),
40
+ deep_logging: false,
41
+ no_schema: true
42
+ )
43
+ @org_id = org_id
44
+ @user_email = email
45
+ @user_pass = pass
46
+ @no_schema = no_schema
47
+ @version = version
48
+
49
+ super(
50
+ api_key: api_key,
51
+ host: host,
52
+ logger: logger,
53
+ deep_logging: deep_logging
54
+ )
55
+ end
56
+
57
+ # Creates a HTTP object adding the `X-ApiKey` or `X-ECOPORTAL-API-KEY` param to the header, depending on the API version.
58
+ # @note It configures HTTP so it only allows body data in json format.
59
+ # @return [HTTP] HTTP object.
60
+ def base_request
61
+ @base_request ||=
62
+ case @version
63
+ when NilClass, 'http'
64
+ HTTP
65
+ when 'v1', 'v0'
66
+ HTTP.headers('X-ApiKey' => key_token)
67
+ when 'v2', 'v3'
68
+ HTTP.headers('X-ECOPORTAL-API-KEY' => key_token)
69
+ when 'graphql'
70
+ HTTP.headers('Authorization' => "Bearer #{session_token(host: host)}")
71
+ end.then do |request|
72
+ request ||= HTTP
73
+ request.accept(:json).timeout(
74
+ read: READ_TIMEOUT,
75
+ write: WRITE_TIMEOUT
76
+ )
77
+ end
78
+ end
79
+
80
+ def org_id
81
+ @org_id || fetch_env_required('ORGANIZATION_ID')
82
+ end
83
+
84
+ # Executes a GraphQL query or mutation over HTTP.
85
+ # @param query_string [String] full GraphQL query document.
86
+ # @param variables [Hash] variable values to pass to the operation.
87
+ # @param operation_name [String, nil] when the document has multiple operations.
88
+ # @return [Hash] parsed response body (string-keyed, includes 'data' and optionally 'errors').
89
+ # @raise [Ecoportal::API::Common::Client::Error::UnexpectedServerError] on non-2xx HTTP status.
90
+ # @raise [Ecoportal::API::Common::GraphQL::ResponseError] when the response body contains GraphQL errors.
91
+ def execute(query_string, variables: {}, operation_name: nil)
92
+ body = { query: query_string, variables: variables }
93
+ body[:operationName] = operation_name if operation_name
94
+
95
+ # Route through the inherited `Common::Client` pipeline
96
+ # (`instrument` -> `with_retry` { `rate_throttling` }) so GraphQL requests
97
+ # inherit the SAME battle-tested contingencies as the REST clients:
98
+ # rate-limit backoff (429 / Cloudflare 1015), 5xx + connection-error retries,
99
+ # timeouts, and instrumentation. Do NOT re-issue the request raw here — that
100
+ # bypasses all of the above and is what let live runs die on the first 429.
101
+ response = instrument('POST', ENDPOINT_PATH, body) do
102
+ request { |http| http.post(url_for(''), json: body) }
103
+ end
104
+
105
+ handle_http_response(response)
106
+ end
107
+
108
+ # Full URl builder of the request
109
+ # @param path [String] the tail that completes the url of the request.
110
+ # @return [String] the final url.
111
+ def url_for(path)
112
+ "#{api_url}#{path}"
113
+ end
114
+
115
+ private
116
+
117
+ def key_token
118
+ return if http?
119
+ return session_token(host: host) if graphql?
120
+ return @api_key if api_key?
121
+ return ENV['ORG_INT_KEY'] if v0?
122
+
123
+ puts 'Api-key missing!'
124
+ end
125
+
126
+ def api_url
127
+ base_url.then do |url|
128
+ next "#{url}/api/#{version}" if v1_0? || v2_3?
129
+ next "#{url}/api/#{org_id}/#{ENDPOINT_PATH}" if graphql?
130
+
131
+ url
132
+ end
133
+ end
134
+
135
+ def base_url
136
+ @base_url ||= self.class.base_url(host)
137
+ end
138
+
139
+ def protocol
140
+ @protocol ||= self.class.protocol(host)
141
+ end
142
+
143
+ def http?
144
+ return true if @version.nil?
145
+
146
+ @version == 'http'
147
+ end
148
+
149
+ def api_key?
150
+ @api_key && !@api_key.match(/\A\W*\z/)
151
+ end
152
+
153
+ def v1_0?
154
+ v1? || v0?
155
+ end
156
+
157
+ def v1?
158
+ @version == 'v1'
159
+ end
160
+
161
+ def v0?
162
+ @version == 'v0'
163
+ end
164
+
165
+ def v2_3?
166
+ return true if @version == 'v2'
167
+ return true if @version == 'v3'
168
+
169
+ false
170
+ end
171
+
172
+ def graphql?
173
+ @version == 'graphql'
174
+ end
175
+
176
+ # @param response [Ecoportal::API::Common::Response] the wrapped response
177
+ # produced by the inherited pipeline (body already JSON-parsed).
178
+ def handle_http_response(response)
179
+ unless response.success?
180
+ raise Ecoportal::API::Common::Client::Error::UnexpectedServerError.new(
181
+ response.src_body, code: response.status.code
182
+ )
183
+ end
184
+
185
+ parsed = response.body
186
+ errors = parsed && parsed['errors']
187
+ raise ResponseError, errors.map { |e| e['message'] }.join('; ') if errors&.any?
188
+
189
+ parsed
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,28 @@
1
+ # common/graphql/model
2
+
3
+ Concerns that add dirty-tracking diff (`Diffable`) and mutation-input serialisation (`AsInput`) to the base `Common::GraphQL::Model`.
4
+
5
+ ## Contents
6
+
7
+ | File / class | Purpose |
8
+ |---|---|
9
+ | `diffable.rb` / `Model::Diffable` | Provides `as_update` (returns changed-field hash or nil) and `dirty?`; delegates to `DIFF_CLASS` (defaults to `DiffService`) |
10
+ | `as_input.rb` / `Model::AsInput` | Instance `as_input` (wraps diff as mutation variables) + class-level `as_input(hash)` (key-sym + nil-id cleanup) |
11
+ | `diffable/diff_service.rb` / `DiffService` | Primary diff engine: flat classic diff then cascaded reduce over nested `GraphQL::Model` children |
12
+ | `diffable/classic_diff_service.rb` / `ClassicDiffService` | Low-level diff: compares `curr_doc` vs `prev_doc`, returns `{ id:, changed_field: new_value }` or nil |
13
+ | `diffable/hash_diff.rb` / `HashDiff` | Primitive equality helpers used by `ClassicDiffService` |
14
+ | `diffable/hash_diff_nesting.rb` / `HashDiffNesting` | Nested path helpers: `dig_set!`, `dig_delete!`, `dig_path?` used when building cascaded diff results |
15
+
16
+ ## Conventions
17
+
18
+ - `DIFF_CLASS = DiffService` is a constant on `Diffable` — subclasses can override it to swap diff strategies.
19
+ - `DiffService` `flat: true` produces a single-level diff (current model only); `flat: false` (default) recurses via `cascaded_reduce` through nested `GraphQL::Model` objects.
20
+ - Objects declared with `root!` in their class are skipped during cascaded diff — they are independent server entities (look-ups only).
21
+ - `as_input` on a model calls `as_update` first; returns `nil` when nothing has changed so callers can skip the mutation.
22
+ - `as_input(target_class:)` is the preferred path when a corresponding `Input::X` class exists — delegates to `target_class.from_model(self)`.
23
+
24
+ ## Related
25
+
26
+ - `../hash_helpers.rb` — `HashHelpers` used inside `DiffService` for key transforms
27
+ - `../../graphql/logic/input.rb` — `Logic::Input.from_model` is the canonical consumer of `as_update`
28
+ - `../../graphql/logic/base_model.rb` — all concrete models inherit this chain
@@ -37,11 +37,14 @@ module Ecoportal
37
37
 
38
38
  # INSTANCE METHODS
39
39
 
40
- def as_input(clientMutationId: '')
41
- self.class.as_input(
42
- as_update,
43
- clientMutationId: clientMutationId
44
- )
40
+ def as_input(target_class: nil, clientMutationId: '')
41
+ return target_class.from_model(self, client_mutation_id: clientMutationId) if target_class
42
+
43
+ diff = as_update
44
+ return nil if diff.nil?
45
+
46
+ diff[:patchVer] = patchVer if respond_to?(:patchVer) && !patchVer.nil?
47
+ self.class.as_input(diff, clientMutationId: clientMutationId)
45
48
  end
46
49
  end
47
50
  end
@@ -38,10 +38,12 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
38
38
  raise "Can't fetch underlying document for instance of #{target.class}."
39
39
  end
40
40
 
41
- def prev_doc(target = subject, flat: flat?)
41
+ def prev_doc(target = subject)
42
42
  return target.original_doc if target.respond_to?(:original_doc)
43
43
 
44
44
  raise "Can't fetch original underlying model for instance of #{target.class}."
45
+ rescue NoMethodError
46
+ nil
45
47
  end
46
48
  end
47
49
  end
@@ -34,12 +34,17 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
34
34
 
35
35
  protected
36
36
 
37
+ # Override: GraphQL mutations expect flat changed-prop values, not patch-op wrappers.
38
+ # Returns { id: ..., changed_field: new_value, ... } or nil when nothing changed.
37
39
  def classic_diff(flat: flat?, ignore: [])
38
- change_diff(
39
- curr_doc(flat: flat),
40
- prev_doc(flat: flat),
41
- ignore: to_a(ignored, ignore)
42
- )
40
+ curr = keys_to_sym_deep(curr_doc(flat: flat) || {})
41
+ prev = keys_to_sym_deep(prev_doc(flat: flat) || {})
42
+
43
+ data = change_data(curr, prev, ignore: to_a(ignored, ignore))
44
+ return nil if data == NO_CHANGES
45
+
46
+ id = get_id(curr, exception: false)
47
+ id ? { id: id }.merge(data) : data
43
48
  end
44
49
 
45
50
  # @note it calls `as_update` for nested / cascaded attributes, which in turn
@@ -49,26 +54,28 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
49
54
  # `#as_update` and `DiffService#diff`.
50
55
  # - The `result` object regards, therefore, to the **current level** alone.
51
56
  # With the aim of building it up (accumulating through the call chain).
52
- def diff_reduce(init = {}, ignore: [])
57
+ def diff_reduce(init, ignore: [])
53
58
  subject.cascaded_reduce(init, recurs: false) do |result, obj, _key, key_path, _trace|
54
- next result if key_path.empty? # first iteration already done
55
- next result if obj == subject # first call had done it (same as above: path relative)
59
+ next result if key_path.empty?
60
+ next result if obj == subject
56
61
 
57
- dig_delete!(result, key_path) if dig_path?(result, key_path)
62
+ sym_path = key_path.map(&:to_sym)
58
63
 
59
- # discard rooted (i.e. read_only) objects from the diff.
64
+ # Remove any flat-diff placeholder for this key before deciding its fate.
65
+ dig_delete!(result, sym_path) if result && dig_path?(result, sym_path)
66
+
67
+ # Discard root-class objects — they are independent entities, not mutation payload.
60
68
  next result if root?(obj)
61
- next result unless dig_path?(result, key_path)
62
- next result unless obj.respond_to?(:as_update)
69
+ # Only cascade-diff GraphQL model objects; ecoportal-api-v2 DoubleModel
70
+ # subclasses (ArrayModel, etc.) have a different as_update signature.
71
+ next result unless obj.is_a?(Ecoportal::API::Common::GraphQL::Model)
63
72
 
64
73
  value = obj.as_update(ignore: ignore)
74
+ next result if value.nil?
65
75
 
66
- dig_set!(
67
- result,
68
- key_path,
69
- value
70
- )
71
-
76
+ result ||= {}
77
+ result[:id] ||= get_id(keys_to_sym_deep(curr_doc(flat: true) || {}), exception: false)
78
+ dig_set!(result, sym_path, value)
72
79
  result
73
80
  end
74
81
  end
@@ -147,9 +154,10 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
147
154
  attr_reader :ignored
148
155
 
149
156
  def root?(obj)
150
- return false unless obj.respond_to?(:root?)
151
-
152
- obj.root?
157
+ # root? is a CLASS method (via Rootable::ClassMethods). The instance root?
158
+ # is protected and checks parent position, not the class declaration.
159
+ # Check the ancestor chain for any class that declared root!.
160
+ obj.class.ancestors.any? { |k| k.respond_to?(:root?) && k.root? }
153
161
  end
154
162
 
155
163
  def curr_doc(target = subject, flat: flat?)
@@ -171,8 +179,8 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
171
179
 
172
180
  # Remove from `json` doc all the nested properties.
173
181
  def doc_with_non_cascaded_attributes(json)
174
- return json unless subject.respond_to?(:_cascaded_doc_keys)
175
- return json unless (excluded = subject._cascaded_doc_keys)
182
+ return json unless subject.class.respond_to?(:_cascaded_doc_keys)
183
+ return json if (excluded = subject.class._cascaded_doc_keys).empty?
176
184
 
177
185
  except_keys(json, *excluded)
178
186
  end
@@ -192,7 +192,7 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
192
192
  end
193
193
 
194
194
  def any_array?(a, b)
195
- [a, b].any? {|item| item.is_a?(Array)}
195
+ [a, b].any?(Array)
196
196
  end
197
197
 
198
198
  def get_id(doc, exception: true)
@@ -207,6 +207,30 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
207
207
  id
208
208
  end
209
209
 
210
+ # @param arr [Array] the source Array of id-bearing items
211
+ # @return [Array<String>] the `id`s thereof
212
+ def array_ids(arr)
213
+ return [] if !arr.is_a?(Array) || arr.empty?
214
+
215
+ arr.map {|item| get_id(item, exception: false)}
216
+ end
217
+
218
+ # @param arr [Array] the source Array
219
+ # @return [Integer, nil] the position of the item with the given `id`
220
+ def array_id_index(arr, id)
221
+ return unless arr.is_a?(Array)
222
+
223
+ arr.index {|item| get_id(item, exception: false) == id}
224
+ end
225
+
226
+ # @param arr [Array] the source Array
227
+ # @return [Object, nil] the item with the given `id`
228
+ def array_id_item(arr, id)
229
+ return unless (idx = array_id_index(arr, id))
230
+
231
+ arr[idx]
232
+ end
233
+
210
234
  def meta_keys
211
235
  return self::META_KEYS if respond_to?(:const_get)
212
236
 
@@ -233,6 +257,35 @@ module Ecoportal::API::Common::GraphQL::Model::Diffable
233
257
  def to_a(*values)
234
258
  [values].flatten.compact.uniq
235
259
  end
260
+
261
+ # Hash path helpers — used by DiffService#diff_reduce to navigate
262
+ # and modify nested result hashes during cascaded diffing.
263
+
264
+ def dig_path?(obj, keys)
265
+ return false unless obj.is_a?(Hash)
266
+ return obj.key?(keys.first) if keys.length == 1
267
+ return false unless obj.key?(keys.first)
268
+
269
+ dig_path?(obj[keys.first], keys[1..])
270
+ end
271
+
272
+ def dig_set!(obj, keys, value)
273
+ if keys.length == 1
274
+ obj[keys.first] = value
275
+ else
276
+ dig_set!(obj[keys.first], keys[1..], value)
277
+ end
278
+ end
279
+
280
+ def dig_delete!(obj, keys)
281
+ if keys.length == 1
282
+ return unless obj.respond_to?(:delete)
283
+
284
+ obj.delete(keys.first)
285
+ else
286
+ dig_delete!(obj[keys.first], keys[1..])
287
+ end
288
+ end
236
289
  end
237
290
 
238
291
  extend InstanceMethods