@commandable/integration-data 0.0.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 (335) hide show
  1. package/dist/credentials-index.d.ts +30 -0
  2. package/dist/credentials-index.d.ts.map +1 -0
  3. package/dist/credentials-index.js +292 -0
  4. package/dist/credentials-index.js.map +1 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +2 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/loader.d.ts +69 -0
  10. package/dist/loader.d.ts.map +1 -0
  11. package/dist/loader.js +164 -0
  12. package/dist/loader.js.map +1 -0
  13. package/integrations/README.md +52 -0
  14. package/integrations/airtable/__tests__/get_handlers.test.ts +137 -0
  15. package/integrations/airtable/__tests__/usage_parity.test.ts +35 -0
  16. package/integrations/airtable/__tests__/write_and_admin_handlers.test.ts +113 -0
  17. package/integrations/airtable/credentials.json +20 -0
  18. package/integrations/airtable/credentials_hint.md +4 -0
  19. package/integrations/airtable/handlers/create_record.js +12 -0
  20. package/integrations/airtable/handlers/delete_record.js +7 -0
  21. package/integrations/airtable/handlers/get_record.js +4 -0
  22. package/integrations/airtable/handlers/get_table_schema.js +6 -0
  23. package/integrations/airtable/handlers/list_bases.js +4 -0
  24. package/integrations/airtable/handlers/list_records.js +25 -0
  25. package/integrations/airtable/handlers/list_table_fields.js +6 -0
  26. package/integrations/airtable/handlers/list_tables.js +4 -0
  27. package/integrations/airtable/handlers/list_views.js +6 -0
  28. package/integrations/airtable/handlers/search_records.js +6 -0
  29. package/integrations/airtable/handlers/update_record.js +11 -0
  30. package/integrations/airtable/manifest.json +83 -0
  31. package/integrations/airtable/schemas/create_record.json +12 -0
  32. package/integrations/airtable/schemas/delete_record.json +11 -0
  33. package/integrations/airtable/schemas/empty.json +6 -0
  34. package/integrations/airtable/schemas/get_record.json +11 -0
  35. package/integrations/airtable/schemas/id_base.json +9 -0
  36. package/integrations/airtable/schemas/id_base_table.json +10 -0
  37. package/integrations/airtable/schemas/list_records.json +26 -0
  38. package/integrations/airtable/schemas/search_records.json +12 -0
  39. package/integrations/airtable/schemas/update_record.json +13 -0
  40. package/integrations/github/__tests__/get_handlers.test.ts +117 -0
  41. package/integrations/github/__tests__/usage_parity.test.ts +34 -0
  42. package/integrations/github/__tests__/write_handlers.test.ts +311 -0
  43. package/integrations/github/credentials.json +20 -0
  44. package/integrations/github/credentials_hint.md +7 -0
  45. package/integrations/github/handlers/add_labels_to_issue.js +12 -0
  46. package/integrations/github/handlers/close_issue.js +5 -0
  47. package/integrations/github/handlers/comment_on_issue.js +5 -0
  48. package/integrations/github/handlers/create_branch.js +33 -0
  49. package/integrations/github/handlers/create_commit.js +91 -0
  50. package/integrations/github/handlers/create_issue.js +10 -0
  51. package/integrations/github/handlers/create_or_update_file.js +21 -0
  52. package/integrations/github/handlers/create_pull_request.js +16 -0
  53. package/integrations/github/handlers/create_repo.js +11 -0
  54. package/integrations/github/handlers/delete_repo.js +6 -0
  55. package/integrations/github/handlers/get_issue.js +4 -0
  56. package/integrations/github/handlers/get_repo.js +4 -0
  57. package/integrations/github/handlers/list_branches.js +4 -0
  58. package/integrations/github/handlers/list_commits.js +12 -0
  59. package/integrations/github/handlers/list_issues.js +12 -0
  60. package/integrations/github/handlers/list_pull_requests.js +8 -0
  61. package/integrations/github/handlers/list_repos_install.js +4 -0
  62. package/integrations/github/handlers/list_repos_user.js +4 -0
  63. package/integrations/github/handlers/merge_pull_request.js +14 -0
  64. package/integrations/github/handlers/update_issue.js +15 -0
  65. package/integrations/github/manifest.json +26 -0
  66. package/integrations/github/schemas/add_labels_to_issue.json +12 -0
  67. package/integrations/github/schemas/close_issue.json +10 -0
  68. package/integrations/github/schemas/comment_on_issue.json +11 -0
  69. package/integrations/github/schemas/create_branch.json +12 -0
  70. package/integrations/github/schemas/create_commit.json +25 -0
  71. package/integrations/github/schemas/create_issue.json +13 -0
  72. package/integrations/github/schemas/create_or_update_file.json +15 -0
  73. package/integrations/github/schemas/create_pull_request.json +15 -0
  74. package/integrations/github/schemas/create_repo.json +12 -0
  75. package/integrations/github/schemas/delete_repo.json +10 -0
  76. package/integrations/github/schemas/empty.json +5 -0
  77. package/integrations/github/schemas/get_issue.json +10 -0
  78. package/integrations/github/schemas/get_repo.json +9 -0
  79. package/integrations/github/schemas/list_commits.json +12 -0
  80. package/integrations/github/schemas/list_issues.json +12 -0
  81. package/integrations/github/schemas/list_pull_requests.json +10 -0
  82. package/integrations/github/schemas/merge_pull_request.json +14 -0
  83. package/integrations/github/schemas/owner_repo.json +9 -0
  84. package/integrations/github/schemas/update_issue.json +15 -0
  85. package/integrations/google-calendar/__tests__/get_handlers.test.ts +112 -0
  86. package/integrations/google-calendar/__tests__/usage_parity.test.ts +34 -0
  87. package/integrations/google-calendar/__tests__/write_and_admin_handlers.test.ts +161 -0
  88. package/integrations/google-calendar/credentials.json +36 -0
  89. package/integrations/google-calendar/credentials_hint.md +9 -0
  90. package/integrations/google-calendar/handlers/create_event.js +6 -0
  91. package/integrations/google-calendar/handlers/delete_acl.js +6 -0
  92. package/integrations/google-calendar/handlers/delete_event.js +7 -0
  93. package/integrations/google-calendar/handlers/freebusy_query.js +4 -0
  94. package/integrations/google-calendar/handlers/get_acl.js +5 -0
  95. package/integrations/google-calendar/handlers/get_calendar.js +4 -0
  96. package/integrations/google-calendar/handlers/get_event.js +5 -0
  97. package/integrations/google-calendar/handlers/insert_acl.js +6 -0
  98. package/integrations/google-calendar/handlers/list_acl.js +5 -0
  99. package/integrations/google-calendar/handlers/list_calendars.js +4 -0
  100. package/integrations/google-calendar/handlers/list_colors.js +4 -0
  101. package/integrations/google-calendar/handlers/list_events.js +21 -0
  102. package/integrations/google-calendar/handlers/list_settings.js +4 -0
  103. package/integrations/google-calendar/handlers/move_event.js +6 -0
  104. package/integrations/google-calendar/handlers/patch_event.js +5 -0
  105. package/integrations/google-calendar/handlers/quick_add.js +6 -0
  106. package/integrations/google-calendar/handlers/update_acl.js +7 -0
  107. package/integrations/google-calendar/handlers/update_event.js +5 -0
  108. package/integrations/google-calendar/manifest.json +26 -0
  109. package/integrations/google-calendar/schemas/create_event.json +34 -0
  110. package/integrations/google-calendar/schemas/delete_acl.json +9 -0
  111. package/integrations/google-calendar/schemas/empty.json +1 -0
  112. package/integrations/google-calendar/schemas/freebusy_query.json +13 -0
  113. package/integrations/google-calendar/schemas/get_acl.json +9 -0
  114. package/integrations/google-calendar/schemas/id_calendar.json +8 -0
  115. package/integrations/google-calendar/schemas/id_calendar_event.json +9 -0
  116. package/integrations/google-calendar/schemas/insert_acl.json +18 -0
  117. package/integrations/google-calendar/schemas/list_events.json +15 -0
  118. package/integrations/google-calendar/schemas/move_event.json +10 -0
  119. package/integrations/google-calendar/schemas/patch_event.json +10 -0
  120. package/integrations/google-calendar/schemas/quick_add.json +9 -0
  121. package/integrations/google-calendar/schemas/update_acl.json +10 -0
  122. package/integrations/google-calendar/schemas/update_event.json +10 -0
  123. package/integrations/google-docs/__tests__/get_handlers.test.ts +72 -0
  124. package/integrations/google-docs/__tests__/usage_parity.test.ts +34 -0
  125. package/integrations/google-docs/__tests__/write_handlers.test.ts +249 -0
  126. package/integrations/google-docs/credentials.json +36 -0
  127. package/integrations/google-docs/credentials_hint.md +9 -0
  128. package/integrations/google-docs/handlers/append_text.js +12 -0
  129. package/integrations/google-docs/handlers/batch_update.js +13 -0
  130. package/integrations/google-docs/handlers/create_document.js +9 -0
  131. package/integrations/google-docs/handlers/delete_first_match.js +50 -0
  132. package/integrations/google-docs/handlers/get_document.js +12 -0
  133. package/integrations/google-docs/handlers/get_document_structured.js +6 -0
  134. package/integrations/google-docs/handlers/get_document_text.js +17 -0
  135. package/integrations/google-docs/handlers/insert_inline_image_after_first_match.js +41 -0
  136. package/integrations/google-docs/handlers/insert_page_break_after_first_match.js +49 -0
  137. package/integrations/google-docs/handlers/insert_table_after_first_match.js +49 -0
  138. package/integrations/google-docs/handlers/insert_text_after_first_match.js +51 -0
  139. package/integrations/google-docs/handlers/replace_all_text.js +8 -0
  140. package/integrations/google-docs/handlers/style_first_match.js +42 -0
  141. package/integrations/google-docs/handlers/update_document_style.js +8 -0
  142. package/integrations/google-docs/handlers/update_paragraph_style_for_first_match.js +48 -0
  143. package/integrations/google-docs/manifest.json +58 -0
  144. package/integrations/google-docs/schemas/append_text.json +10 -0
  145. package/integrations/google-docs/schemas/apply_text_style.json +13 -0
  146. package/integrations/google-docs/schemas/batch_update.json +16 -0
  147. package/integrations/google-docs/schemas/create_document.json +8 -0
  148. package/integrations/google-docs/schemas/delete_content_range.json +11 -0
  149. package/integrations/google-docs/schemas/delete_first_match.json +10 -0
  150. package/integrations/google-docs/schemas/get_document.json +11 -0
  151. package/integrations/google-docs/schemas/get_document_structured.json +9 -0
  152. package/integrations/google-docs/schemas/get_document_text.json +9 -0
  153. package/integrations/google-docs/schemas/insert_inline_image.json +12 -0
  154. package/integrations/google-docs/schemas/insert_inline_image_after_first_match.json +13 -0
  155. package/integrations/google-docs/schemas/insert_page_break.json +10 -0
  156. package/integrations/google-docs/schemas/insert_page_break_after_first_match.json +11 -0
  157. package/integrations/google-docs/schemas/insert_table.json +12 -0
  158. package/integrations/google-docs/schemas/insert_table_after_first_match.json +13 -0
  159. package/integrations/google-docs/schemas/insert_text_after_first_match.json +12 -0
  160. package/integrations/google-docs/schemas/insert_text_at.json +11 -0
  161. package/integrations/google-docs/schemas/replace_all_text.json +12 -0
  162. package/integrations/google-docs/schemas/style_first_match.json +12 -0
  163. package/integrations/google-docs/schemas/update_document_style.json +11 -0
  164. package/integrations/google-docs/schemas/update_paragraph_style.json +13 -0
  165. package/integrations/google-docs/schemas/update_paragraph_style_for_first_match.json +12 -0
  166. package/integrations/google-sheet/__tests__/get_handlers.test.ts +129 -0
  167. package/integrations/google-sheet/__tests__/usage_parity.test.ts +35 -0
  168. package/integrations/google-sheet/__tests__/write_handlers.test.ts +171 -0
  169. package/integrations/google-sheet/credentials.json +36 -0
  170. package/integrations/google-sheet/credentials_hint.md +9 -0
  171. package/integrations/google-sheet/handlers/append_values.js +18 -0
  172. package/integrations/google-sheet/handlers/batch_clear_values.js +6 -0
  173. package/integrations/google-sheet/handlers/batch_clear_values_by_data_filter.js +6 -0
  174. package/integrations/google-sheet/handlers/batch_get_values.js +16 -0
  175. package/integrations/google-sheet/handlers/batch_update.js +14 -0
  176. package/integrations/google-sheet/handlers/batch_update_values.js +16 -0
  177. package/integrations/google-sheet/handlers/batch_update_values_by_data_filter.js +16 -0
  178. package/integrations/google-sheet/handlers/clear_values.js +6 -0
  179. package/integrations/google-sheet/handlers/copy_to_spreadsheet.js +6 -0
  180. package/integrations/google-sheet/handlers/create_spreadsheet.js +5 -0
  181. package/integrations/google-sheet/handlers/get_developer_metadata.js +6 -0
  182. package/integrations/google-sheet/handlers/get_spreadsheet.js +12 -0
  183. package/integrations/google-sheet/handlers/get_spreadsheet_by_data_filter.js +10 -0
  184. package/integrations/google-sheet/handlers/get_values.js +14 -0
  185. package/integrations/google-sheet/handlers/get_values_by_data_filter.js +14 -0
  186. package/integrations/google-sheet/handlers/search_developer_metadata.js +7 -0
  187. package/integrations/google-sheet/handlers/update_values.js +16 -0
  188. package/integrations/google-sheet/manifest.json +125 -0
  189. package/integrations/google-sheet/schemas/append_values.json +16 -0
  190. package/integrations/google-sheet/schemas/batch_clear_values.json +10 -0
  191. package/integrations/google-sheet/schemas/batch_clear_values_by_data_filter.json +10 -0
  192. package/integrations/google-sheet/schemas/batch_get_values.json +13 -0
  193. package/integrations/google-sheet/schemas/batch_update.json +13 -0
  194. package/integrations/google-sheet/schemas/batch_update_values.json +25 -0
  195. package/integrations/google-sheet/schemas/batch_update_values_by_data_filter.json +25 -0
  196. package/integrations/google-sheet/schemas/clear_values.json +10 -0
  197. package/integrations/google-sheet/schemas/copy_to_spreadsheet.json +11 -0
  198. package/integrations/google-sheet/schemas/create_spreadsheet.json +11 -0
  199. package/integrations/google-sheet/schemas/get_developer_metadata.json +10 -0
  200. package/integrations/google-sheet/schemas/get_spreadsheet.json +15 -0
  201. package/integrations/google-sheet/schemas/get_spreadsheet_by_data_filter.json +11 -0
  202. package/integrations/google-sheet/schemas/get_values.json +13 -0
  203. package/integrations/google-sheet/schemas/get_values_by_data_filter.json +17 -0
  204. package/integrations/google-sheet/schemas/search_developer_metadata.json +14 -0
  205. package/integrations/google-sheet/schemas/update_values.json +15 -0
  206. package/integrations/google-slides/__tests__/get_handlers.test.ts +69 -0
  207. package/integrations/google-slides/__tests__/usage_parity.test.ts +34 -0
  208. package/integrations/google-slides/__tests__/write_handlers.test.ts +125 -0
  209. package/integrations/google-slides/credentials.json +36 -0
  210. package/integrations/google-slides/credentials_hint.md +9 -0
  211. package/integrations/google-slides/handlers/append_text_to_title_of_first_slide.js +17 -0
  212. package/integrations/google-slides/handlers/batch_update.js +15 -0
  213. package/integrations/google-slides/handlers/create_presentation.js +8 -0
  214. package/integrations/google-slides/handlers/create_slide_after_first_match.js +20 -0
  215. package/integrations/google-slides/handlers/get_page_thumbnail.js +12 -0
  216. package/integrations/google-slides/handlers/get_presentation.js +6 -0
  217. package/integrations/google-slides/handlers/insert_image_after_first_match.js +19 -0
  218. package/integrations/google-slides/handlers/insert_shape_after_first_match.js +21 -0
  219. package/integrations/google-slides/handlers/replace_text_first_match.js +9 -0
  220. package/integrations/google-slides/handlers/set_background_color_for_slide_index.js +15 -0
  221. package/integrations/google-slides/handlers/style_text_first_match.js +48 -0
  222. package/integrations/google-slides/manifest.json +41 -0
  223. package/integrations/google-slides/schemas/append_text_to_title_of_first_slide.json +11 -0
  224. package/integrations/google-slides/schemas/batch_update.json +13 -0
  225. package/integrations/google-slides/schemas/create_presentation.json +8 -0
  226. package/integrations/google-slides/schemas/create_slide_after_first_match.json +11 -0
  227. package/integrations/google-slides/schemas/get_page_thumbnail.json +12 -0
  228. package/integrations/google-slides/schemas/get_presentation.json +9 -0
  229. package/integrations/google-slides/schemas/insert_image_after_first_match.json +13 -0
  230. package/integrations/google-slides/schemas/insert_shape_after_first_match.json +13 -0
  231. package/integrations/google-slides/schemas/replace_text_first_match.json +12 -0
  232. package/integrations/google-slides/schemas/set_background_color_for_slide_index.json +11 -0
  233. package/integrations/google-slides/schemas/style_text_first_match.json +12 -0
  234. package/integrations/new_integration_prompt.md +41 -0
  235. package/integrations/notion/__tests__/get_handlers.test.ts +153 -0
  236. package/integrations/notion/__tests__/usage_parity.test.ts +34 -0
  237. package/integrations/notion/__tests__/write_and_admin_handlers.test.ts +190 -0
  238. package/integrations/notion/credentials.json +21 -0
  239. package/integrations/notion/credentials_hint.md +5 -0
  240. package/integrations/notion/handlers/append_block_children.js +7 -0
  241. package/integrations/notion/handlers/create_comment.js +10 -0
  242. package/integrations/notion/handlers/create_database.js +11 -0
  243. package/integrations/notion/handlers/create_page.js +13 -0
  244. package/integrations/notion/handlers/delete_block.js +8 -0
  245. package/integrations/notion/handlers/get_me.js +4 -0
  246. package/integrations/notion/handlers/list_block_children.js +10 -0
  247. package/integrations/notion/handlers/list_comments.js +14 -0
  248. package/integrations/notion/handlers/list_users.js +10 -0
  249. package/integrations/notion/handlers/query_database.js +10 -0
  250. package/integrations/notion/handlers/retrieve_block.js +4 -0
  251. package/integrations/notion/handlers/retrieve_database.js +4 -0
  252. package/integrations/notion/handlers/retrieve_page.js +4 -0
  253. package/integrations/notion/handlers/retrieve_page_property_item.js +10 -0
  254. package/integrations/notion/handlers/retrieve_user.js +4 -0
  255. package/integrations/notion/handlers/search.js +11 -0
  256. package/integrations/notion/handlers/update_block.js +7 -0
  257. package/integrations/notion/handlers/update_database.js +10 -0
  258. package/integrations/notion/handlers/update_page_properties.js +10 -0
  259. package/integrations/notion/manifest.json +139 -0
  260. package/integrations/notion/prompt.md +26 -0
  261. package/integrations/notion/schemas/append_block_children.json +10 -0
  262. package/integrations/notion/schemas/create_comment.json +18 -0
  263. package/integrations/notion/schemas/create_database.json +18 -0
  264. package/integrations/notion/schemas/create_page.json +22 -0
  265. package/integrations/notion/schemas/delete_block.json +9 -0
  266. package/integrations/notion/schemas/empty.json +6 -0
  267. package/integrations/notion/schemas/id_block.json +9 -0
  268. package/integrations/notion/schemas/id_database.json +9 -0
  269. package/integrations/notion/schemas/id_page.json +9 -0
  270. package/integrations/notion/schemas/id_user.json +9 -0
  271. package/integrations/notion/schemas/list_block_children.json +11 -0
  272. package/integrations/notion/schemas/list_comments.json +15 -0
  273. package/integrations/notion/schemas/list_users.json +9 -0
  274. package/integrations/notion/schemas/query_database.json +13 -0
  275. package/integrations/notion/schemas/retrieve_page_property_item.json +12 -0
  276. package/integrations/notion/schemas/search.json +27 -0
  277. package/integrations/notion/schemas/update_block.json +10 -0
  278. package/integrations/notion/schemas/update_database.json +13 -0
  279. package/integrations/notion/schemas/update_page_properties.json +13 -0
  280. package/integrations/trello/__tests__/get_handlers.test.ts +240 -0
  281. package/integrations/trello/__tests__/usage_parity.test.ts +34 -0
  282. package/integrations/trello/__tests__/write_and_admin_handlers.test.ts +189 -0
  283. package/integrations/trello/credentials.json +26 -0
  284. package/integrations/trello/credentials_hint.md +4 -0
  285. package/integrations/trello/handlers/add_checklist_to_card.js +5 -0
  286. package/integrations/trello/handlers/add_member_to_card.js +5 -0
  287. package/integrations/trello/handlers/archive_list.js +5 -0
  288. package/integrations/trello/handlers/create_card.js +13 -0
  289. package/integrations/trello/handlers/create_list.js +7 -0
  290. package/integrations/trello/handlers/delete_card.js +9 -0
  291. package/integrations/trello/handlers/get_board.js +4 -0
  292. package/integrations/trello/handlers/get_board_cards.js +4 -0
  293. package/integrations/trello/handlers/get_board_custom_fields.js +4 -0
  294. package/integrations/trello/handlers/get_board_labels.js +4 -0
  295. package/integrations/trello/handlers/get_board_lists.js +4 -0
  296. package/integrations/trello/handlers/get_board_members.js +4 -0
  297. package/integrations/trello/handlers/get_board_memberships.js +4 -0
  298. package/integrations/trello/handlers/get_card.js +4 -0
  299. package/integrations/trello/handlers/get_card_actions.js +4 -0
  300. package/integrations/trello/handlers/get_card_attachments.js +4 -0
  301. package/integrations/trello/handlers/get_card_checklists.js +4 -0
  302. package/integrations/trello/handlers/get_card_custom_field_items.js +4 -0
  303. package/integrations/trello/handlers/get_card_members.js +4 -0
  304. package/integrations/trello/handlers/get_list.js +4 -0
  305. package/integrations/trello/handlers/get_list_cards.js +4 -0
  306. package/integrations/trello/handlers/get_member.js +4 -0
  307. package/integrations/trello/handlers/get_member_boards.js +4 -0
  308. package/integrations/trello/handlers/get_member_organizations.js +4 -0
  309. package/integrations/trello/handlers/get_organization.js +4 -0
  310. package/integrations/trello/handlers/get_organization_boards.js +4 -0
  311. package/integrations/trello/handlers/move_card_to_list.js +5 -0
  312. package/integrations/trello/handlers/remove_member_from_card.js +9 -0
  313. package/integrations/trello/handlers/search.js +5 -0
  314. package/integrations/trello/handlers/update_card.js +19 -0
  315. package/integrations/trello/handlers/update_list.js +11 -0
  316. package/integrations/trello/manifest.json +231 -0
  317. package/integrations/trello/schemas/add_checklist_to_card.json +10 -0
  318. package/integrations/trello/schemas/add_member_to_card.json +10 -0
  319. package/integrations/trello/schemas/archive_list.json +9 -0
  320. package/integrations/trello/schemas/create_card.json +13 -0
  321. package/integrations/trello/schemas/create_list.json +11 -0
  322. package/integrations/trello/schemas/delete_card.json +9 -0
  323. package/integrations/trello/schemas/display_trello_cards.json +45 -0
  324. package/integrations/trello/schemas/empty.json +5 -0
  325. package/integrations/trello/schemas/get_member.json +5 -0
  326. package/integrations/trello/schemas/id_board.json +8 -0
  327. package/integrations/trello/schemas/id_card.json +8 -0
  328. package/integrations/trello/schemas/id_list.json +8 -0
  329. package/integrations/trello/schemas/id_org.json +8 -0
  330. package/integrations/trello/schemas/move_card_to_list.json +10 -0
  331. package/integrations/trello/schemas/remove_member_from_card.json +10 -0
  332. package/integrations/trello/schemas/search.json +8 -0
  333. package/integrations/trello/schemas/update_card.json +16 -0
  334. package/integrations/trello/schemas/update_list.json +12 -0
  335. package/package.json +45 -0
