webhookdb 0.1.0

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 (364) hide show
  1. checksums.yaml +7 -0
  2. data/data/messages/layouts/blank.email.liquid +10 -0
  3. data/data/messages/layouts/minimal.email.liquid +28 -0
  4. data/data/messages/layouts/standard.email.liquid +28 -0
  5. data/data/messages/partials/button.liquid +15 -0
  6. data/data/messages/partials/environment_banner.liquid +9 -0
  7. data/data/messages/partials/footer.liquid +22 -0
  8. data/data/messages/partials/greeting.liquid +3 -0
  9. data/data/messages/partials/logo_header.liquid +18 -0
  10. data/data/messages/partials/signoff.liquid +1 -0
  11. data/data/messages/styles/v1.liquid +346 -0
  12. data/data/messages/templates/errors/icalendar_fetch.email.liquid +29 -0
  13. data/data/messages/templates/invite.email.liquid +15 -0
  14. data/data/messages/templates/new_customer.email.liquid +24 -0
  15. data/data/messages/templates/org_database_migration_finished.email.liquid +7 -0
  16. data/data/messages/templates/org_database_migration_started.email.liquid +9 -0
  17. data/data/messages/templates/specs/_field_partial.liquid +1 -0
  18. data/data/messages/templates/specs/basic.email.liquid +2 -0
  19. data/data/messages/templates/specs/basic.fake.liquid +1 -0
  20. data/data/messages/templates/specs/with_field.email.liquid +2 -0
  21. data/data/messages/templates/specs/with_field.fake.liquid +1 -0
  22. data/data/messages/templates/specs/with_include.email.liquid +2 -0
  23. data/data/messages/templates/specs/with_partial.email.liquid +1 -0
  24. data/data/messages/templates/verification.email.liquid +14 -0
  25. data/data/messages/templates/verification.sms.liquid +1 -0
  26. data/data/messages/web/install-customer-login.liquid +48 -0
  27. data/data/messages/web/install-error.liquid +17 -0
  28. data/data/messages/web/install-success.liquid +35 -0
  29. data/data/messages/web/install.liquid +20 -0
  30. data/data/messages/web/partials/footer.liquid +4 -0
  31. data/data/messages/web/partials/form_error.liquid +1 -0
  32. data/data/messages/web/partials/header.liquid +3 -0
  33. data/data/messages/web/styles.liquid +134 -0
  34. data/data/windows_tz.txt +461 -0
  35. data/db/migrations/001_testing_pixies.rb +13 -0
  36. data/db/migrations/002_initial.rb +132 -0
  37. data/db/migrations/003_ux_overhaul.rb +20 -0
  38. data/db/migrations/004_incremental_backfill.rb +9 -0
  39. data/db/migrations/005_log_webhooks.rb +24 -0
  40. data/db/migrations/006_generalize_roles.rb +29 -0
  41. data/db/migrations/007_org_dns.rb +12 -0
  42. data/db/migrations/008_webhook_subscriptions.rb +19 -0
  43. data/db/migrations/009_nonunique_stripe_subscription_customer.rb +16 -0
  44. data/db/migrations/010_drop_integration_soft_delete.rb +14 -0
  45. data/db/migrations/011_webhook_subscriptions_created_at.rb +10 -0
  46. data/db/migrations/012_webhook_subscriptions_created_by.rb +9 -0
  47. data/db/migrations/013_default_org_membership.rb +30 -0
  48. data/db/migrations/014_webhook_subscription_deliveries.rb +26 -0
  49. data/db/migrations/015_dependent_integrations.rb +9 -0
  50. data/db/migrations/016_encrypted_columns.rb +9 -0
  51. data/db/migrations/017_skip_verification.rb +9 -0
  52. data/db/migrations/018_sync_targets.rb +25 -0
  53. data/db/migrations/019_org_schema.rb +9 -0
  54. data/db/migrations/020_org_database_migrations.rb +25 -0
  55. data/db/migrations/021_no_default_org_schema.rb +14 -0
  56. data/db/migrations/022_database_document.rb +15 -0
  57. data/db/migrations/023_sync_target_schema.rb +9 -0
  58. data/db/migrations/024_org_semaphore_jobs.rb +9 -0
  59. data/db/migrations/025_integration_backfill_cursor.rb +9 -0
  60. data/db/migrations/026_undo_integration_backfill_cursor.rb +9 -0
  61. data/db/migrations/027_sync_target_http_sync.rb +12 -0
  62. data/db/migrations/028_logged_webhook_path.rb +24 -0
  63. data/db/migrations/029_encrypt_columns.rb +97 -0
  64. data/db/migrations/030_org_sync_target_timeout.rb +9 -0
  65. data/db/migrations/031_org_max_query_rows.rb +9 -0
  66. data/db/migrations/032_remove_db_defaults.rb +12 -0
  67. data/db/migrations/033_backfill_jobs.rb +26 -0
  68. data/db/migrations/034_backfill_job_criteria.rb +9 -0
  69. data/db/migrations/035_synchronous_backfill.rb +9 -0
  70. data/db/migrations/036_oauth.rb +26 -0
  71. data/db/migrations/037_oauth_used.rb +9 -0
  72. data/lib/amigo/durable_job.rb +416 -0
  73. data/lib/pry/clipboard.rb +111 -0
  74. data/lib/sequel/advisory_lock.rb +65 -0
  75. data/lib/webhookdb/admin.rb +4 -0
  76. data/lib/webhookdb/admin_api/auth.rb +36 -0
  77. data/lib/webhookdb/admin_api/customers.rb +63 -0
  78. data/lib/webhookdb/admin_api/database_documents.rb +20 -0
  79. data/lib/webhookdb/admin_api/entities.rb +66 -0
  80. data/lib/webhookdb/admin_api/message_deliveries.rb +61 -0
  81. data/lib/webhookdb/admin_api/roles.rb +15 -0
  82. data/lib/webhookdb/admin_api.rb +34 -0
  83. data/lib/webhookdb/aggregate_result.rb +63 -0
  84. data/lib/webhookdb/api/auth.rb +122 -0
  85. data/lib/webhookdb/api/connstr_auth.rb +36 -0
  86. data/lib/webhookdb/api/db.rb +188 -0
  87. data/lib/webhookdb/api/demo.rb +14 -0
  88. data/lib/webhookdb/api/entities.rb +198 -0
  89. data/lib/webhookdb/api/helpers.rb +253 -0
  90. data/lib/webhookdb/api/install.rb +296 -0
  91. data/lib/webhookdb/api/me.rb +53 -0
  92. data/lib/webhookdb/api/organizations.rb +254 -0
  93. data/lib/webhookdb/api/replay.rb +64 -0
  94. data/lib/webhookdb/api/service_integrations.rb +402 -0
  95. data/lib/webhookdb/api/services.rb +27 -0
  96. data/lib/webhookdb/api/stripe.rb +22 -0
  97. data/lib/webhookdb/api/subscriptions.rb +67 -0
  98. data/lib/webhookdb/api/sync_targets.rb +232 -0
  99. data/lib/webhookdb/api/system.rb +37 -0
  100. data/lib/webhookdb/api/webhook_subscriptions.rb +96 -0
  101. data/lib/webhookdb/api.rb +92 -0
  102. data/lib/webhookdb/apps.rb +93 -0
  103. data/lib/webhookdb/async/audit_logger.rb +38 -0
  104. data/lib/webhookdb/async/autoscaler.rb +84 -0
  105. data/lib/webhookdb/async/job.rb +18 -0
  106. data/lib/webhookdb/async/job_logger.rb +45 -0
  107. data/lib/webhookdb/async/scheduled_job.rb +18 -0
  108. data/lib/webhookdb/async.rb +142 -0
  109. data/lib/webhookdb/aws.rb +98 -0
  110. data/lib/webhookdb/backfill_job.rb +107 -0
  111. data/lib/webhookdb/backfiller.rb +107 -0
  112. data/lib/webhookdb/cloudflare.rb +39 -0
  113. data/lib/webhookdb/connection_cache.rb +177 -0
  114. data/lib/webhookdb/console.rb +71 -0
  115. data/lib/webhookdb/convertkit.rb +14 -0
  116. data/lib/webhookdb/crypto.rb +66 -0
  117. data/lib/webhookdb/customer/reset_code.rb +94 -0
  118. data/lib/webhookdb/customer.rb +347 -0
  119. data/lib/webhookdb/database_document.rb +72 -0
  120. data/lib/webhookdb/db_adapter/column_types.rb +37 -0
  121. data/lib/webhookdb/db_adapter/default_sql.rb +187 -0
  122. data/lib/webhookdb/db_adapter/pg.rb +96 -0
  123. data/lib/webhookdb/db_adapter/snowflake.rb +137 -0
  124. data/lib/webhookdb/db_adapter.rb +208 -0
  125. data/lib/webhookdb/dbutil.rb +92 -0
  126. data/lib/webhookdb/demo_mode.rb +100 -0
  127. data/lib/webhookdb/developer_alert.rb +51 -0
  128. data/lib/webhookdb/email_octopus.rb +21 -0
  129. data/lib/webhookdb/enumerable.rb +18 -0
  130. data/lib/webhookdb/fixtures/backfill_jobs.rb +72 -0
  131. data/lib/webhookdb/fixtures/customers.rb +65 -0
  132. data/lib/webhookdb/fixtures/database_documents.rb +27 -0
  133. data/lib/webhookdb/fixtures/faker.rb +41 -0
  134. data/lib/webhookdb/fixtures/logged_webhooks.rb +56 -0
  135. data/lib/webhookdb/fixtures/message_deliveries.rb +59 -0
  136. data/lib/webhookdb/fixtures/oauth_sessions.rb +24 -0
  137. data/lib/webhookdb/fixtures/organization_database_migrations.rb +37 -0
  138. data/lib/webhookdb/fixtures/organization_memberships.rb +54 -0
  139. data/lib/webhookdb/fixtures/organizations.rb +32 -0
  140. data/lib/webhookdb/fixtures/reset_codes.rb +23 -0
  141. data/lib/webhookdb/fixtures/service_integrations.rb +42 -0
  142. data/lib/webhookdb/fixtures/subscriptions.rb +33 -0
  143. data/lib/webhookdb/fixtures/sync_targets.rb +32 -0
  144. data/lib/webhookdb/fixtures/webhook_subscriptions.rb +35 -0
  145. data/lib/webhookdb/fixtures.rb +15 -0
  146. data/lib/webhookdb/formatting.rb +56 -0
  147. data/lib/webhookdb/front.rb +49 -0
  148. data/lib/webhookdb/github.rb +22 -0
  149. data/lib/webhookdb/google_calendar.rb +29 -0
  150. data/lib/webhookdb/heroku.rb +21 -0
  151. data/lib/webhookdb/http.rb +114 -0
  152. data/lib/webhookdb/icalendar.rb +17 -0
  153. data/lib/webhookdb/id.rb +17 -0
  154. data/lib/webhookdb/idempotency.rb +90 -0
  155. data/lib/webhookdb/increase.rb +42 -0
  156. data/lib/webhookdb/intercom.rb +23 -0
  157. data/lib/webhookdb/jobs/amigo_test_jobs.rb +118 -0
  158. data/lib/webhookdb/jobs/backfill.rb +32 -0
  159. data/lib/webhookdb/jobs/create_mirror_table.rb +18 -0
  160. data/lib/webhookdb/jobs/create_stripe_customer.rb +17 -0
  161. data/lib/webhookdb/jobs/customer_created_notify_internal.rb +22 -0
  162. data/lib/webhookdb/jobs/demo_mode_sync_data.rb +19 -0
  163. data/lib/webhookdb/jobs/deprecated_jobs.rb +19 -0
  164. data/lib/webhookdb/jobs/developer_alert_handle.rb +14 -0
  165. data/lib/webhookdb/jobs/durable_job_recheck_poller.rb +17 -0
  166. data/lib/webhookdb/jobs/emailer.rb +15 -0
  167. data/lib/webhookdb/jobs/icalendar_enqueue_syncs.rb +25 -0
  168. data/lib/webhookdb/jobs/icalendar_sync.rb +23 -0
  169. data/lib/webhookdb/jobs/logged_webhook_replay.rb +17 -0
  170. data/lib/webhookdb/jobs/logged_webhook_resilient_replay.rb +15 -0
  171. data/lib/webhookdb/jobs/message_dispatched.rb +16 -0
  172. data/lib/webhookdb/jobs/organization_database_migration_notify_finished.rb +21 -0
  173. data/lib/webhookdb/jobs/organization_database_migration_notify_started.rb +21 -0
  174. data/lib/webhookdb/jobs/organization_database_migration_run.rb +24 -0
  175. data/lib/webhookdb/jobs/prepare_database_connections.rb +22 -0
  176. data/lib/webhookdb/jobs/process_webhook.rb +47 -0
  177. data/lib/webhookdb/jobs/renew_watch_channel.rb +24 -0
  178. data/lib/webhookdb/jobs/replication_migration.rb +24 -0
  179. data/lib/webhookdb/jobs/reset_code_create_dispatch.rb +23 -0
  180. data/lib/webhookdb/jobs/scheduled_backfills.rb +77 -0
  181. data/lib/webhookdb/jobs/send_invite.rb +15 -0
  182. data/lib/webhookdb/jobs/send_test_webhook.rb +25 -0
  183. data/lib/webhookdb/jobs/send_webhook.rb +20 -0
  184. data/lib/webhookdb/jobs/sync_target_enqueue_scheduled.rb +16 -0
  185. data/lib/webhookdb/jobs/sync_target_run_sync.rb +38 -0
  186. data/lib/webhookdb/jobs/trim_logged_webhooks.rb +15 -0
  187. data/lib/webhookdb/jobs/webhook_resource_notify_integrations.rb +30 -0
  188. data/lib/webhookdb/jobs/webhook_subscription_delivery_attempt.rb +29 -0
  189. data/lib/webhookdb/jobs.rb +4 -0
  190. data/lib/webhookdb/json.rb +113 -0
  191. data/lib/webhookdb/liquid/expose.rb +27 -0
  192. data/lib/webhookdb/liquid/filters.rb +16 -0
  193. data/lib/webhookdb/liquid/liquification.rb +26 -0
  194. data/lib/webhookdb/liquid/partial.rb +12 -0
  195. data/lib/webhookdb/logged_webhook/resilient.rb +95 -0
  196. data/lib/webhookdb/logged_webhook.rb +194 -0
  197. data/lib/webhookdb/message/body.rb +25 -0
  198. data/lib/webhookdb/message/delivery.rb +127 -0
  199. data/lib/webhookdb/message/email_transport.rb +133 -0
  200. data/lib/webhookdb/message/fake_transport.rb +54 -0
  201. data/lib/webhookdb/message/liquid_drops.rb +29 -0
  202. data/lib/webhookdb/message/template.rb +89 -0
  203. data/lib/webhookdb/message/transport.rb +43 -0
  204. data/lib/webhookdb/message.rb +150 -0
  205. data/lib/webhookdb/messages/error_icalendar_fetch.rb +42 -0
  206. data/lib/webhookdb/messages/invite.rb +23 -0
  207. data/lib/webhookdb/messages/new_customer.rb +14 -0
  208. data/lib/webhookdb/messages/org_database_migration_finished.rb +23 -0
  209. data/lib/webhookdb/messages/org_database_migration_started.rb +24 -0
  210. data/lib/webhookdb/messages/specs.rb +57 -0
  211. data/lib/webhookdb/messages/verification.rb +23 -0
  212. data/lib/webhookdb/method_utilities.rb +82 -0
  213. data/lib/webhookdb/microsoft_calendar.rb +36 -0
  214. data/lib/webhookdb/nextpax.rb +14 -0
  215. data/lib/webhookdb/oauth/front.rb +58 -0
  216. data/lib/webhookdb/oauth/intercom.rb +58 -0
  217. data/lib/webhookdb/oauth/session.rb +24 -0
  218. data/lib/webhookdb/oauth.rb +80 -0
  219. data/lib/webhookdb/organization/alerting.rb +35 -0
  220. data/lib/webhookdb/organization/database_migration.rb +151 -0
  221. data/lib/webhookdb/organization/db_builder.rb +429 -0
  222. data/lib/webhookdb/organization.rb +506 -0
  223. data/lib/webhookdb/organization_membership.rb +58 -0
  224. data/lib/webhookdb/phone_number.rb +38 -0
  225. data/lib/webhookdb/plaid.rb +23 -0
  226. data/lib/webhookdb/platform.rb +27 -0
  227. data/lib/webhookdb/plivo.rb +52 -0
  228. data/lib/webhookdb/postgres/maintenance.rb +166 -0
  229. data/lib/webhookdb/postgres/model.rb +82 -0
  230. data/lib/webhookdb/postgres/model_utilities.rb +382 -0
  231. data/lib/webhookdb/postgres/testing_pixie.rb +16 -0
  232. data/lib/webhookdb/postgres/validations.rb +46 -0
  233. data/lib/webhookdb/postgres.rb +176 -0
  234. data/lib/webhookdb/postmark.rb +20 -0
  235. data/lib/webhookdb/redis.rb +35 -0
  236. data/lib/webhookdb/replicator/atom_single_feed_v1.rb +116 -0
  237. data/lib/webhookdb/replicator/aws_pricing_v1.rb +488 -0
  238. data/lib/webhookdb/replicator/base.rb +1185 -0
  239. data/lib/webhookdb/replicator/column.rb +482 -0
  240. data/lib/webhookdb/replicator/convertkit_broadcast_v1.rb +69 -0
  241. data/lib/webhookdb/replicator/convertkit_subscriber_v1.rb +200 -0
  242. data/lib/webhookdb/replicator/convertkit_tag_v1.rb +66 -0
  243. data/lib/webhookdb/replicator/convertkit_v1_mixin.rb +65 -0
  244. data/lib/webhookdb/replicator/docgen.rb +167 -0
  245. data/lib/webhookdb/replicator/email_octopus_campaign_v1.rb +84 -0
  246. data/lib/webhookdb/replicator/email_octopus_contact_v1.rb +159 -0
  247. data/lib/webhookdb/replicator/email_octopus_event_v1.rb +244 -0
  248. data/lib/webhookdb/replicator/email_octopus_list_v1.rb +101 -0
  249. data/lib/webhookdb/replicator/fake.rb +453 -0
  250. data/lib/webhookdb/replicator/front_conversation_v1.rb +45 -0
  251. data/lib/webhookdb/replicator/front_marketplace_root_v1.rb +55 -0
  252. data/lib/webhookdb/replicator/front_message_v1.rb +45 -0
  253. data/lib/webhookdb/replicator/front_v1_mixin.rb +22 -0
  254. data/lib/webhookdb/replicator/github_issue_comment_v1.rb +58 -0
  255. data/lib/webhookdb/replicator/github_issue_v1.rb +83 -0
  256. data/lib/webhookdb/replicator/github_pull_v1.rb +84 -0
  257. data/lib/webhookdb/replicator/github_release_v1.rb +47 -0
  258. data/lib/webhookdb/replicator/github_repo_v1_mixin.rb +250 -0
  259. data/lib/webhookdb/replicator/github_repository_event_v1.rb +45 -0
  260. data/lib/webhookdb/replicator/icalendar_calendar_v1.rb +465 -0
  261. data/lib/webhookdb/replicator/icalendar_event_v1.rb +334 -0
  262. data/lib/webhookdb/replicator/increase_account_number_v1.rb +77 -0
  263. data/lib/webhookdb/replicator/increase_account_transfer_v1.rb +61 -0
  264. data/lib/webhookdb/replicator/increase_account_v1.rb +63 -0
  265. data/lib/webhookdb/replicator/increase_ach_transfer_v1.rb +78 -0
  266. data/lib/webhookdb/replicator/increase_check_transfer_v1.rb +64 -0
  267. data/lib/webhookdb/replicator/increase_limit_v1.rb +78 -0
  268. data/lib/webhookdb/replicator/increase_transaction_v1.rb +74 -0
  269. data/lib/webhookdb/replicator/increase_v1_mixin.rb +121 -0
  270. data/lib/webhookdb/replicator/increase_wire_transfer_v1.rb +61 -0
  271. data/lib/webhookdb/replicator/intercom_contact_v1.rb +36 -0
  272. data/lib/webhookdb/replicator/intercom_conversation_v1.rb +38 -0
  273. data/lib/webhookdb/replicator/intercom_marketplace_root_v1.rb +69 -0
  274. data/lib/webhookdb/replicator/intercom_v1_mixin.rb +105 -0
  275. data/lib/webhookdb/replicator/oauth_refresh_access_token_mixin.rb +65 -0
  276. data/lib/webhookdb/replicator/plivo_sms_inbound_v1.rb +102 -0
  277. data/lib/webhookdb/replicator/postmark_inbound_message_v1.rb +94 -0
  278. data/lib/webhookdb/replicator/postmark_outbound_message_event_v1.rb +107 -0
  279. data/lib/webhookdb/replicator/schema_modification.rb +42 -0
  280. data/lib/webhookdb/replicator/shopify_customer_v1.rb +58 -0
  281. data/lib/webhookdb/replicator/shopify_order_v1.rb +64 -0
  282. data/lib/webhookdb/replicator/shopify_v1_mixin.rb +161 -0
  283. data/lib/webhookdb/replicator/signalwire_message_v1.rb +169 -0
  284. data/lib/webhookdb/replicator/sponsy_customer_v1.rb +54 -0
  285. data/lib/webhookdb/replicator/sponsy_placement_v1.rb +34 -0
  286. data/lib/webhookdb/replicator/sponsy_publication_v1.rb +125 -0
  287. data/lib/webhookdb/replicator/sponsy_slot_v1.rb +41 -0
  288. data/lib/webhookdb/replicator/sponsy_status_v1.rb +35 -0
  289. data/lib/webhookdb/replicator/sponsy_v1_mixin.rb +165 -0
  290. data/lib/webhookdb/replicator/state_machine_step.rb +69 -0
  291. data/lib/webhookdb/replicator/stripe_charge_v1.rb +77 -0
  292. data/lib/webhookdb/replicator/stripe_coupon_v1.rb +62 -0
  293. data/lib/webhookdb/replicator/stripe_customer_v1.rb +60 -0
  294. data/lib/webhookdb/replicator/stripe_dispute_v1.rb +77 -0
  295. data/lib/webhookdb/replicator/stripe_invoice_item_v1.rb +82 -0
  296. data/lib/webhookdb/replicator/stripe_invoice_v1.rb +116 -0
  297. data/lib/webhookdb/replicator/stripe_payout_v1.rb +67 -0
  298. data/lib/webhookdb/replicator/stripe_price_v1.rb +60 -0
  299. data/lib/webhookdb/replicator/stripe_product_v1.rb +60 -0
  300. data/lib/webhookdb/replicator/stripe_refund_v1.rb +101 -0
  301. data/lib/webhookdb/replicator/stripe_subscription_item_v1.rb +56 -0
  302. data/lib/webhookdb/replicator/stripe_subscription_v1.rb +75 -0
  303. data/lib/webhookdb/replicator/stripe_v1_mixin.rb +116 -0
  304. data/lib/webhookdb/replicator/transistor_episode_stats_v1.rb +141 -0
  305. data/lib/webhookdb/replicator/transistor_episode_v1.rb +169 -0
  306. data/lib/webhookdb/replicator/transistor_show_v1.rb +68 -0
  307. data/lib/webhookdb/replicator/transistor_v1_mixin.rb +65 -0
  308. data/lib/webhookdb/replicator/twilio_sms_v1.rb +156 -0
  309. data/lib/webhookdb/replicator/webhook_request.rb +5 -0
  310. data/lib/webhookdb/replicator/webhookdb_customer_v1.rb +74 -0
  311. data/lib/webhookdb/replicator.rb +224 -0
  312. data/lib/webhookdb/role.rb +42 -0
  313. data/lib/webhookdb/sentry.rb +35 -0
  314. data/lib/webhookdb/service/auth.rb +138 -0
  315. data/lib/webhookdb/service/collection.rb +91 -0
  316. data/lib/webhookdb/service/entities.rb +97 -0
  317. data/lib/webhookdb/service/helpers.rb +270 -0
  318. data/lib/webhookdb/service/middleware.rb +124 -0
  319. data/lib/webhookdb/service/types.rb +30 -0
  320. data/lib/webhookdb/service/validators.rb +32 -0
  321. data/lib/webhookdb/service/view_api.rb +63 -0
  322. data/lib/webhookdb/service.rb +219 -0
  323. data/lib/webhookdb/service_integration.rb +332 -0
  324. data/lib/webhookdb/shopify.rb +35 -0
  325. data/lib/webhookdb/signalwire.rb +13 -0
  326. data/lib/webhookdb/slack.rb +68 -0
  327. data/lib/webhookdb/snowflake.rb +90 -0
  328. data/lib/webhookdb/spec_helpers/async.rb +122 -0
  329. data/lib/webhookdb/spec_helpers/citest.rb +88 -0
  330. data/lib/webhookdb/spec_helpers/integration.rb +121 -0
  331. data/lib/webhookdb/spec_helpers/message.rb +41 -0
  332. data/lib/webhookdb/spec_helpers/postgres.rb +220 -0
  333. data/lib/webhookdb/spec_helpers/service.rb +432 -0
  334. data/lib/webhookdb/spec_helpers/shared_examples_for_columns.rb +56 -0
  335. data/lib/webhookdb/spec_helpers/shared_examples_for_replicators.rb +915 -0
  336. data/lib/webhookdb/spec_helpers/whdb.rb +139 -0
  337. data/lib/webhookdb/spec_helpers.rb +63 -0
  338. data/lib/webhookdb/sponsy.rb +14 -0
  339. data/lib/webhookdb/stripe.rb +37 -0
  340. data/lib/webhookdb/subscription.rb +203 -0
  341. data/lib/webhookdb/sync_target.rb +491 -0
  342. data/lib/webhookdb/tasks/admin.rb +49 -0
  343. data/lib/webhookdb/tasks/annotate.rb +36 -0
  344. data/lib/webhookdb/tasks/db.rb +82 -0
  345. data/lib/webhookdb/tasks/docs.rb +42 -0
  346. data/lib/webhookdb/tasks/fixture.rb +35 -0
  347. data/lib/webhookdb/tasks/message.rb +50 -0
  348. data/lib/webhookdb/tasks/regress.rb +87 -0
  349. data/lib/webhookdb/tasks/release.rb +27 -0
  350. data/lib/webhookdb/tasks/sidekiq.rb +23 -0
  351. data/lib/webhookdb/tasks/specs.rb +64 -0
  352. data/lib/webhookdb/theranest.rb +15 -0
  353. data/lib/webhookdb/transistor.rb +13 -0
  354. data/lib/webhookdb/twilio.rb +13 -0
  355. data/lib/webhookdb/typed_struct.rb +44 -0
  356. data/lib/webhookdb/version.rb +5 -0
  357. data/lib/webhookdb/webhook_response.rb +50 -0
  358. data/lib/webhookdb/webhook_subscription/delivery.rb +82 -0
  359. data/lib/webhookdb/webhook_subscription.rb +226 -0
  360. data/lib/webhookdb/windows_tz.rb +32 -0
  361. data/lib/webhookdb/xml.rb +92 -0
  362. data/lib/webhookdb.rb +224 -0
  363. data/lib/webterm/apps.rb +45 -0
  364. metadata +1129 -0