@@ -0,0 +1,117 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest'
2
+ import { IntegrationProxy } from '../../../src/integrations/proxy.js'
3
+ import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
4
+
5
+ // LIVE GitHub integration tests using managed OAuth
6
+ // Required env vars:
7
+ // - COMMANDABLE_MANAGED_OAUTH_BASE_URL
8
+ // - COMMANDABLE_MANAGED_OAUTH_SECRET_KEY
9
+ // - GITHUB_TEST_CONNECTION_ID (managed OAuth connection for provider 'github')
10
+
11
+ interface Ctx {
12
+ owner?: string
13
+ repo?: string
14
+ issue_number?: number
15
+ }
16
+
17
+ const env = process.env as Record<string, string>
18
+ const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
19
+ const suite = hasEnv('COMMANDABLE_MANAGED_OAUTH_BASE_URL', 'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY', 'GITHUB_TEST_CONNECTION_ID')
20
+ ? describe
21
+ : describe.skip
22
+
23
+ suite('github read handlers (live)', () => {
24
+ const ctx: Ctx = {}
25
+ let buildHandler: (name: string) => ((input: any) => Promise<any>)
26
+
27
+ beforeAll(async () => {
28
+ const { COMMANDABLE_MANAGED_OAUTH_BASE_URL, COMMANDABLE_MANAGED_OAUTH_SECRET_KEY, GITHUB_TEST_CONNECTION_ID } = env
29
+
30
+ const proxy = new IntegrationProxy({
31
+ managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
32
+ managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
33
+ })
34
+ const integrationNode = { id: 'node-github', type: 'github', label: 'GitHub', connectionId: GITHUB_TEST_CONNECTION_ID } as any
35
+
36
+ const tools = loadIntegrationTools('github')
37
+ expect(tools).toBeTruthy()
38
+
39
+ buildHandler = (name: string) => {
40
+ const tool = tools!.read.find(t => t.name === name)
41
+ expect(tool, `tool ${name} exists`).toBeTruthy()
42
+ const integration = {
43
+ fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init),
44
+ }
45
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
46
+ return build(integration) as (input: any) => Promise<any>
47
+ }
48
+
49
+ // Discover owner/repo/issue for tests
50
+ const list_repos = buildHandler('list_repos')
51
+ const repos = await list_repos({})
52
+ const first = Array.isArray(repos) ? repos[0] : repos?.[0]
53
+ ctx.owner = first?.owner?.login || first?.owner || first?.full_name?.split?.('/')[0]
54
+ ctx.repo = first?.name || first?.full_name?.split?.('/')[1]
55
+
56
+ if (ctx.owner && ctx.repo) {
57
+ const list_issues = buildHandler('list_issues')
58
+ const issues = await list_issues({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
59
+ const firstIssue = Array.isArray(issues) ? issues.find((i: any) => typeof i.number === 'number') : undefined
60
+ ctx.issue_number = firstIssue?.number
61
+ }
62
+ }, 60000)
63
+
64
+ it('list_repos returns repositories', async () => {
65
+ const handler = buildHandler('list_repos')
66
+ const result = await handler({})
67
+ expect(result).toBeTruthy()
68
+ }, 30000)
69
+
70
+ it('get_repo returns repo details', async () => {
71
+ if (!ctx.owner || !ctx.repo)
72
+ return expect(true).toBe(true)
73
+ const handler = buildHandler('get_repo')
74
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
75
+ expect(result?.name?.toLowerCase?.()).toBe(ctx.repo?.toLowerCase?.())
76
+ }, 30000)
77
+
78
+ it('list_issues returns issues for repo', async () => {
79
+ if (!ctx.owner || !ctx.repo)
80
+ return expect(true).toBe(true)
81
+ const handler = buildHandler('list_issues')
82
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
83
+ expect(Array.isArray(result)).toBe(true)
84
+ }, 30000)
85
+
86
+ it('get_issue returns a single issue if available', async () => {
87
+ if (!ctx.owner || !ctx.repo || !ctx.issue_number)
88
+ return expect(true).toBe(true)
89
+ const handler = buildHandler('get_issue')
90
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number })
91
+ expect(result?.number).toBe(ctx.issue_number)
92
+ }, 30000)
93
+
94
+ it('list_pull_requests returns PRs', async () => {
95
+ if (!ctx.owner || !ctx.repo)
96
+ return expect(true).toBe(true)
97
+ const handler = buildHandler('list_pull_requests')
98
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo, state: 'all' })
99
+ expect(Array.isArray(result)).toBe(true)
100
+ }, 30000)
101
+
102
+ it('list_branches returns branches', async () => {
103
+ if (!ctx.owner || !ctx.repo)
104
+ return expect(true).toBe(true)
105
+ const handler = buildHandler('list_branches')
106
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
107
+ expect(Array.isArray(result)).toBe(true)
108
+ }, 30000)
109
+
110
+ it('list_commits returns commits', async () => {
111
+ if (!ctx.owner || !ctx.repo)
112
+ return expect(true).toBe(true)
113
+ const handler = buildHandler('list_commits')
114
+ const result = await handler({ owner: ctx.owner, repo: ctx.repo })
115
+ expect(Array.isArray(result)).toBe(true)
116
+ }, 30000)
117
+ })
@@ -0,0 +1,34 @@
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs'
2
+ import { resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+ import { loadIntegrationManifest } from '../../../src/integrations/dataLoader.js'
6
+
7
+ function escapeRegExp(str: string): string {
8
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
9
+ }
10
+
11
+ describe('github static usage parity', () => {
12
+ it('every manifest tool is referenced in tests via build*(name)', () => {
13
+ const manifest = loadIntegrationManifest('github')!
14
+ const toolNames = (manifest.tools as any[]).map(t => t.name)
15
+
16
+ const testsDir = fileURLToPath(new URL('.', import.meta.url))
17
+ expect(existsSync(testsDir)).toBe(true)
18
+ const testFiles = readdirSync(testsDir)
19
+ .filter(f => /\.test\.(t|j)s$/.test(f) && !f.includes('usage_parity.test'))
20
+ .map(f => resolve(testsDir, f))
21
+
22
+ const fileContents = testFiles.map(f => readFileSync(f, 'utf8'))
23
+
24
+ const missing: string[] = []
25
+ for (const name of toolNames) {
26
+ const nameRe = new RegExp(`build(?:Read|Write|Admin)?(?:Handler)?\\(\\s*['"\`]${escapeRegExp(name)}['"\`]\\s*\\)`, 'm')
27
+ const found = fileContents.some(src => nameRe.test(src))
28
+ if (!found)
29
+ missing.push(name)
30
+ }
31
+
32
+ expect(missing, `Missing handler usages in tests: ${missing.join(', ')}`).toEqual([])
33
+ })
34
+ })
@@ -0,0 +1,311 @@
1
+ import { beforeAll, describe, expect, it } from 'vitest'
2
+ import { IntegrationProxy } from '../../../src/integrations/proxy.js'
3
+ import { loadIntegrationTools } from '../../../src/integrations/dataLoader.js'
4
+
5
+ // LIVE GitHub write tests using managed OAuth
6
+ // Required env vars for write tests:
7
+ // - COMMANDABLE_MANAGED_OAUTH_BASE_URL
8
+ // - COMMANDABLE_MANAGED_OAUTH_SECRET_KEY
9
+ // - GITHUB_TEST_CONNECTION_ID (managed OAuth connection for provider 'github')
10
+ // - GITHUB_TEST_OWNER (owner to use for write tests)
11
+ // - GITHUB_TEST_REPO (repo to use for write tests)
12
+
13
+ interface Ctx {
14
+ owner?: string
15
+ repo?: string
16
+ issue_number?: number
17
+ }
18
+
19
+ const env = process.env as Record<string, string>
20
+ const hasEnv = (...keys: string[]) => keys.every(k => !!env[k] && env[k].trim().length > 0)
21
+ const suite = hasEnv(
22
+ 'COMMANDABLE_MANAGED_OAUTH_BASE_URL',
23
+ 'COMMANDABLE_MANAGED_OAUTH_SECRET_KEY',
24
+ 'GITHUB_TEST_CONNECTION_ID',
25
+ 'GITHUB_TEST_OWNER',
26
+ 'GITHUB_TEST_REPO',
27
+ )
28
+ ? describe
29
+ : describe.skip
30
+
31
+ suite('github write handlers (live)', () => {
32
+ const ctx: Ctx = {}
33
+ let buildWriteHandler: (name: string) => ((input: any) => Promise<any>)
34
+ let buildReadHandler: (name: string) => ((input: any) => Promise<any>)
35
+
36
+ beforeAll(async () => {
37
+ const {
38
+ COMMANDABLE_MANAGED_OAUTH_BASE_URL,
39
+ COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
40
+ GITHUB_TEST_CONNECTION_ID,
41
+ GITHUB_TEST_OWNER,
42
+ GITHUB_TEST_REPO,
43
+ } = env
44
+
45
+ const proxy = new IntegrationProxy({
46
+ managedOAuthBaseUrl: COMMANDABLE_MANAGED_OAUTH_BASE_URL,
47
+ managedOAuthSecretKey: COMMANDABLE_MANAGED_OAUTH_SECRET_KEY,
48
+ })
49
+ const integrationNode = { id: 'node-github', type: 'github', label: 'GitHub', connectionId: GITHUB_TEST_CONNECTION_ID } as any
50
+
51
+ const tools = loadIntegrationTools('github')
52
+ expect(tools).toBeTruthy()
53
+
54
+ buildWriteHandler = (name: string) => {
55
+ const tool = tools!.write.find(t => t.name === name)
56
+ expect(tool, `write tool ${name} exists`).toBeTruthy()
57
+ const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
58
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
59
+ return build(integration) as (input: any) => Promise<any>
60
+ }
61
+
62
+ buildReadHandler = (name: string) => {
63
+ const tool = tools!.read.find(t => t.name === name)
64
+ expect(tool, `read tool ${name} exists`).toBeTruthy()
65
+ const integration = { fetch: (path: string, init?: RequestInit) => proxy.call(integrationNode, path, init) }
66
+ const build = new Function('integration', `return (${tool!.handlerCode});`)
67
+ return build(integration) as (input: any) => Promise<any>
68
+ }
69
+
70
+ ctx.owner = GITHUB_TEST_OWNER
71
+ ctx.repo = GITHUB_TEST_REPO
72
+ }, 60000)
73
+
74
+ it('create_issue -> update_issue -> comment_on_issue -> close_issue roundtrip', async () => {
75
+ if (!ctx.owner || !ctx.repo)
76
+ return expect(true).toBe(true)
77
+
78
+ const titleBase = `CmdTest Issue ${Date.now()}`
79
+
80
+ // Create
81
+ const create_issue = buildWriteHandler('create_issue')
82
+ const created = await create_issue({ owner: ctx.owner, repo: ctx.repo, title: titleBase, body: 'Initial body from test.' })
83
+ expect(created?.number).toBeTruthy()
84
+ ctx.issue_number = created.number
85
+
86
+ // Update
87
+ const update_issue = buildWriteHandler('update_issue')
88
+ const updated = await update_issue({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number, body: 'Updated body from test.' })
89
+ expect(updated?.number).toBe(ctx.issue_number)
90
+
91
+ // Comment
92
+ const comment_on_issue = buildWriteHandler('comment_on_issue')
93
+ const comment = await comment_on_issue({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number, body: 'A comment from test.' })
94
+ expect(comment?.id).toBeTruthy()
95
+
96
+ // Close
97
+ const close_issue = buildWriteHandler('close_issue')
98
+ const closed = await close_issue({ owner: ctx.owner, repo: ctx.repo, issue_number: ctx.issue_number })
99
+ expect(closed?.state).toBe('closed')
100
+ }, 90000)
101
+
102
+ it('create_repo -> delete_repo lifecycle', async () => {
103
+ if (!ctx.owner)
104
+ return expect(true).toBe(true)
105
+
106
+ const repoName = `cmdtest-repo-${Date.now()}`
107
+
108
+ // Create
109
+ const create_repo = buildWriteHandler('create_repo')
110
+ const created = await create_repo({
111
+ name: repoName,
112
+ description: 'Test repo created by integration tests',
113
+ private: true,
114
+ auto_init: true,
115
+ })
116
+ expect(created?.name).toBe(repoName)
117
+ expect(created?.full_name).toBe(`${ctx.owner}/${repoName}`)
118
+
119
+ // Delete
120
+ const delete_repo = buildWriteHandler('delete_repo')
121
+ const deleted = await delete_repo({ owner: ctx.owner, repo: repoName })
122
+ expect(deleted?.success).toBe(true)
123
+ expect(deleted?.status).toBe(204)
124
+ }, 90000)
125
+
126
+ it('create_or_update_file: single file commit', async () => {
127
+ if (!ctx.owner || !ctx.repo)
128
+ return expect(true).toBe(true)
129
+
130
+ const timestamp = Date.now()
131
+ const branchName = `test-single-file-${timestamp}`
132
+
133
+ // Create a new branch
134
+ const create_branch = buildWriteHandler('create_branch')
135
+ const branch = await create_branch({
136
+ owner: ctx.owner,
137
+ repo: ctx.repo,
138
+ branch: branchName,
139
+ })
140
+ expect(branch?.ref).toBe(`refs/heads/${branchName}`)
141
+
142
+ // Create a file using create_or_update_file
143
+ const create_or_update_file = buildWriteHandler('create_or_update_file')
144
+ const file = await create_or_update_file({
145
+ owner: ctx.owner,
146
+ repo: ctx.repo,
147
+ path: `test-single-${timestamp}.txt`,
148
+ message: `Add single test file ${timestamp}`,
149
+ content: `Test content with UTF-8: Hello 世界 🌍\nCreated at ${timestamp}`,
150
+ branch: branchName,
151
+ })
152
+ expect(file?.commit?.message).toBe(`Add single test file ${timestamp}`)
153
+ expect(file?.content?.path).toBe(`test-single-${timestamp}.txt`)
154
+
155
+ // Update the same file
156
+ const updated = await create_or_update_file({
157
+ owner: ctx.owner,
158
+ repo: ctx.repo,
159
+ path: `test-single-${timestamp}.txt`,
160
+ message: `Update test file ${timestamp}`,
161
+ content: `Updated content at ${timestamp}`,
162
+ branch: branchName,
163
+ sha: file.content.sha,
164
+ })
165
+ expect(updated?.commit?.message).toBe(`Update test file ${timestamp}`)
166
+ }, 90000)
167
+
168
+ it('create_commit: multiple files in one commit', async () => {
169
+ if (!ctx.owner || !ctx.repo)
170
+ return expect(true).toBe(true)
171
+
172
+ const timestamp = Date.now()
173
+ const branchName = `test-multi-file-${timestamp}`
174
+
175
+ // Create a new branch
176
+ const create_branch = buildWriteHandler('create_branch')
177
+ const branch = await create_branch({
178
+ owner: ctx.owner,
179
+ repo: ctx.repo,
180
+ branch: branchName,
181
+ })
182
+ expect(branch?.ref).toBe(`refs/heads/${branchName}`)
183
+
184
+ // Create multiple files in one commit using create_commit
185
+ const create_commit = buildWriteHandler('create_commit')
186
+ const commit = await create_commit({
187
+ owner: ctx.owner,
188
+ repo: ctx.repo,
189
+ branch: branchName,
190
+ message: `Add multiple files ${timestamp}`,
191
+ files: [
192
+ {
193
+ path: `multi-test/file1-${timestamp}.txt`,
194
+ content: 'Content of file 1',
195
+ },
196
+ {
197
+ path: `multi-test/file2-${timestamp}.txt`,
198
+ content: 'Content of file 2',
199
+ },
200
+ {
201
+ path: `multi-test/file3-${timestamp}.md`,
202
+ content: '# Test File 3\n\nWith UTF-8: 你好 🚀',
203
+ },
204
+ ],
205
+ })
206
+ expect(commit?.commit?.sha).toBeTruthy()
207
+ expect(commit?.commit?.message).toBe(`Add multiple files ${timestamp}`)
208
+ expect(commit?.files?.length).toBe(3)
209
+
210
+ // Update and delete files in another commit
211
+ const commit2 = await create_commit({
212
+ owner: ctx.owner,
213
+ repo: ctx.repo,
214
+ branch: branchName,
215
+ message: `Update and delete files ${timestamp}`,
216
+ files: [
217
+ {
218
+ path: `multi-test/file1-${timestamp}.txt`,
219
+ content: 'Updated content of file 1',
220
+ },
221
+ {
222
+ path: `multi-test/file2-${timestamp}.txt`,
223
+ // Omit content to delete the file
224
+ },
225
+ {
226
+ path: `multi-test/file4-${timestamp}.txt`,
227
+ content: 'New file 4',
228
+ },
229
+ ],
230
+ })
231
+ expect(commit2?.commit?.sha).toBeTruthy()
232
+ expect(commit2?.commit?.message).toBe(`Update and delete files ${timestamp}`)
233
+ }, 120000)
234
+
235
+ it('full PR workflow: create_branch -> create_commit -> create_pull_request -> merge_pull_request', async () => {
236
+ if (!ctx.owner || !ctx.repo)
237
+ return expect(true).toBe(true)
238
+
239
+ const timestamp = Date.now()
240
+ const branchName = `test-pr-workflow-${timestamp}`
241
+
242
+ // Create a new branch
243
+ const create_branch = buildWriteHandler('create_branch')
244
+ const branch = await create_branch({
245
+ owner: ctx.owner,
246
+ repo: ctx.repo,
247
+ branch: branchName,
248
+ })
249
+ expect(branch?.ref).toBe(`refs/heads/${branchName}`)
250
+
251
+ // Create multiple files using create_commit
252
+ const create_commit = buildWriteHandler('create_commit')
253
+ const commit = await create_commit({
254
+ owner: ctx.owner,
255
+ repo: ctx.repo,
256
+ branch: branchName,
257
+ message: `Add feature files ${timestamp}`,
258
+ files: [
259
+ {
260
+ path: `feature-${timestamp}/index.js`,
261
+ content: 'export default function() { return "Hello"; }',
262
+ },
263
+ {
264
+ path: `feature-${timestamp}/README.md`,
265
+ content: `# Feature ${timestamp}\n\nThis is a test feature.`,
266
+ },
267
+ ],
268
+ })
269
+ expect(commit?.commit?.sha).toBeTruthy()
270
+
271
+ // Create a pull request
272
+ const create_pull_request = buildWriteHandler('create_pull_request')
273
+ const get_repo = buildReadHandler('get_repo')
274
+ const repoDetails = await get_repo({ owner: ctx.owner, repo: ctx.repo })
275
+ const defaultBranch = repoDetails?.default_branch || 'main'
276
+ const pr = await create_pull_request({
277
+ owner: ctx.owner,
278
+ repo: ctx.repo,
279
+ title: `Test PR workflow ${timestamp}`,
280
+ body: 'This PR was created by integration tests to test the full workflow',
281
+ head: branchName,
282
+ base: defaultBranch,
283
+ })
284
+ expect(pr?.number).toBeTruthy()
285
+ const prNumber = pr.number
286
+
287
+ // Add labels to the PR
288
+ const add_labels_to_issue = buildWriteHandler('add_labels_to_issue')
289
+ try {
290
+ await add_labels_to_issue({
291
+ owner: ctx.owner,
292
+ repo: ctx.repo,
293
+ issue_number: prNumber,
294
+ labels: ['test'],
295
+ })
296
+ } catch (e) {
297
+ // Label might not exist, that's ok for this test
298
+ console.log('Label add skipped (label may not exist)')
299
+ }
300
+
301
+ // Merge the pull request
302
+ const merge_pull_request = buildWriteHandler('merge_pull_request')
303
+ const merged = await merge_pull_request({
304
+ owner: ctx.owner,
305
+ repo: ctx.repo,
306
+ pull_number: prNumber,
307
+ merge_method: 'squash',
308
+ })
309
+ expect(merged?.merged).toBe(true)
310
+ }, 150000)
311
+ })
@@ -0,0 +1,20 @@
1
+ {
2
+ "schema": {
3
+ "type": "object",
4
+ "properties": {
5
+ "token": {
6
+ "type": "string",
7
+ "title": "Personal Access Token",
8
+ "description": "GitHub personal access token (classic or fine-grained) with appropriate scopes."
9
+ }
10
+ },
11
+ "required": ["token"],
12
+ "additionalProperties": false
13
+ },
14
+ "injection": {
15
+ "headers": {
16
+ "Authorization": "Bearer {{token}}"
17
+ }
18
+ }
19
+ }
20
+
@@ -0,0 +1,7 @@
1
+ Create a GitHub personal access token and paste it here.
2
+
3
+ - Fine-grained PAT: Settings → Developer settings → Personal access tokens → Fine-grained tokens
4
+ - Classic PAT: Settings → Developer settings → Personal access tokens → Tokens (classic)
5
+
6
+ Minimum scopes depend on the tools you use (repo read/write, issues, pull requests, etc.).
7
+
@@ -0,0 +1,12 @@
1
+ async (input) => {
2
+ const body = {
3
+ labels: input.labels,
4
+ }
5
+
6
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/issues/${input.issue_number}/labels`, {
7
+ method: 'POST',
8
+ body
9
+ })
10
+ return await res.json()
11
+ }
12
+
@@ -0,0 +1,5 @@
1
+ async (input) => {
2
+ const body = { state: 'closed' }
3
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/issues/${input.issue_number}`, { method: 'PATCH', body })
4
+ return await res.json()
5
+ }
@@ -0,0 +1,5 @@
1
+ async (input) => {
2
+ const body = { body: input.body }
3
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/issues/${input.issue_number}/comments`, { method: 'POST', body })
4
+ return await res.json()
5
+ }
@@ -0,0 +1,33 @@
1
+ async (input) => {
2
+ // First, get the SHA of the branch to create from
3
+ let fromRef = input.from_branch || 'main'
4
+
5
+ // Try to get the ref, fallback to master if main doesn't exist
6
+ let refRes
7
+ try {
8
+ refRes = await integration.fetch(`/repos/${input.owner}/${input.repo}/git/refs/heads/${fromRef}`)
9
+ } catch (e) {
10
+ if (fromRef === 'main') {
11
+ fromRef = 'master'
12
+ refRes = await integration.fetch(`/repos/${input.owner}/${input.repo}/git/refs/heads/${fromRef}`)
13
+ } else {
14
+ throw e
15
+ }
16
+ }
17
+
18
+ const refData = await refRes.json()
19
+ const sha = refData.object.sha
20
+
21
+ // Create the new branch
22
+ const body = {
23
+ ref: `refs/heads/${input.branch}`,
24
+ sha: sha,
25
+ }
26
+
27
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/git/refs`, {
28
+ method: 'POST',
29
+ body
30
+ })
31
+ return await res.json()
32
+ }
33
+
@@ -0,0 +1,91 @@
1
+ async (input) => {
2
+ const { owner, repo, branch, message, files } = input
3
+
4
+ // 1. Get the current commit SHA for the branch
5
+ const refRes = await integration.fetch(`/repos/${owner}/${repo}/git/refs/heads/${branch}`)
6
+ const refData = await refRes.json()
7
+ const currentCommitSha = refData.object.sha
8
+
9
+ // 2. Get the current commit to get its tree
10
+ const commitRes = await integration.fetch(`/repos/${owner}/${repo}/git/commits/${currentCommitSha}`)
11
+ const commitData = await commitRes.json()
12
+ const currentTreeSha = commitData.tree.sha
13
+
14
+ // 3. Create blobs for each file with content
15
+ const tree = []
16
+ for (const file of files) {
17
+ if (file.content !== undefined && file.content !== null) {
18
+ // Create a blob for this file
19
+ const contentBase64 = typeof Buffer !== 'undefined'
20
+ ? Buffer.from(file.content).toString('base64')
21
+ : btoa(unescape(encodeURIComponent(file.content)))
22
+
23
+ const blobRes = await integration.fetch(`/repos/${owner}/${repo}/git/blobs`, {
24
+ method: 'POST',
25
+ body: {
26
+ content: contentBase64,
27
+ encoding: 'base64',
28
+ },
29
+ })
30
+ const blobData = await blobRes.json()
31
+
32
+ tree.push({
33
+ path: file.path,
34
+ mode: file.mode || '100644',
35
+ type: 'blob',
36
+ sha: blobData.sha,
37
+ })
38
+ } else {
39
+ // File deletion (null sha means delete)
40
+ tree.push({
41
+ path: file.path,
42
+ mode: '100644',
43
+ type: 'blob',
44
+ sha: null,
45
+ })
46
+ }
47
+ }
48
+
49
+ // 4. Create a new tree
50
+ const treeRes = await integration.fetch(`/repos/${owner}/${repo}/git/trees`, {
51
+ method: 'POST',
52
+ body: {
53
+ base_tree: currentTreeSha,
54
+ tree: tree,
55
+ },
56
+ })
57
+ const treeData = await treeRes.json()
58
+
59
+ // 5. Create the commit
60
+ const newCommitRes = await integration.fetch(`/repos/${owner}/${repo}/git/commits`, {
61
+ method: 'POST',
62
+ body: {
63
+ message: message,
64
+ tree: treeData.sha,
65
+ parents: [currentCommitSha],
66
+ },
67
+ })
68
+ const newCommitData = await newCommitRes.json()
69
+
70
+ // 6. Update the branch reference
71
+ const updateRefRes = await integration.fetch(`/repos/${owner}/${repo}/git/refs/heads/${branch}`, {
72
+ method: 'PATCH',
73
+ body: {
74
+ sha: newCommitData.sha,
75
+ },
76
+ })
77
+ await updateRefRes.json()
78
+
79
+ return {
80
+ commit: {
81
+ sha: newCommitData.sha,
82
+ url: newCommitData.html_url,
83
+ message: newCommitData.message,
84
+ },
85
+ tree: {
86
+ sha: treeData.sha,
87
+ },
88
+ files: files.map(f => ({ path: f.path })),
89
+ }
90
+ }
91
+
@@ -0,0 +1,10 @@
1
+ async (input) => {
2
+ const body = {
3
+ title: input.title,
4
+ body: input.body,
5
+ assignees: input.assignees,
6
+ labels: input.labels,
7
+ }
8
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/issues`, { method: 'POST', body })
9
+ return await res.json()
10
+ }
@@ -0,0 +1,21 @@
1
+ async (input) => {
2
+ // GitHub API expects content to be base64 encoded
3
+ // Use btoa with proper UTF-8 encoding for browser/Node.js compatibility
4
+ const contentBase64 = typeof Buffer !== 'undefined'
5
+ ? Buffer.from(input.content).toString('base64')
6
+ : btoa(unescape(encodeURIComponent(input.content)))
7
+
8
+ const body = {
9
+ message: input.message,
10
+ content: contentBase64,
11
+ branch: input.branch,
12
+ sha: input.sha,
13
+ }
14
+
15
+ const res = await integration.fetch(`/repos/${input.owner}/${input.repo}/contents/${input.path}`, {
16
+ method: 'PUT',
17
+ body
18
+ })
19
+ return await res.json()
20
+ }
21
+