@@ -0,0 +1,453 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Webhookdb::Replicator::Fake < Webhookdb::Replicator::Base
4
+ extend Webhookdb::MethodUtilities
5
+
6
+ singleton_attr_accessor :webhook_response
7
+ singleton_attr_accessor :upsert_has_deps
8
+ singleton_attr_accessor :resource_and_event_hook
9
+ singleton_attr_accessor :dispatch_request_to_hook
10
+ singleton_attr_accessor :process_webhooks_synchronously
11
+ singleton_attr_accessor :obfuscate_headers_for_logging
12
+ singleton_attr_accessor :requires_sequence
13
+
14
+ def self.descriptor
15
+ return Webhookdb::Replicator::Descriptor.new(
16
+ name: "fake_v1",
17
+ ctor: ->(sint) { Webhookdb::Replicator::Fake.new(sint) },
18
+ feature_roles: ["internal"],
19
+ resource_name_singular: "Fake",
20
+ supports_webhooks: true,
21
+ supports_backfill: true,
22
+ )
23
+ end
24
+
25
+ def self.reset
26
+ self.webhook_response = Webhookdb::WebhookResponse.ok
27
+ self.upsert_has_deps = false
28
+ self.resource_and_event_hook = nil
29
+ self.dispatch_request_to_hook = nil
30
+ self.process_webhooks_synchronously = nil
31
+ self.obfuscate_headers_for_logging = []
32
+ self.requires_sequence = false
33
+ end
34
+
35
+ def self.stub_backfill_request(items, status: 200)
36
+ return WebMock::API.stub_request(:get, "https://fake-integration/?token=").
37
+ to_return(status:, body: [items, nil].to_json, headers: {"Content-Type" => "application/json"})
38
+ end
39
+
40
+ def process_webhooks_synchronously?
41
+ return self.class.process_webhooks_synchronously ? true : false
42
+ end
43
+
44
+ def preprocess_headers_for_logging(headers)
45
+ self.class.obfuscate_headers_for_logging.each { |h| headers[h] = "***" }
46
+ end
47
+
48
+ def synchronous_processing_response_body(**)
49
+ return super unless self.process_webhooks_synchronously?
50
+ return self.class.process_webhooks_synchronously
51
+ end
52
+
53
+ def calculate_webhook_state_machine
54
+ step = Webhookdb::Replicator::StateMachineStep.new
55
+ # if the service integration doesn't exist, create it with some standard values
56
+ unless self.service_integration.webhook_secret.present?
57
+ step.output = "You're creating a fake_v1 service integration."
58
+ return step.prompting("fake API secret").webhook_secret(self.service_integration)
59
+ end
60
+
61
+ step.output = "The integration creation flow is working correctly. Here is " \
62
+ "the integration's opaque id, which you'll need to enter in a second: " \
63
+ "#{self.service_integration.opaque_id}"
64
+ return step.completed
65
+ end
66
+
67
+ def calculate_backfill_state_machine
68
+ step = Webhookdb::Replicator::StateMachineStep.new
69
+ # if the service integration doesn't exist, create it with some standard values
70
+ unless self.service_integration.backfill_secret.present?
71
+ step.needs_input = true
72
+ step.output = "Now let's test the backfill flow."
73
+ step.prompt = "Paste or type a string here:"
74
+ step.prompt_is_secret = false
75
+ step.post_to_url = self.service_integration.unauthed_webhook_path + "/transition/backfill_secret"
76
+ step.complete = false
77
+ return step
78
+ end
79
+
80
+ step.needs_input = false
81
+ step.output = "The backfill flow is working correctly."
82
+ step.complete = true
83
+ return step
84
+ end
85
+
86
+ def _webhook_response(_request)
87
+ r = self.class.webhook_response
88
+ raise r if r.is_a?(Exception)
89
+ return r
90
+ end
91
+
92
+ def _remote_key_column
93
+ return Webhookdb::Replicator::Column.new(:my_id, TEXT)
94
+ end
95
+
96
+ def _denormalized_columns
97
+ return [
98
+ Webhookdb::Replicator::Column.new(
99
+ :at,
100
+ TIMESTAMP,
101
+ index: true,
102
+ converter: Webhookdb::Replicator::Column::CONV_PARSE_TIME,
103
+ ),
104
+ ]
105
+ end
106
+
107
+ def _timestamp_column_name
108
+ return :at
109
+ end
110
+
111
+ def _resource_and_event(request)
112
+ body = request.body
113
+ return self.class.resource_and_event_hook.call(body) if self.class.resource_and_event_hook
114
+ return body, nil
115
+ end
116
+
117
+ def _update_where_expr
118
+ return Sequel[self.qualified_table_sequel_identifier][:at] < Sequel[:excluded][:at]
119
+ end
120
+
121
+ def requires_sequence?
122
+ return self.class.requires_sequence
123
+ end
124
+
125
+ def dispatch_request_to(request)
126
+ return self.class.dispatch_request_to_hook.call(request) if self.class.dispatch_request_to_hook
127
+ return super
128
+ end
129
+
130
+ def _fetch_backfill_page(pagination_token, **_kwargs)
131
+ r = Webhookdb::Http.get("https://fake-integration?token=#{pagination_token}", logger: nil, timeout: 30)
132
+ raise "Expected 2-item array" unless r.parsed_response.is_a?(Array) && r.parsed_response.length == 2
133
+ return r.parsed_response
134
+ end
135
+
136
+ def upsert_has_deps?
137
+ return self.class.upsert_has_deps
138
+ end
139
+ end
140
+
141
+ class Webhookdb::Replicator::FakeWithEnrichments < Webhookdb::Replicator::Fake
142
+ def self.descriptor
143
+ return Webhookdb::Replicator::Descriptor.new(
144
+ name: "fake_with_enrichments_v1",
145
+ ctor: ->(sint) { Webhookdb::Replicator::FakeWithEnrichments.new(sint) },
146
+ feature_roles: ["internal"],
147
+ resource_name_singular: "Enriched Fake",
148
+ supports_webhooks: true,
149
+ supports_backfill: true,
150
+ )
151
+ end
152
+
153
+ def _denormalized_columns
154
+ return super << Webhookdb::Replicator::Column.new(:extra, TEXT, from_enrichment: true)
155
+ end
156
+
157
+ def _store_enrichment_body?
158
+ return true
159
+ end
160
+
161
+ def _fetch_enrichment(resource, _event, _request)
162
+ r = Webhookdb::Http.get("https://fake-integration/enrichment/" + resource["my_id"], logger: nil, timeout: 30)
163
+ return r.parsed_response
164
+ end
165
+ end
166
+
167
+ class Webhookdb::Replicator::FakeDependent < Webhookdb::Replicator::Fake
168
+ singleton_attr_accessor :on_dependency_webhook_upsert_callback
169
+
170
+ def self.descriptor
171
+ return Webhookdb::Replicator::Descriptor.new(
172
+ name: "fake_dependent_v1",
173
+ ctor: ->(sint) { Webhookdb::Replicator::FakeDependent.new(sint) },
174
+ feature_roles: ["internal"],
175
+ resource_name_singular: "FakeDependent",
176
+ dependency_descriptor: Webhookdb::Replicator::Fake.descriptor,
177
+ supports_webhooks: true,
178
+ supports_backfill: true,
179
+ )
180
+ end
181
+
182
+ def on_dependency_webhook_upsert(replicator, payload, changed:)
183
+ self.class.on_dependency_webhook_upsert_callback&.call(replicator, payload, changed:)
184
+ end
185
+
186
+ def calculate_webhook_state_machine
187
+ dependency_help = "This is where you would explain things like the relationship between stripe cards and customers."
188
+ if (step = self.calculate_dependency_state_machine_step(dependency_help:))
189
+ return step
190
+ end
191
+ return super
192
+ end
193
+ end
194
+
195
+ class Webhookdb::Replicator::FakeDependentDependent < Webhookdb::Replicator::Fake
196
+ singleton_attr_accessor :on_dependency_webhook_upsert_callback
197
+
198
+ def self.descriptor
199
+ return Webhookdb::Replicator::Descriptor.new(
200
+ name: "fake_dependent_dependent_v1",
201
+ ctor: ->(sint) { Webhookdb::Replicator::FakeDependentDependent.new(sint) },
202
+ feature_roles: ["internal"],
203
+ resource_name_singular: "FakeDependentDependent",
204
+ dependency_descriptor: Webhookdb::Replicator::FakeDependent.descriptor,
205
+ supports_webhooks: true,
206
+ supports_backfill: true,
207
+ )
208
+ end
209
+
210
+ def on_dependency_webhook_upsert(replicator, payload, changed:)
211
+ self.class.on_dependency_webhook_upsert_callback&.call(replicator, payload, changed:)
212
+ end
213
+
214
+ def calculate_webhook_state_machine
215
+ dependency_help = "This is where you would explain things like the relationship between stripe cards and customers."
216
+ if (step = self.calculate_dependency_state_machine_step(dependency_help:))
217
+ return step
218
+ end
219
+ return super
220
+ end
221
+ end
222
+
223
+ class Webhookdb::Replicator::FakeEnqueueBackfillOnCreate < Webhookdb::Replicator::Fake
224
+ singleton_attr_accessor :on_dependency_webhook_upsert_callback
225
+
226
+ def self.descriptor
227
+ return Webhookdb::Replicator::Descriptor.new(
228
+ name: "fake_enqueue_backfill_on_create_v1",
229
+ ctor: ->(sint) { Webhookdb::Replicator::FakeEnqueueBackfillOnCreate.new(sint) },
230
+ feature_roles: ["internal"],
231
+ resource_name_singular: "FakeEnqueueBackfillOnCreate",
232
+ supports_webhooks: true,
233
+ supports_backfill: true,
234
+ )
235
+ end
236
+
237
+ def calculate_backfill_state_machine
238
+ # To mimic situations where it is possible to enqueue a backfill job on create, this backfill machine does
239
+ # not require any extra information--its initial step is "complete." The main situation where this would
240
+ # happen is if a replicator gets backfill creds from a dependency.
241
+ step = Webhookdb::Replicator::StateMachineStep.new
242
+ step.needs_input = false
243
+ step.output = "The backfill flow is working correctly."
244
+ step.complete = true
245
+ return step
246
+ end
247
+ end
248
+
249
+ class Webhookdb::Replicator::FakeWebhooksOnly < Webhookdb::Replicator::Fake
250
+ def self.descriptor
251
+ return Webhookdb::Replicator::Descriptor.new(
252
+ name: "fake_webhooks_only_v1",
253
+ ctor: ->(sint) { Webhookdb::Replicator::FakeWebhooksOnly.new(sint) },
254
+ feature_roles: ["internal"],
255
+ resource_name_singular: "Fake Webhooks Only (No Backfill)",
256
+ supports_webhooks: true,
257
+ supports_backfill: false,
258
+ )
259
+ end
260
+
261
+ def documentation_url = "https://abc.xyz"
262
+
263
+ def calculate_backfill_state_machine = raise NotImplementedError
264
+ end
265
+
266
+ class Webhookdb::Replicator::FakeBackfillOnly < Webhookdb::Replicator::Fake
267
+ def self.descriptor
268
+ return Webhookdb::Replicator::Descriptor.new(
269
+ name: "fake_backfill_only_v1",
270
+ ctor: ->(sint) { Webhookdb::Replicator::FakeBackfillOnly.new(sint) },
271
+ feature_roles: ["internal"],
272
+ resource_name_singular: "Fake Backfill Only (No Webhooks)",
273
+ supports_webhooks: false,
274
+ supports_backfill: true,
275
+ )
276
+ end
277
+
278
+ def calculate_webhook_state_machine = raise NotImplementedError
279
+ end
280
+
281
+ class Webhookdb::Replicator::FakeBackfillWithCriteria < Webhookdb::Replicator::Fake
282
+ def self.descriptor
283
+ return Webhookdb::Replicator::Descriptor.new(
284
+ name: "fake_backfill_with_criteria_v1",
285
+ ctor: ->(sint) { Webhookdb::Replicator::FakeBackfillWithCriteria.new(sint) },
286
+ feature_roles: ["internal"],
287
+ resource_name_singular: "Fake Backfill with Criteria",
288
+ dependency_descriptor: Webhookdb::Replicator::Fake,
289
+ supports_backfill: true,
290
+ )
291
+ end
292
+
293
+ def _denormalized_columns
294
+ return super << Webhookdb::Replicator::Column.new(:backfill_kwargs, OBJECT, optional: true)
295
+ end
296
+
297
+ def _backfillers(**kwargs)
298
+ return [CriteriaStoringBackfiller.new(self, kwargs)]
299
+ end
300
+
301
+ class CriteriaStoringBackfiller < Webhookdb::Backfiller
302
+ def initialize(svc, kw)
303
+ @svc = svc
304
+ @kw = kw
305
+ super()
306
+ end
307
+
308
+ def handle_item(body)
309
+ body["backfill_kwargs"] = @kw
310
+ @svc.upsert_webhook_body(body)
311
+ end
312
+
313
+ def fetch_backfill_page(_pagination_token, **_kwargs)
314
+ return [[{"my_id" => "x", "at" => "2022-01-01T00:00:00Z"}], nil]
315
+ end
316
+ end
317
+ end
318
+
319
+ class Webhookdb::Replicator::FakeExhaustiveConverter < Webhookdb::Replicator::Fake
320
+ def self.descriptor
321
+ return Webhookdb::Replicator::Descriptor.new(
322
+ name: "fake_exhaustive_converter_v1",
323
+ ctor: ->(sint) { Webhookdb::Replicator::FakeExhaustiveConverter.new(sint) },
324
+ feature_roles: ["internal"],
325
+ resource_name_singular: "Fake with all converters",
326
+ supports_webhooks: true,
327
+ supports_backfill: false,
328
+ )
329
+ end
330
+
331
+ def requires_sequence? = true
332
+
333
+ # True to return only the superclass columns. Used to test column updates.
334
+ attr_accessor :super_cols_only
335
+ # True to return only the columns that can be used for updates. Used to test column updates.
336
+ # Should be true when testing Ruby converters.
337
+ attr_accessor :exclude_unimplemented_sql_update_cols
338
+
339
+ def _denormalized_columns
340
+ cols = super
341
+ return cols if self.super_cols_only
342
+ cols += [
343
+ Webhookdb::Replicator::Column.new(
344
+ :comma_sep,
345
+ TEXT_ARRAY,
346
+ converter: Webhookdb::Replicator::Column::CONV_COMMA_SEP,
347
+ ),
348
+ Webhookdb::Replicator::Column.new(
349
+ :geo_lat,
350
+ DECIMAL,
351
+ data_key: "latlng",
352
+ converter: Webhookdb::Replicator::Column.converter_array_element(index: 0, sep: " ", cls: DECIMAL),
353
+ ),
354
+ Webhookdb::Replicator::Column.new(
355
+ :geo_lng,
356
+ DECIMAL,
357
+ data_key: "latlng",
358
+ converter: Webhookdb::Replicator::Column.converter_array_element(index: 1, sep: " ", cls: DECIMAL),
359
+ ),
360
+ Webhookdb::Replicator::Column.new(:date, DATE, converter: :date),
361
+ Webhookdb::Replicator::Column.new(:datetime, TIMESTAMP, converter: :time),
362
+ Webhookdb::Replicator::Column.new(:parsed_int, INTEGER, converter: :to_i),
363
+ Webhookdb::Replicator::Column.new(:unix_ts, TIMESTAMP, converter: :tsat),
364
+ Webhookdb::Replicator::Column.new(
365
+ :strptime,
366
+ TIMESTAMP,
367
+ converter: Webhookdb::Replicator::Column.converter_strptime("%d%m%Y %H%M%S%Z", "DDMMYYYY HH24MISS", cls: Time),
368
+ ),
369
+ Webhookdb::Replicator::Column.new(
370
+ :strptime_date,
371
+ DATE,
372
+ converter: Webhookdb::Replicator::Column.converter_strptime("%d%Y%m", "DDYYYYMM", cls: Date),
373
+ ),
374
+ Webhookdb::Replicator::Column.new(
375
+ :int_array,
376
+ BIGINT_ARRAY,
377
+ data_key: "obj_array",
378
+ converter: Webhookdb::Replicator::Column.converter_array_pluck("id", BIGINT),
379
+ ),
380
+ Webhookdb::Replicator::Column.new(
381
+ :text_array,
382
+ TEXT_ARRAY,
383
+ data_key: "obj_array",
384
+ converter: Webhookdb::Replicator::Column.converter_array_pluck("name", TEXT),
385
+ ),
386
+ Webhookdb::Replicator::Column.new(
387
+ :subtext,
388
+ TEXT,
389
+ converter: Webhookdb::Replicator::Column.converter_gsub("^hello", "goodbye"),
390
+ ),
391
+ Webhookdb::Replicator::Column.new(
392
+ :regex_extract,
393
+ TEXT,
394
+ data_key: "regex_conv",
395
+ converter: Webhookdb::Replicator::Column.converter_from_regex('/resources/(\d+)'),
396
+ ),
397
+ Webhookdb::Replicator::Column.new(
398
+ :regex_conv,
399
+ INTEGER,
400
+ converter: Webhookdb::Replicator::Column.converter_from_regex('/resources/(\d+)', dbtype: INTEGER),
401
+ ),
402
+ Webhookdb::Replicator::Column.new(
403
+ :to_utc_date,
404
+ DATE,
405
+ converter: Webhookdb::Replicator::Column::CONV_TO_UTC_DATE,
406
+ ),
407
+ Webhookdb::Replicator::Column.new(
408
+ :using_backfill_expr,
409
+ TEXT,
410
+ data_key: "my_id",
411
+ backfill_expr: "hi there",
412
+ ),
413
+ Webhookdb::Replicator::Column.new(
414
+ :using_backfill_statement,
415
+ TEXT,
416
+ data_key: "my_id",
417
+ backfill_statement: Sequel.lit(<<~SQL),
418
+ CREATE OR REPLACE FUNCTION pg_temp.fake_backfiller_update_tests(text)
419
+ RETURNS text AS 'SELECT $1 || $1' LANGUAGE sql IMMUTABLE
420
+ SQL
421
+ backfill_expr: Sequel.lit("pg_temp.fake_backfiller_update_tests(my_id)"),
422
+ ),
423
+ ]
424
+ return cols if self.exclude_unimplemented_sql_update_cols
425
+ cols << Webhookdb::Replicator::Column.new(
426
+ :int_or_seq_has,
427
+ INTEGER,
428
+ converter: Webhookdb::Replicator::Column.converter_int_or_sequence_from_regex('/resources/(\d+)'),
429
+ )
430
+ cols << Webhookdb::Replicator::Column.new(
431
+ :int_or_seq_has_not,
432
+ INTEGER,
433
+ converter: Webhookdb::Replicator::Column.converter_int_or_sequence_from_regex('/resources/(\d+)'),
434
+ )
435
+ cols << Webhookdb::Replicator::Column.new(
436
+ :map_lookup,
437
+ TEXT,
438
+ converter: Webhookdb::Replicator::Column.converter_map_lookup(
439
+ array: false,
440
+ map: {"a" => "A", "b" => "B"},
441
+ ),
442
+ )
443
+ cols << Webhookdb::Replicator::Column.new(
444
+ :map_lookup_array,
445
+ TEXT_ARRAY,
446
+ converter: Webhookdb::Replicator::Column.converter_map_lookup(
447
+ array: true,
448
+ map: {"a" => "A", "b" => "B"},
449
+ ),
450
+ )
451
+ return cols
452
+ end
453
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/replicator/front_v1_mixin"
4
+
5
+ class Webhookdb::Replicator::FrontConversationV1 < Webhookdb::Replicator::Base
6
+ include Appydays::Loggable
7
+ include Webhookdb::DBAdapter::ColumnTypes
8
+ include Webhookdb::Replicator::FrontV1Mixin
9
+
10
+ def self.descriptor
11
+ return Webhookdb::Replicator::Descriptor.new(
12
+ name: "front_conversation_v1",
13
+ ctor: self,
14
+ feature_roles: ["front"],
15
+ resource_name_singular: "Front Conversation",
16
+ dependency_descriptor: Webhookdb::Replicator::FrontMarketplaceRootV1.descriptor,
17
+ supports_webhooks: true,
18
+ api_docs_url: "https://dev.frontapp.com/reference/conversations",
19
+ )
20
+ end
21
+
22
+ def _remote_key_column
23
+ return Webhookdb::Replicator::Column.new(:front_id, TEXT, data_key: "id")
24
+ end
25
+
26
+ def _denormalized_columns
27
+ return [
28
+ Webhookdb::Replicator::Column.new(:subject, TEXT),
29
+ Webhookdb::Replicator::Column.new(:status, TEXT),
30
+ Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, converter: :tsat),
31
+ ]
32
+ end
33
+
34
+ def _timestamp_column_name
35
+ return :created_at
36
+ end
37
+
38
+ def _resource_and_event(request)
39
+ return request.body.dig("payload", "conversation"), request.body.fetch("payload")
40
+ end
41
+
42
+ def _update_where_expr
43
+ return self.qualified_table_sequel_identifier[:data] !~ Sequel[:excluded][:data]
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/replicator/front_v1_mixin"
4
+
5
+ class Webhookdb::Replicator::FrontMarketplaceRootV1 < Webhookdb::Replicator::Base
6
+ include Appydays::Loggable
7
+
8
+ # @return [Webhookdb::Replicator::Descriptor]
9
+ def self.descriptor
10
+ return Webhookdb::Replicator::Descriptor.new(
11
+ name: "front_marketplace_root_v1",
12
+ ctor: self,
13
+ feature_roles: ["front"],
14
+ resource_name_singular: "Front Auth",
15
+ resource_name_plural: "Front Auth",
16
+ supports_webhooks: true,
17
+ description: "You can replicate your data to WebhookDB Cloud using the Front Marketplace.",
18
+ )
19
+ end
20
+
21
+ def _remote_key_column
22
+ return Webhookdb::Replicator::Column.new(:ignore_id, INTEGER)
23
+ end
24
+
25
+ def _denormalized_columns
26
+ return []
27
+ end
28
+
29
+ def _upsert_webhook(**_kwargs)
30
+ raise NotImplementedError("This is a stub integration only for auth purposes.")
31
+ end
32
+
33
+ def build_dependents
34
+ org = self.service_integration.organization
35
+ conversation_sint = Webhookdb::ServiceIntegration.create_disambiguated(
36
+ "front_conversation_v1",
37
+ organization: org,
38
+ depends_on: self.service_integration,
39
+ )
40
+ message_sint = Webhookdb::ServiceIntegration.create_disambiguated(
41
+ "front_message_v1",
42
+ organization: org,
43
+ depends_on: self.service_integration,
44
+ )
45
+ conversation_sint.replicator.create_table
46
+ message_sint.replicator.create_table
47
+ end
48
+
49
+ def calculate_webhook_state_machine
50
+ step = Webhookdb::Replicator::StateMachineStep.new
51
+ step.output = "This integration cannot be modified through the command line."
52
+ step.completed
53
+ return step
54
+ end
55
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/replicator/front_v1_mixin"
4
+
5
+ class Webhookdb::Replicator::FrontMessageV1 < Webhookdb::Replicator::Base
6
+ include Appydays::Loggable
7
+ include Webhookdb::DBAdapter::ColumnTypes
8
+ include Webhookdb::Replicator::FrontV1Mixin
9
+
10
+ def self.descriptor
11
+ return Webhookdb::Replicator::Descriptor.new(
12
+ name: "front_message_v1",
13
+ ctor: self,
14
+ feature_roles: ["front"],
15
+ resource_name_singular: "Front Message",
16
+ dependency_descriptor: Webhookdb::Replicator::FrontMarketplaceRootV1.descriptor,
17
+ supports_webhooks: true,
18
+ api_docs_url: "https://dev.frontapp.com/reference/messages",
19
+ )
20
+ end
21
+
22
+ def _remote_key_column
23
+ return Webhookdb::Replicator::Column.new(:front_id, TEXT, data_key: "id")
24
+ end
25
+
26
+ def _denormalized_columns
27
+ return [
28
+ Webhookdb::Replicator::Column.new(:type, TEXT),
29
+ Webhookdb::Replicator::Column.new(:front_conversation_id, TEXT, event_key: ["conversation", "id"]),
30
+ Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, converter: :tsat),
31
+ ]
32
+ end
33
+
34
+ def _timestamp_column_name
35
+ return :created_at
36
+ end
37
+
38
+ def _resource_and_event(request)
39
+ return request.body.dig("payload", "target", "data"), request.body.fetch("payload")
40
+ end
41
+
42
+ def _update_where_expr
43
+ return self.qualified_table_sequel_identifier[:data] !~ Sequel[:excluded][:data]
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/front"
4
+
5
+ module Webhookdb::Replicator::FrontV1Mixin
6
+ def calculate_webhook_state_machine
7
+ if (step = self.calculate_dependency_state_machine_step(dependency_help: ""))
8
+ return step
9
+ end
10
+ step = Webhookdb::Replicator::StateMachineStep.new
11
+ step.output = %(Great! WebhookDB is now listening for #{self.resource_name_singular} webhooks.)
12
+ return step.completed
13
+ end
14
+
15
+ def _webhook_response(request)
16
+ return Webhookdb::Front.webhook_response(request)
17
+ end
18
+
19
+ def on_dependency_webhook_upsert(_replicator, _payload, *)
20
+ return
21
+ end
22
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webhookdb/github"
4
+ require "webhookdb/replicator/github_repo_v1_mixin"
5
+
6
+ class Webhookdb::Replicator::GithubIssueCommentV1 < Webhookdb::Replicator::Base
7
+ include Appydays::Loggable
8
+ include Webhookdb::Replicator::GithubRepoV1Mixin
9
+
10
+ def _mixin_backfill_url = "/issues/comments"
11
+ def _mixin_webhook_events = ["Issue comments"]
12
+ def _mixin_webhook_key = "comment"
13
+ def _mixin_fine_grained_permission = "Issues"
14
+
15
+ def _mixin_query_params(last_backfilled:)
16
+ q = {}
17
+ if last_backfilled
18
+ q[:sort] = "updated"
19
+ q[:since] = last_backfilled.utc.iso8601
20
+ end
21
+ return q
22
+ end
23
+
24
+ # @return [Webhookdb::Replicator::Descriptor]
25
+ def self.descriptor
26
+ return Webhookdb::Replicator::Descriptor.new(
27
+ name: "github_issue_comment_v1",
28
+ ctor: ->(sint) { Webhookdb::Replicator::GithubIssueCommentV1.new(sint) },
29
+ feature_roles: [],
30
+ resource_name_singular: "GitHub Issue Comment",
31
+ supports_webhooks: true,
32
+ supports_backfill: true,
33
+ api_docs_url: Webhookdb::Replicator::GithubRepoV1Mixin._api_docs_url("/issues/comments"),
34
+ )
35
+ end
36
+
37
+ def _remote_key_column
38
+ return Webhookdb::Replicator::Column.new(:github_id, BIGINT, data_key: "id")
39
+ end
40
+
41
+ def _denormalized_columns
42
+ return [
43
+ Webhookdb::Replicator::Column.new(
44
+ :issue_id,
45
+ BIGINT,
46
+ index: true,
47
+ data_key: "issue_url",
48
+ converter: Webhookdb::Replicator::Column.converter_from_regex('/issues/(\d+)$', dbtype: BIGINT),
49
+ ),
50
+ Webhookdb::Replicator::Column.new(:created_at, TIMESTAMP, index: true),
51
+ Webhookdb::Replicator::Column.new(:updated_at, TIMESTAMP, index: true),
52
+ Webhookdb::Replicator::Column.new(:user_id, BIGINT, index: true, data_key: ["user", "id"], optional: true),
53
+ Webhookdb::Replicator::Column.new(:node_id, TEXT, index: true),
54
+ ]
55
+ end
56
+
57
+ def _timestamp_column_name = :updated_at
58
+ end