@zackbart/connecta 0.34.0 → 0.35.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 (428) hide show
  1. package/CHANGELOG.md +393 -0
  2. package/README.md +62 -105
  3. package/SECURITY.md +3 -2
  4. package/bin/connecta.mjs +41 -16
  5. package/bin/version.mjs +1 -1
  6. package/dist/access-tokens.d.ts +2 -1
  7. package/dist/access-tokens.js +66 -30
  8. package/dist/activity.d.ts +1 -1
  9. package/dist/activity.js +2 -0
  10. package/dist/agent-config.d.ts +23 -0
  11. package/dist/agent-config.js +59 -0
  12. package/dist/agent-description.js +16 -0
  13. package/dist/agent-identity.js +4 -4
  14. package/dist/agent-observation.js +39 -0
  15. package/dist/auth/clerk-sdk/client.d.ts +2 -0
  16. package/dist/auth/clerk-sdk/generated.js +554 -563
  17. package/dist/auth/clerk-transport.js +70 -3
  18. package/dist/auth/clerk.d.ts +13 -0
  19. package/dist/auth/clerk.js +653 -246
  20. package/dist/auth/cloudflare-access.js +46 -42
  21. package/dist/auth/downstream-client-metadata.js +2 -2
  22. package/dist/auth/downstream-oauth.js +2051 -1160
  23. package/dist/auth/downstream-revocation.js +88 -88
  24. package/dist/auth/native-call.js +20 -0
  25. package/dist/auth/native.js +184 -0
  26. package/dist/auth/oauth-start-reset.js +11 -5
  27. package/dist/auth/oauth-token-response.js +121 -102
  28. package/dist/auth/oauth-v2-migration.js +97 -78
  29. package/dist/auth/renewable-grant.js +10 -0
  30. package/dist/auth/static-oauth.js +663 -271
  31. package/dist/auth/vercel-agent.js +266 -0
  32. package/dist/auth-admission.js +204 -0
  33. package/dist/auth-elicitation.js +350 -241
  34. package/dist/authorization-handoff.js +164 -90
  35. package/dist/call-admission-context.js +3 -10
  36. package/dist/call-admission.js +2 -0
  37. package/dist/call-classification.js +9 -0
  38. package/dist/call-recovery.js +32 -13
  39. package/dist/canonical-json.js +8 -0
  40. package/dist/catalog-cache.js +369 -213
  41. package/dist/catalog-service.js +659 -530
  42. package/dist/catalog.js +5 -1
  43. package/dist/concurrency.js +0 -25
  44. package/dist/config-defaults.d.ts +1 -0
  45. package/dist/config-defaults.js +1 -0
  46. package/dist/config-schema.d.ts +3 -1
  47. package/dist/config-schema.js +13 -3
  48. package/dist/config.d.ts +40 -6
  49. package/dist/config.js +40 -26
  50. package/dist/connector-caller.d.ts +4 -0
  51. package/dist/connector-caller.js +17 -4
  52. package/dist/connectors/api-connector.d.ts +15 -7
  53. package/dist/connectors/api-connector.js +147 -57
  54. package/dist/connectors/guarded-fetch.d.ts +51 -17
  55. package/dist/connectors/guarded-fetch.js +215 -121
  56. package/dist/connectors/negotiation-cache.js +20 -10
  57. package/dist/connectors/option-shapes.js +1 -1
  58. package/dist/connectors/remote-mcp.d.ts +12 -30
  59. package/dist/connectors/remote-mcp.js +960 -564
  60. package/dist/d1.js +10 -243
  61. package/dist/derived-context.js +5 -0
  62. package/dist/describe-config.d.ts +5 -1
  63. package/dist/describe-config.js +3 -0
  64. package/dist/downstream-input.js +347 -260
  65. package/dist/errors.d.ts +87 -6
  66. package/dist/errors.js +114 -4
  67. package/dist/execute.js +87 -50
  68. package/dist/executor-admission.js +3 -0
  69. package/dist/executors/quickjs.js +163 -112
  70. package/dist/guarded-transport.js +50 -0
  71. package/dist/guest-runtime.js +1 -1
  72. package/dist/http/client.js +439 -0
  73. package/dist/http/errors.js +558 -0
  74. package/dist/http/fields.js +49 -0
  75. package/dist/http/hatch-paging.js +318 -0
  76. package/dist/http/hatch.js +1279 -0
  77. package/dist/http/json-schema.js +267 -0
  78. package/dist/http/node-transport.js +241 -0
  79. package/dist/http/oauth.js +162 -0
  80. package/dist/http/paging.js +228 -0
  81. package/dist/http/provider.js +221 -0
  82. package/dist/http/safety.js +82 -0
  83. package/dist/http/services.js +79 -0
  84. package/dist/http/tools.js +383 -0
  85. package/dist/http/vendor-index.js +138 -0
  86. package/dist/http/vendor.js +448 -0
  87. package/dist/http/write-request.js +66 -0
  88. package/dist/http-policy.d.ts +11 -0
  89. package/dist/http-policy.js +45 -0
  90. package/dist/inbound-credential.js +1 -1
  91. package/dist/index.d.ts +2 -2
  92. package/dist/index.js +4 -0
  93. package/dist/invocation-auth.js +30 -19
  94. package/dist/invocation.js +221 -87
  95. package/dist/mcp-result.js +0 -4
  96. package/dist/membership.d.ts +4 -0
  97. package/dist/meta-output.js +1 -1
  98. package/dist/meta-tools.js +534 -408
  99. package/dist/native-recovery.js +52 -0
  100. package/dist/native-tools.js +382 -0
  101. package/dist/node.d.ts +4 -3
  102. package/dist/node.js +45 -8
  103. package/dist/oauth-handoff.js +177 -104
  104. package/dist/oauth-partition.js +6 -20
  105. package/dist/oauth-sealing.js +6 -7
  106. package/dist/operation-vocabulary.js +101 -0
  107. package/dist/operator-record.d.ts +2 -2
  108. package/dist/operator-record.js +17 -4
  109. package/dist/operator-ui/agents.d.ts +5 -4
  110. package/dist/operator-ui/agents.js +17 -7
  111. package/dist/operator-ui/config-summary.js +8 -4
  112. package/dist/operator-ui/connection-map.js +9 -6
  113. package/dist/operator-ui/contract.d.ts +7 -3
  114. package/dist/operator-ui/endpoints.js +5 -14
  115. package/dist/operator-ui/fix-prompts.d.ts +1 -1
  116. package/dist/operator-ui/fix-prompts.js +0 -8
  117. package/dist/operator-ui/generated.js +3 -3
  118. package/dist/operator-ui/health.js +52 -0
  119. package/dist/operator-ui/model.d.ts +2 -3
  120. package/dist/operator-ui/overview.js +11 -19
  121. package/dist/operator-ui/setup-commands.js +0 -4
  122. package/dist/operator-ui/view.d.ts +5 -29
  123. package/dist/operator-ui/view.js +3 -59
  124. package/dist/program-writes.js +47 -26
  125. package/dist/provider-call-facts.d.ts +115 -0
  126. package/dist/provider-call-facts.js +182 -0
  127. package/dist/provider-call.d.ts +112 -0
  128. package/dist/provider-call.js +271 -0
  129. package/dist/provider.d.ts +71 -32
  130. package/dist/provider.js +134 -40
  131. package/dist/providers/_shared/google/hatch.js +91 -0
  132. package/dist/providers/_shared/google/kit.js +537 -0
  133. package/dist/providers/_shared/google/result-size.js +15 -2
  134. package/dist/providers/_shared/google/service-account.d.ts +2 -1
  135. package/dist/providers/_shared/google/service-account.js +8 -4
  136. package/dist/providers/_shared/google/workspace.d.ts +8 -209
  137. package/dist/providers/_shared/google/workspace.js +7 -426
  138. package/dist/providers/_shared/rest/compact-index.js +86 -0
  139. package/dist/providers/_shared/rest/dispatch.js +3 -23
  140. package/dist/providers/_shared/rest/kit.js +546 -0
  141. package/dist/providers/_shared/rest/operation-index.js +230 -14
  142. package/dist/providers/_shared/rest/response-media.js +11 -0
  143. package/dist/providers/_shared/rest/tools.js +101 -78
  144. package/dist/providers/_shared/rest/value-safety.js +353 -195
  145. package/dist/providers/_shared/sensitive-fields.js +27 -0
  146. package/dist/providers/breeze/api.js +584 -0
  147. package/dist/providers/breeze/index.d.ts +3 -3
  148. package/dist/providers/breeze/index.js +67 -1420
  149. package/dist/providers/breeze/openapi.generated.js +60 -0
  150. package/dist/providers/breeze/skill.generated.js +2 -6
  151. package/dist/providers/breeze/tools.js +696 -0
  152. package/dist/providers/ccb/api.js +496 -0
  153. package/dist/providers/ccb/index.d.ts +17 -37
  154. package/dist/providers/ccb/index.js +77 -1702
  155. package/dist/providers/ccb/lib/constants.d.ts +34 -0
  156. package/dist/providers/ccb/lib/constants.js +74 -0
  157. package/dist/providers/ccb/lib/guide.js +9 -0
  158. package/dist/providers/ccb/lib/verdicts.js +387 -0
  159. package/dist/providers/ccb/openapi.generated.js +397 -0
  160. package/dist/providers/ccb/safety.js +295 -0
  161. package/dist/providers/ccb/skill.generated.js +2 -6
  162. package/dist/providers/ccb/tools.js +853 -0
  163. package/dist/providers/cloudflare/api.js +1066 -0
  164. package/dist/providers/cloudflare/index.d.ts +7 -22
  165. package/dist/providers/cloudflare/index.js +80 -194
  166. package/dist/providers/cloudflare/lib/config.d.ts +16 -0
  167. package/dist/providers/cloudflare/lib/config.js +2 -0
  168. package/dist/providers/cloudflare/lib/discovery.js +29 -0
  169. package/dist/providers/cloudflare/{graphql.js → lib/graphql.js} +1 -1
  170. package/dist/providers/cloudflare/lib/hatch.js +103 -0
  171. package/dist/providers/cloudflare/lib/path-bounds.js +28 -0
  172. package/dist/providers/cloudflare/lib/response-media.js +75 -0
  173. package/dist/providers/cloudflare/openapi.generated.js +3299 -3208
  174. package/dist/providers/cloudflare/{value-safety.js → safety.js} +538 -18
  175. package/dist/providers/cloudflare/skill.generated.js +2 -10
  176. package/dist/providers/cloudflare/tools.js +360 -0
  177. package/dist/providers/docs/api.js +51 -0
  178. package/dist/providers/docs/index.d.ts +1 -12
  179. package/dist/providers/docs/index.js +53 -1165
  180. package/dist/providers/docs/lib/constants.d.ts +18 -0
  181. package/dist/providers/docs/lib/constants.js +18 -0
  182. package/dist/providers/docs/lib/discovery.js +26 -0
  183. package/dist/providers/docs/lib/requests.js +48 -0
  184. package/dist/providers/docs/lib/schemas.js +168 -0
  185. package/dist/providers/docs/openapi.generated.js +16 -0
  186. package/dist/providers/docs/safety.js +54 -0
  187. package/dist/providers/docs/skill.generated.js +2 -6
  188. package/dist/providers/docs/tools.js +802 -0
  189. package/dist/providers/drive/api.js +177 -0
  190. package/dist/providers/drive/index.d.ts +1 -12
  191. package/dist/providers/drive/index.js +38 -1448
  192. package/dist/providers/drive/lib/constants.d.ts +6 -0
  193. package/dist/providers/drive/lib/constants.js +6 -0
  194. package/dist/providers/drive/lib/contracts.js +532 -0
  195. package/dist/providers/drive/lib/hatch.js +197 -0
  196. package/dist/providers/drive/openapi.generated.js +77 -0
  197. package/dist/providers/drive/safety.js +90 -0
  198. package/dist/providers/drive/skill.generated.js +2 -6
  199. package/dist/providers/drive/tools.js +1290 -0
  200. package/dist/providers/forms/api.js +71 -0
  201. package/dist/providers/forms/index.d.ts +1 -12
  202. package/dist/providers/forms/index.js +49 -1145
  203. package/dist/providers/forms/lib/constants.d.ts +14 -0
  204. package/dist/providers/forms/lib/constants.js +19 -0
  205. package/dist/providers/forms/lib/hatch.js +72 -0
  206. package/dist/providers/forms/openapi.generated.js +23 -0
  207. package/dist/providers/forms/safety.js +34 -0
  208. package/dist/providers/forms/skill.generated.js +2 -8
  209. package/dist/providers/forms/tools.js +1024 -0
  210. package/dist/providers/github/api.js +150 -0
  211. package/dist/providers/github/index.d.ts +4 -5
  212. package/dist/providers/github/index.js +30 -87
  213. package/dist/providers/github/{auth.d.ts → lib/auth.d.ts} +5 -3
  214. package/dist/providers/github/{auth.js → lib/auth.js} +40 -43
  215. package/dist/providers/github/lib/discovery.js +132 -0
  216. package/dist/providers/github/lib/operations.js +58 -0
  217. package/dist/providers/github/{scope.d.ts → lib/scope.d.ts} +2 -0
  218. package/dist/providers/github/{scope.js → lib/scope.js} +25 -1
  219. package/dist/providers/github/openapi.generated.js +1216 -0
  220. package/dist/providers/github/safety.js +216 -0
  221. package/dist/providers/github/skill.generated.js +2 -5
  222. package/dist/providers/github/tools.js +506 -0
  223. package/dist/providers/gmail/api.js +114 -0
  224. package/dist/providers/gmail/index.d.ts +1 -12
  225. package/dist/providers/gmail/index.js +73 -1621
  226. package/dist/providers/gmail/lib/constants.d.ts +13 -0
  227. package/dist/providers/gmail/lib/constants.js +16 -0
  228. package/dist/providers/gmail/lib/index.js +173 -0
  229. package/dist/providers/gmail/lib/schemas.js +176 -0
  230. package/dist/providers/gmail/lib/threading.js +120 -0
  231. package/dist/providers/gmail/openapi.generated.js +92 -0
  232. package/dist/providers/gmail/safety.js +21 -0
  233. package/dist/providers/gmail/skill.generated.js +2 -6
  234. package/dist/providers/gmail/tools.js +1435 -0
  235. package/dist/providers/overflow/api.js +1008 -0
  236. package/dist/providers/overflow/index.d.ts +3 -17
  237. package/dist/providers/overflow/index.js +60 -1488
  238. package/dist/providers/overflow/skill.generated.js +2 -5
  239. package/dist/providers/overflow/tools.js +873 -0
  240. package/dist/providers/planning-center/api.js +467 -0
  241. package/dist/providers/planning-center/index.d.ts +6 -35
  242. package/dist/providers/planning-center/index.js +69 -2445
  243. package/dist/providers/planning-center/lib/constants.d.ts +58 -0
  244. package/dist/providers/planning-center/lib/constants.js +83 -0
  245. package/dist/providers/planning-center/lib/discovery.js +40 -0
  246. package/dist/providers/planning-center/lib/guide.js +39 -0
  247. package/dist/providers/planning-center/lib/json-api.js +83 -0
  248. package/dist/providers/planning-center/lib/verdicts.js +1758 -0
  249. package/dist/providers/planning-center/openapi.generated.js +1764 -0
  250. package/dist/providers/planning-center/safety.js +188 -0
  251. package/dist/providers/planning-center/skill.generated.js +2 -27
  252. package/dist/providers/planning-center/tools.js +1010 -0
  253. package/dist/providers/sheets/api.js +133 -0
  254. package/dist/providers/sheets/index.d.ts +4 -16
  255. package/dist/providers/sheets/index.js +61 -1172
  256. package/dist/providers/sheets/lib/constants.d.ts +14 -0
  257. package/dist/providers/sheets/lib/constants.js +14 -0
  258. package/dist/providers/sheets/lib/hatch.js +163 -0
  259. package/dist/providers/sheets/lib/requests.js +105 -0
  260. package/dist/providers/sheets/lib/schemas.js +138 -0
  261. package/dist/providers/sheets/openapi.generated.js +30 -0
  262. package/dist/providers/sheets/safety.js +27 -0
  263. package/dist/providers/sheets/skill.generated.js +2 -7
  264. package/dist/providers/sheets/tools.js +734 -0
  265. package/dist/providers/slides/api.js +147 -0
  266. package/dist/providers/slides/index.d.ts +2 -10
  267. package/dist/providers/slides/index.js +48 -2555
  268. package/dist/providers/slides/lib/constants.d.ts +11 -0
  269. package/dist/providers/slides/lib/constants.js +11 -0
  270. package/dist/providers/slides/lib/requests.js +60 -0
  271. package/dist/providers/slides/lib/schemas.js +565 -0
  272. package/dist/providers/slides/openapi.generated.js +18 -0
  273. package/dist/providers/slides/skill.generated.js +2 -6
  274. package/dist/providers/slides/tools.js +1968 -0
  275. package/dist/providers/stripe/api.js +401 -0
  276. package/dist/providers/stripe/index.d.ts +7 -27
  277. package/dist/providers/stripe/index.js +75 -191
  278. package/dist/providers/stripe/lib/config.d.ts +4 -0
  279. package/dist/providers/stripe/lib/config.js +2 -0
  280. package/dist/providers/stripe/openapi.generated.js +4 -3
  281. package/dist/providers/stripe/{value-safety.js → safety.js} +5 -5
  282. package/dist/providers/stripe/skill.generated.js +2 -10
  283. package/dist/providers/stripe/tools.js +77 -0
  284. package/dist/providers/tithely/api.js +531 -0
  285. package/dist/providers/tithely/index.d.ts +19 -0
  286. package/dist/providers/tithely/index.js +86 -965
  287. package/dist/providers/tithely/skill.generated.js +2 -5
  288. package/dist/providers/tithely/tools.js +426 -0
  289. package/dist/providers/vercel/api.js +551 -0
  290. package/dist/providers/vercel/index.d.ts +11 -25
  291. package/dist/providers/vercel/index.js +67 -261
  292. package/dist/providers/vercel/lib/config.d.ts +2 -0
  293. package/dist/providers/vercel/lib/config.js +2 -0
  294. package/dist/providers/vercel/lib/index.js +117 -0
  295. package/dist/providers/vercel/lib/logs.js +100 -0
  296. package/dist/providers/vercel/lib/pin.js +270 -0
  297. package/dist/providers/vercel/openapi.generated.js +398 -376
  298. package/dist/providers/vercel/{value-safety.js → safety.js} +261 -42
  299. package/dist/providers/vercel/skill.generated.js +2 -7
  300. package/dist/providers/vercel/tools.js +642 -0
  301. package/dist/redaction-identity.js +47 -0
  302. package/dist/redaction-marker.js +125 -0
  303. package/dist/registry.d.ts +30 -28
  304. package/dist/registry.js +446 -413
  305. package/dist/routes/access-tokens.js +1 -1
  306. package/dist/routes/actor-labels.js +1 -1
  307. package/dist/routes/connect.js +1 -1
  308. package/dist/routes/dispatch.js +103 -0
  309. package/dist/routes/mcp.js +170 -79
  310. package/dist/routes/oauth.js +3 -1
  311. package/dist/routes/operator.js +2 -2
  312. package/dist/routes/shared.d.ts +5 -4
  313. package/dist/routes/shared.js +244 -177
  314. package/dist/routes/skills.js +10 -8
  315. package/dist/routes/ui-config.js +27 -3
  316. package/dist/routes/ui-data.js +29 -22
  317. package/dist/routes/ui.js +1 -1
  318. package/dist/runtime/call-admission.js +0 -26
  319. package/dist/runtime/call-entry.js +30 -0
  320. package/dist/runtime/call.js +556 -0
  321. package/dist/runtime/connector-scope.js +7 -0
  322. package/dist/runtime/credential-probe.js +34 -0
  323. package/dist/runtime/executor.js +40 -0
  324. package/dist/runtime/native-storage.js +63 -0
  325. package/dist/runtime/registry.js +27 -0
  326. package/dist/runtime/request-scope.js +72 -0
  327. package/dist/runtime/run.js +15 -7
  328. package/dist/runtime/shared-read.js +34 -5
  329. package/dist/runtime/storage.js +34 -21
  330. package/dist/sent-secrets.d.ts +194 -37
  331. package/dist/sent-secrets.js +1743 -340
  332. package/dist/server.js +5 -56
  333. package/dist/skills.js +330 -224
  334. package/dist/sqlite.js +15 -14
  335. package/dist/storage/d1-copy.js +255 -0
  336. package/dist/storage/d1-driver.js +15 -0
  337. package/dist/storage/keys.js +28 -0
  338. package/dist/storage/sql-driver.js +88 -0
  339. package/dist/storage/sql-native.js +544 -0
  340. package/dist/storage/sql-schema.d.ts +6 -0
  341. package/dist/storage/sql-schema.js +15 -0
  342. package/dist/storage/sql.d.ts +14 -20
  343. package/dist/storage/sql.js +29 -535
  344. package/dist/timeout.js +0 -26
  345. package/dist/tool-safety.js +20 -10
  346. package/dist/types.d.ts +11 -99
  347. package/dist/upward.js +3 -0
  348. package/dist/usage-guide.js +3 -1
  349. package/dist/validate.d.ts +4 -2
  350. package/dist/validate.js +86 -9
  351. package/dist/version.d.ts +1 -1
  352. package/dist/version.js +1 -1
  353. package/dist/worker.js +312 -292
  354. package/dist/workspace-subject.js +5 -1
  355. package/dist/write-outcome.js +454 -34
  356. package/documentation/README.md +27 -7
  357. package/documentation/architecture.md +2550 -186
  358. package/documentation/auth.md +821 -98
  359. package/documentation/code-mode.md +56 -21
  360. package/documentation/deploying.md +164 -20
  361. package/documentation/hosted-mcp-migration.md +460 -0
  362. package/documentation/integrating.md +144 -105
  363. package/documentation/meta-tools.md +411 -34
  364. package/documentation/operating.md +28 -4
  365. package/documentation/operator-tests.md +11 -2
  366. package/documentation/operator-ui.md +103 -33
  367. package/documentation/provider-auth-migration.md +38 -63
  368. package/documentation/provider-migration-0.29.md +10 -5
  369. package/documentation/provider-migration-0.35.md +975 -0
  370. package/documentation/providers.md +965 -0
  371. package/examples/worker/AGENTS.md +23 -9
  372. package/examples/worker/README.md +254 -135
  373. package/examples/worker/alchemy.run.ts +116 -0
  374. package/examples/worker/gitignore +10 -0
  375. package/examples/worker/src/connecta.config.ts +23 -21
  376. package/examples/worker/wrangler.jsonc +14 -5
  377. package/guides/connecting-agents.md +157 -0
  378. package/guides/how-it-works.md +156 -0
  379. package/guides/safety-and-trust.md +153 -0
  380. package/package.json +27 -42
  381. package/templates/node/.env.example +3 -0
  382. package/templates/node/README.md +22 -2
  383. package/templates/node/docker-compose.yml +1 -0
  384. package/templates/node/package.json +3 -2
  385. package/templates/node/src/connecta.config.ts +8 -0
  386. package/dist/catalog-drift.d.ts +0 -134
  387. package/dist/catalog-drift.js +0 -493
  388. package/dist/providers/_shared/request-token.js +0 -83
  389. package/dist/providers/_shared/rest/operation-index.d.ts +0 -133
  390. package/dist/providers/_shared/rest/tools.d.ts +0 -141
  391. package/dist/providers/_shared/rest/value-safety.d.ts +0 -201
  392. package/dist/providers/basecamp/index.d.ts +0 -43
  393. package/dist/providers/basecamp/index.js +0 -997
  394. package/dist/providers/basecamp/skill.generated.js +0 -9
  395. package/dist/providers/cloudflare/rest.d.ts +0 -37
  396. package/dist/providers/cloudflare/rest.js +0 -1078
  397. package/dist/providers/github/hosted.js +0 -218
  398. package/dist/providers/github/rest.js +0 -321
  399. package/dist/providers/infisical/index.d.ts +0 -7
  400. package/dist/providers/infisical/index.js +0 -713
  401. package/dist/providers/infisical/skill.generated.js +0 -8
  402. package/dist/providers/linear/index.d.ts +0 -55
  403. package/dist/providers/linear/index.js +0 -352
  404. package/dist/providers/linear/skill.generated.js +0 -8
  405. package/dist/providers/mixpanel/index.d.ts +0 -57
  406. package/dist/providers/mixpanel/index.js +0 -468
  407. package/dist/providers/mixpanel/operations.js +0 -20
  408. package/dist/providers/mixpanel/rest.js +0 -603
  409. package/dist/providers/mixpanel/skill.generated.js +0 -10
  410. package/dist/providers/mixpanel/value-safety.js +0 -16
  411. package/dist/providers/notion/index.d.ts +0 -65
  412. package/dist/providers/notion/index.js +0 -368
  413. package/dist/providers/notion/openapi.generated.js +0 -75
  414. package/dist/providers/notion/rest.d.ts +0 -24
  415. package/dist/providers/notion/rest.js +0 -1226
  416. package/dist/providers/notion/skill.generated.js +0 -11
  417. package/dist/providers/notion/value-safety.js +0 -56
  418. package/dist/providers/revenuecat/index.d.ts +0 -49
  419. package/dist/providers/revenuecat/index.js +0 -557
  420. package/dist/providers/revenuecat/skill.generated.js +0 -11
  421. package/dist/providers/stripe/rest.d.ts +0 -14
  422. package/dist/providers/stripe/rest.js +0 -402
  423. package/dist/providers/vercel/rest.d.ts +0 -20
  424. package/dist/providers/vercel/rest.js +0 -1020
  425. package/dist/providers/wispr-flow/index.d.ts +0 -14
  426. package/dist/providers/wispr-flow/index.js +0 -117
  427. package/dist/providers/wispr-flow/skill.generated.js +0 -8
  428. /package/dist/providers/github/{key.js → lib/key.js} +0 -0
@@ -0,0 +1,853 @@
1
+ // CCB v2 curated projections, bound numbered pages and reviewed POST data search.
2
+ import { Effect, Schema } from "effect";
3
+ import { ConnectorCallError } from "../../errors.js";
4
+ import { checked } from "../_shared/rest/kit.js";
5
+ import { refuseWithheldValues } from "../_shared/rest/value-safety.js";
6
+ import { Refusal } from "../../http/errors.js";
7
+ import { Integer, isMinChars, isMaxChars } from "../../http/json-schema.js";
8
+ import { read, list } from "../../http/tools.js";
9
+ import { callCcb, DEFAULT_PER_PAGE, SEARCH_DOMAINS, CCB_INDEX, ccbPageInfo, } from "./api.js";
10
+ function asRecord(value) {
11
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
12
+ }
13
+ function asArray(value) {
14
+ return Array.isArray(value) ? value : [];
15
+ }
16
+ function compact(value) {
17
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined && entry !== null));
18
+ }
19
+ /** An object that is empty after compaction reads as absent. */
20
+ function present(value) {
21
+ return Object.keys(value).length > 0 ? value : undefined;
22
+ }
23
+ function phones(value) {
24
+ const phone = asRecord(value);
25
+ return present(compact({
26
+ mobile: phone["mobile"] || undefined,
27
+ home: phone["home"] || undefined,
28
+ work: phone["work"] || undefined,
29
+ }));
30
+ }
31
+ function address(value) {
32
+ const row = asRecord(value);
33
+ return present(compact({
34
+ street: row["street"] || undefined,
35
+ city: row["city"] || undefined,
36
+ state: row["state"] || undefined,
37
+ zip: row["zip"] || undefined,
38
+ country: row["country_iso"] || undefined,
39
+ }));
40
+ }
41
+ function projectPerson(value) {
42
+ const row = asRecord(value);
43
+ return compact({
44
+ id: row["id"],
45
+ name: row["name"],
46
+ firstName: row["first_name"],
47
+ lastName: row["last_name"],
48
+ email: row["email"] || undefined,
49
+ phones: phones(row["phone"]),
50
+ birthday: row["birthday"],
51
+ familyId: row["family_id"],
52
+ familyPosition: row["family_position"],
53
+ campusId: row["campus_id"],
54
+ membershipTypeId: row["membership_type_id"],
55
+ active: row["active"],
56
+ deceased: row["deceased"],
57
+ });
58
+ }
59
+ function projectIndividual(value) {
60
+ const row = asRecord(value);
61
+ const addresses = asRecord(row["addresses"]);
62
+ return compact({
63
+ ...projectPerson(row),
64
+ gender: row["gender"],
65
+ maritalStatus: row["marital_status"],
66
+ homeAddress: address(addresses["home"]),
67
+ mailingAddress: address(addresses["mailing"]),
68
+ campusName: row["campus_name"],
69
+ membershipTypeName: row["membership_type_name"],
70
+ membershipDate: row["membership_date"],
71
+ schoolGrade: row["school_grade"],
72
+ baptized: row["baptized"],
73
+ baptizedDate: row["baptized_date"],
74
+ lastAttendedDate: row["last_attended_date"],
75
+ limitedAccessUser: row["limited_access_user"],
76
+ listed: row["listed"],
77
+ created: row["created"],
78
+ modified: row["modified"],
79
+ customFields: present(Object.fromEntries(asArray(row["custom_fields"])
80
+ .map(asRecord)
81
+ .filter((field) => field["id"] !== undefined)
82
+ .map((field) => [String(field["id"]), field["value"]]))),
83
+ });
84
+ }
85
+ function projectFamily(value) {
86
+ const row = asRecord(value);
87
+ return compact({
88
+ id: row["id"],
89
+ lastName: row["last_name"],
90
+ address: address(row["address"]),
91
+ members: Array.isArray(row["members"]) ? row["members"].map(projectPerson) : undefined,
92
+ });
93
+ }
94
+ function ref(value) {
95
+ const row = asRecord(value);
96
+ return row["id"] === undefined && row["name"] === undefined
97
+ ? undefined
98
+ : compact({ id: row["id"], name: row["name"] });
99
+ }
100
+ function projectGroup(value) {
101
+ const row = asRecord(value);
102
+ return compact({
103
+ id: row["id"],
104
+ name: row["name"],
105
+ campusId: row["campus_id"],
106
+ inactive: row["inactive"],
107
+ groupType: asRecord(row["group_type"])["name"],
108
+ interactionType: row["interaction_type"],
109
+ membershipType: row["membership_type"],
110
+ mainLeader: ref(row["main_leader"]),
111
+ departmentId: asRecord(row["department"])["id"],
112
+ description: row["description"],
113
+ memberCount: row["member_count"],
114
+ childcare: row["childcare"],
115
+ listed: row["listed"],
116
+ full: row["full"],
117
+ meetDay: asRecord(row["meet_day"])["name"],
118
+ meetTime: asRecord(row["meet_time"])["name"],
119
+ area: asRecord(row["area"])["name"],
120
+ address: address(row["address"]),
121
+ });
122
+ }
123
+ function projectMembership(value) {
124
+ const row = asRecord(value);
125
+ const person = asRecord(row["individual"]);
126
+ const group = asRecord(row["group"]);
127
+ return compact({
128
+ groupId: row["group_id"],
129
+ individualId: row["individual_id"],
130
+ status: row["status"],
131
+ dateAdded: row["date_added"],
132
+ name: person["name"],
133
+ email: person["email"] || undefined,
134
+ phones: phones(person["phone"]),
135
+ groupName: group["name"],
136
+ groupType: asRecord(group["group_type"])["name"],
137
+ groupInactive: group["inactive"],
138
+ });
139
+ }
140
+ function projectOccurrence(value) {
141
+ const row = asRecord(value);
142
+ const event = asRecord(row["event"]);
143
+ const group = asRecord(event["group"]);
144
+ return compact({
145
+ eventId: row["event_id"] ?? event["id"],
146
+ occurrence: row["occurrence"],
147
+ start: row["start"],
148
+ end: row["end"],
149
+ name: event["name"],
150
+ campusId: event["campus_id"],
151
+ recurs: event["recurs"],
152
+ groupId: group["id"] === undefined ? undefined : Number(group["id"]),
153
+ groupName: group["name"],
154
+ });
155
+ }
156
+ function projectEvent(value) {
157
+ const row = asRecord(value);
158
+ const attendance = asRecord(row["attendance"]);
159
+ return compact({
160
+ id: row["id"],
161
+ name: row["name"],
162
+ description: row["description"],
163
+ campusId: row["campus_id"],
164
+ start: row["start"],
165
+ end: row["end"],
166
+ recurs: row["recurs"],
167
+ recurEndDate: row["recur_end_date"],
168
+ approvalStatus: row["approval_status"],
169
+ address: address(row["address"]),
170
+ guestCounts: present(compact({ ...asRecord(row["guest_counts"]) })),
171
+ group: ref(row["group"]),
172
+ attendance: present(compact({
173
+ status: attendance["status"],
174
+ totalAttendance: attendance["total_attendance"],
175
+ visitors: attendance["visitors"],
176
+ })),
177
+ });
178
+ }
179
+ function projectAttendance(value) {
180
+ const row = asRecord(value);
181
+ return compact({
182
+ eventId: row["event_id"],
183
+ occurrence: row["occurrence"],
184
+ status: row["status"],
185
+ totalAttendance: row["total_attendance"],
186
+ visitors: row["visitors"],
187
+ topic: row["topic"],
188
+ });
189
+ }
190
+ function projectAttendee(value) {
191
+ const row = asRecord(value);
192
+ const person = asRecord(row["individual"]);
193
+ return compact({
194
+ individualId: row["individual_id"] ?? person["id"],
195
+ name: person["name"],
196
+ familyId: person["family_id"],
197
+ occurrenceDate: row["occurrence_date"],
198
+ });
199
+ }
200
+ function projectNote(value) {
201
+ const row = asRecord(value);
202
+ return compact({
203
+ id: row["id"],
204
+ individualId: row["individual_id"],
205
+ note: row["note"],
206
+ date: row["date"],
207
+ sharingLevel: row["sharing_level"],
208
+ context: row["context"],
209
+ contextId: row["context_id"],
210
+ creator: ref(row["creator"]),
211
+ });
212
+ }
213
+ const PERSON_SCHEMA = Schema.Struct({
214
+ "id": Schema.optionalKey(Integer),
215
+ "name": Schema.optionalKey(Schema.String),
216
+ "firstName": Schema.optionalKey(Schema.String),
217
+ "lastName": Schema.optionalKey(Schema.String),
218
+ "email": Schema.optionalKey(Schema.String),
219
+ "phones": Schema.optionalKey(Schema.Struct({
220
+ "mobile": Schema.optionalKey(Schema.String),
221
+ "home": Schema.optionalKey(Schema.String),
222
+ "work": Schema.optionalKey(Schema.String),
223
+ })),
224
+ "birthday": Schema.optionalKey(Schema.String),
225
+ "familyId": Schema.optionalKey(Integer),
226
+ "familyPosition": Schema.optionalKey(Schema.String),
227
+ "campusId": Schema.optionalKey(Integer),
228
+ "membershipTypeId": Schema.optionalKey(Integer),
229
+ "active": Schema.optionalKey(Schema.Boolean),
230
+ "deceased": Schema.optionalKey(Schema.String),
231
+ });
232
+ const INDIVIDUAL_SCHEMA = Schema.Struct({
233
+ "id": Schema.optionalKey(Integer),
234
+ "name": Schema.optionalKey(Schema.String),
235
+ "firstName": Schema.optionalKey(Schema.String),
236
+ "lastName": Schema.optionalKey(Schema.String),
237
+ "email": Schema.optionalKey(Schema.String),
238
+ "phones": Schema.optionalKey(Schema.Struct({
239
+ "mobile": Schema.optionalKey(Schema.String),
240
+ "home": Schema.optionalKey(Schema.String),
241
+ "work": Schema.optionalKey(Schema.String),
242
+ })),
243
+ "birthday": Schema.optionalKey(Schema.String),
244
+ "familyId": Schema.optionalKey(Integer),
245
+ "familyPosition": Schema.optionalKey(Schema.String),
246
+ "campusId": Schema.optionalKey(Integer),
247
+ "membershipTypeId": Schema.optionalKey(Integer),
248
+ "active": Schema.optionalKey(Schema.Boolean),
249
+ "deceased": Schema.optionalKey(Schema.String),
250
+ "gender": Schema.optionalKey(Schema.String),
251
+ "maritalStatus": Schema.optionalKey(Schema.String),
252
+ "homeAddress": Schema.optionalKey(Schema.Struct({
253
+ "street": Schema.optionalKey(Schema.String),
254
+ "city": Schema.optionalKey(Schema.String),
255
+ "state": Schema.optionalKey(Schema.String),
256
+ "zip": Schema.optionalKey(Schema.String),
257
+ "country": Schema.optionalKey(Schema.String),
258
+ })),
259
+ "mailingAddress": Schema.optionalKey(Schema.Struct({
260
+ "street": Schema.optionalKey(Schema.String),
261
+ "city": Schema.optionalKey(Schema.String),
262
+ "state": Schema.optionalKey(Schema.String),
263
+ "zip": Schema.optionalKey(Schema.String),
264
+ "country": Schema.optionalKey(Schema.String),
265
+ })),
266
+ "campusName": Schema.optionalKey(Schema.String),
267
+ "membershipTypeName": Schema.optionalKey(Schema.String),
268
+ "membershipDate": Schema.optionalKey(Schema.String),
269
+ "schoolGrade": Schema.optionalKey(Schema.String),
270
+ "baptized": Schema.optionalKey(Schema.Boolean),
271
+ "baptizedDate": Schema.optionalKey(Schema.String),
272
+ "lastAttendedDate": Schema.optionalKey(Schema.String),
273
+ "limitedAccessUser": Schema.optionalKey(Schema.Boolean),
274
+ "listed": Schema.optionalKey(Schema.Boolean),
275
+ "created": Schema.optionalKey(Schema.String),
276
+ "modified": Schema.optionalKey(Schema.String),
277
+ "customFields": Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown)),
278
+ });
279
+ const FAMILY_SCHEMA = Schema.Struct({
280
+ "id": Schema.optionalKey(Integer),
281
+ "lastName": Schema.optionalKey(Schema.String),
282
+ "address": Schema.optionalKey(Schema.Struct({
283
+ "street": Schema.optionalKey(Schema.String),
284
+ "city": Schema.optionalKey(Schema.String),
285
+ "state": Schema.optionalKey(Schema.String),
286
+ "zip": Schema.optionalKey(Schema.String),
287
+ "country": Schema.optionalKey(Schema.String),
288
+ })),
289
+ "members": Schema.optionalKey(Schema.Array(PERSON_SCHEMA)),
290
+ });
291
+ const GROUP_DETAIL_SCHEMA = Schema.Struct({
292
+ "id": Schema.optionalKey(Integer),
293
+ "name": Schema.optionalKey(Schema.String),
294
+ "campusId": Schema.optionalKey(Integer),
295
+ "inactive": Schema.optionalKey(Schema.Boolean),
296
+ "groupType": Schema.optionalKey(Schema.String),
297
+ "interactionType": Schema.optionalKey(Schema.String),
298
+ "membershipType": Schema.optionalKey(Schema.String),
299
+ "mainLeader": Schema.optionalKey(Schema.Struct({ "id": Schema.optionalKey(Integer), "name": Schema.optionalKey(Schema.String) })),
300
+ "departmentId": Schema.optionalKey(Integer),
301
+ "description": Schema.optionalKey(Schema.String),
302
+ "memberCount": Schema.optionalKey(Integer),
303
+ "childcare": Schema.optionalKey(Schema.Boolean),
304
+ "listed": Schema.optionalKey(Schema.Boolean),
305
+ "full": Schema.optionalKey(Schema.Boolean),
306
+ "meetDay": Schema.optionalKey(Schema.String),
307
+ "meetTime": Schema.optionalKey(Schema.String),
308
+ "area": Schema.optionalKey(Schema.String),
309
+ "address": Schema.optionalKey(Schema.Struct({
310
+ "street": Schema.optionalKey(Schema.String),
311
+ "city": Schema.optionalKey(Schema.String),
312
+ "state": Schema.optionalKey(Schema.String),
313
+ "zip": Schema.optionalKey(Schema.String),
314
+ "country": Schema.optionalKey(Schema.String),
315
+ })),
316
+ });
317
+ const MEMBERSHIP_SCHEMA = Schema.Struct({
318
+ "groupId": Schema.optionalKey(Integer),
319
+ "individualId": Schema.optionalKey(Integer),
320
+ "status": Schema.optionalKey(Schema.String),
321
+ "dateAdded": Schema.optionalKey(Schema.String),
322
+ "name": Schema.optionalKey(Schema.String),
323
+ "email": Schema.optionalKey(Schema.String),
324
+ "phones": Schema.optionalKey(Schema.Struct({
325
+ "mobile": Schema.optionalKey(Schema.String),
326
+ "home": Schema.optionalKey(Schema.String),
327
+ "work": Schema.optionalKey(Schema.String),
328
+ })),
329
+ "groupName": Schema.optionalKey(Schema.String),
330
+ "groupType": Schema.optionalKey(Schema.String),
331
+ "groupInactive": Schema.optionalKey(Schema.Boolean),
332
+ });
333
+ const OCCURRENCE_SCHEMA = Schema.Struct({
334
+ "eventId": Schema.optionalKey(Integer),
335
+ "occurrence": Schema.optionalKey(Schema.String),
336
+ "start": Schema.optionalKey(Schema.String),
337
+ "end": Schema.optionalKey(Schema.String),
338
+ "name": Schema.optionalKey(Schema.String),
339
+ "campusId": Schema.optionalKey(Integer),
340
+ "recurs": Schema.optionalKey(Schema.Boolean),
341
+ "groupId": Schema.optionalKey(Integer),
342
+ "groupName": Schema.optionalKey(Schema.String),
343
+ });
344
+ const EVENT_SCHEMA = Schema.Struct({
345
+ "id": Schema.optionalKey(Integer),
346
+ "name": Schema.optionalKey(Schema.String),
347
+ "description": Schema.optionalKey(Schema.String),
348
+ "campusId": Schema.optionalKey(Integer),
349
+ "start": Schema.optionalKey(Schema.String),
350
+ "end": Schema.optionalKey(Schema.String),
351
+ "recurs": Schema.optionalKey(Schema.Boolean),
352
+ "recurEndDate": Schema.optionalKey(Schema.String),
353
+ "approvalStatus": Schema.optionalKey(Schema.String),
354
+ "address": Schema.optionalKey(Schema.Struct({
355
+ "street": Schema.optionalKey(Schema.String),
356
+ "city": Schema.optionalKey(Schema.String),
357
+ "state": Schema.optionalKey(Schema.String),
358
+ "zip": Schema.optionalKey(Schema.String),
359
+ "country": Schema.optionalKey(Schema.String),
360
+ })),
361
+ "guestCounts": Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown)),
362
+ "group": Schema.optionalKey(Schema.Struct({ "id": Schema.optionalKey(Integer), "name": Schema.optionalKey(Schema.String) })),
363
+ "attendance": Schema.optionalKey(Schema.Struct({
364
+ "status": Schema.optionalKey(Schema.String),
365
+ "totalAttendance": Schema.optionalKey(Integer),
366
+ "visitors": Schema.optionalKey(Integer),
367
+ })),
368
+ });
369
+ const ATTENDANCE_SCHEMA = Schema.Struct({
370
+ "eventId": Schema.optionalKey(Integer),
371
+ "occurrence": Schema.optionalKey(Schema.String),
372
+ "status": Schema.optionalKey(Schema.String),
373
+ "totalAttendance": Schema.optionalKey(Integer),
374
+ "visitors": Schema.optionalKey(Integer),
375
+ "topic": Schema.optionalKey(Schema.String),
376
+ });
377
+ const ATTENDEE_SCHEMA = Schema.Struct({
378
+ "individualId": Schema.optionalKey(Integer),
379
+ "name": Schema.optionalKey(Schema.String),
380
+ "familyId": Schema.optionalKey(Integer),
381
+ "occurrenceDate": Schema.optionalKey(Schema.String),
382
+ });
383
+ const NOTE_SCHEMA = Schema.Struct({
384
+ "id": Schema.optionalKey(Integer),
385
+ "individualId": Schema.optionalKey(Integer),
386
+ "note": Schema.optionalKey(Schema.String),
387
+ "date": Schema.optionalKey(Schema.String),
388
+ "sharingLevel": Schema.optionalKey(Schema.String),
389
+ "context": Schema.optionalKey(Schema.String),
390
+ "contextId": Schema.optionalKey(Integer),
391
+ "creator": Schema.optionalKey(Schema.Struct({ "id": Schema.optionalKey(Integer), "name": Schema.optionalKey(Schema.String) })),
392
+ });
393
+ const ME_SCHEMA = Schema.Struct({
394
+ "id": Schema.optionalKey(Integer),
395
+ "name": Schema.optionalKey(Schema.String),
396
+ "email": Schema.optionalKey(Schema.String),
397
+ "username": Schema.optionalKey(Schema.String),
398
+ "familyId": Schema.optionalKey(Integer),
399
+ "campusId": Schema.optionalKey(Integer),
400
+ "userTypes": Schema.optionalKey(Schema.Array(Schema.String)),
401
+ });
402
+ function compactDate(value) {
403
+ return typeof value === "string" ? value.replace(/-/g, "") : undefined;
404
+ }
405
+ export function ccbTools({ connection, options, }) {
406
+ const limit = {
407
+ default: options.defaultPerPage ?? DEFAULT_PER_PAGE,
408
+ max: 100,
409
+ values: [25, 50, 75, 100],
410
+ description: "Allowed page sizes are 25, 50, 75, and 100. The vendor default is 25.",
411
+ };
412
+ const request = (req) => callCcb(connection, req);
413
+ const id = (value) => encodeURIComponent(String(value));
414
+ const one = (path, project, query = {}) => request({ method: "GET", path, query }).pipe(Effect.map(({ body }) => project(body)));
415
+ const fetchPage = (path, args, project, query = {}, cursor, body) => Effect.gen(function* () {
416
+ const size = Number(args.limit ?? limit.default);
417
+ let page = 1;
418
+ if (cursor) {
419
+ const saved = JSON.parse(cursor);
420
+ if (saved.revision !== CCB_INDEX.revision)
421
+ return yield* fail(new ConnectorCallError("invalid_args", "This CCB cursor belongs to a different API revision; start a new list."));
422
+ if (!Number.isSafeInteger(saved.page) || saved.page < 1)
423
+ return yield* fail(new ConnectorCallError("invalid_args", "This CCB cursor contains no valid page number."));
424
+ if (saved.limit !== size)
425
+ return yield* fail(new ConnectorCallError("invalid_args", "Keep the same limit when continuing this CCB page."));
426
+ page = saved.page;
427
+ }
428
+ const answer = yield* request({
429
+ method: body === undefined ? "GET" : "POST",
430
+ path,
431
+ query: { ...query, page, per_page: size },
432
+ ...(body === undefined ? {} : { body }),
433
+ });
434
+ if (path === "/search/schedules_totals/results" &&
435
+ answer.body &&
436
+ typeof answer.body === "object" &&
437
+ !Array.isArray(answer.body))
438
+ return { rows: [project(answer.body)], page: { hasMore: false, nextCursor: null } };
439
+ if (!Array.isArray(answer.body))
440
+ return yield* fail(new ConnectorCallError("connector_call_failed", "CCB returned a list without an array.", {
441
+ retryable: false,
442
+ }));
443
+ const rows = answer.body;
444
+ const totalText = answer.headers.get("x-total");
445
+ const total = yield* checked(() => {
446
+ if (totalText === null || totalText === "")
447
+ return undefined;
448
+ if (!/^(0|[1-9]\d*)$/.test(totalText) || !Number.isSafeInteger(Number(totalText)))
449
+ throw new ConnectorCallError("connector_call_failed", "CCB returned an invalid exact total.", {
450
+ retryable: false,
451
+ });
452
+ return Number(totalText);
453
+ });
454
+ const next = yield* checked(() => ccbPageInfo(Object.fromEntries(answer.headers), page, size, rows.length));
455
+ return {
456
+ rows: rows.map(project),
457
+ page: {
458
+ ...(total === undefined ? {} : { total }),
459
+ hasMore: next !== null,
460
+ nextCursor: next === null ? null : JSON.stringify({ page: next, limit: size, revision: CCB_INDEX.revision }),
461
+ },
462
+ };
463
+ });
464
+ return [
465
+ read(connection, {
466
+ name: "get_me",
467
+ description: "Get the CCB individual the access token belongs to. Under Identity Auth that is the signed-in person whose permissions every call carries.",
468
+ input: Schema.Struct({}),
469
+ output: ME_SCHEMA,
470
+ fields: true,
471
+ run: () => Effect.gen(function* () {
472
+ const { body } = yield* request({ method: "GET", path: "/me" });
473
+ const row = asRecord(body);
474
+ return compact({
475
+ id: row["id"],
476
+ name: row["name"],
477
+ email: row["email"] || undefined,
478
+ username: row["username"],
479
+ familyId: row["family_id"],
480
+ campusId: row["campus_id"],
481
+ userTypes: Array.isArray(row["user_types"]) ? row["user_types"] : undefined,
482
+ });
483
+ }),
484
+ }),
485
+ list(connection, {
486
+ name: "list_individuals",
487
+ description: "Find CCB individuals by partial name, phone, or email. Returns lean profiles with family and campus ids; not the advanced search.",
488
+ filters: {
489
+ "query": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({
490
+ description: "Partial name, phone number, or email. Omit to page everyone.",
491
+ })),
492
+ "includeInactive": Schema.optionalKey(Schema.Boolean.annotate({ description: "Include inactive individuals." })),
493
+ "includeDeceased": Schema.optionalKey(Schema.Boolean.annotate({ description: "Include deceased individuals." })),
494
+ "campusScope": Schema.optionalKey(Schema.Literals(["all", "current", "other"]).annotate({
495
+ description: "Campuses to search relative to the connection's own.",
496
+ })),
497
+ },
498
+ row: PERSON_SCHEMA,
499
+ limit,
500
+ total: true,
501
+ cursor: "bound",
502
+ page: (args, cursor) => Effect.gen(function* () {
503
+ return yield* fetchPage("/individuals", args, projectPerson, {
504
+ name: args["query"],
505
+ include_inactive: args["includeInactive"],
506
+ include_deceased: args["includeDeceased"],
507
+ campus_scope: args["campusScope"],
508
+ }, cursor);
509
+ }),
510
+ }),
511
+ read(connection, {
512
+ name: "get_individual",
513
+ description: "Get one CCB individual's profile: contact, addresses, membership, and custom fields. CCB allows one call a second; prefer list_individuals for many people.",
514
+ input: Schema.Struct({
515
+ "individualId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
516
+ description: "Individual id from list_individuals.",
517
+ }),
518
+ }),
519
+ output: INDIVIDUAL_SCHEMA,
520
+ fields: true,
521
+ run: (args) => Effect.gen(function* () {
522
+ return yield* one(`/individuals/${id(args["individualId"])}`, projectIndividual, {});
523
+ }),
524
+ }),
525
+ list(connection, {
526
+ name: "list_families",
527
+ description: "Find CCB families by partial last name, email, or mobile phone. Returns family ids and addresses; get_family lists the members.",
528
+ filters: {
529
+ "lastName": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({ description: "Partial last name." })),
530
+ "email": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({ description: "Partial email." })),
531
+ "phone": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(50)).annotate({ description: "Partial mobile phone." })),
532
+ },
533
+ row: FAMILY_SCHEMA,
534
+ limit,
535
+ total: true,
536
+ cursor: "bound",
537
+ page: (args, cursor) => Effect.gen(function* () {
538
+ return yield* fetchPage("/families", args, projectFamily, {
539
+ last_name: args["lastName"],
540
+ email: args["email"],
541
+ phone: args["phone"],
542
+ }, cursor);
543
+ }),
544
+ }),
545
+ read(connection, {
546
+ name: "get_family",
547
+ description: "Get one CCB family with every member's lean profile and family position.",
548
+ input: Schema.Struct({
549
+ "familyId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
550
+ description: "Family id from an individual's familyId or list_families.",
551
+ }),
552
+ "includeInactive": Schema.optionalKey(Schema.Boolean.annotate({ description: "Include inactive members." })),
553
+ "includeDeceased": Schema.optionalKey(Schema.Boolean.annotate({ description: "Include deceased members." })),
554
+ }),
555
+ output: FAMILY_SCHEMA,
556
+ fields: true,
557
+ run: (args) => Effect.gen(function* () {
558
+ return yield* one(`/families/${id(args["familyId"])}`, projectFamily, {
559
+ include_inactive: args["includeInactive"],
560
+ include_deceased: args["includeDeceased"],
561
+ });
562
+ }),
563
+ }),
564
+ list(connection, {
565
+ name: "list_groups",
566
+ description: "List or search CCB groups by partial name, optionally for one campus. Returns group type, leader, and membership mode.",
567
+ filters: {
568
+ "name": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({ description: "Partial group name." })),
569
+ "campusId": Schema.optionalKey(Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({ description: "Only groups at this campus." })),
570
+ },
571
+ row: GROUP_DETAIL_SCHEMA,
572
+ limit,
573
+ total: true,
574
+ cursor: "bound",
575
+ page: (args, cursor) => Effect.gen(function* () {
576
+ return yield* fetchPage("/groups", args, projectGroup, {
577
+ name: args["name"],
578
+ campus_ids: args["campusId"] === undefined ? undefined : [args["campusId"]],
579
+ }, cursor);
580
+ }),
581
+ }),
582
+ read(connection, {
583
+ name: "get_group",
584
+ description: "Get one CCB group: description, member count, meeting day, time, area, and address.",
585
+ input: Schema.Struct({
586
+ "groupId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
587
+ description: "Group id from list_groups.",
588
+ }),
589
+ }),
590
+ output: GROUP_DETAIL_SCHEMA,
591
+ fields: true,
592
+ run: (args) => Effect.gen(function* () {
593
+ return yield* one(`/groups/${id(args["groupId"])}`, projectGroup, {});
594
+ }),
595
+ }),
596
+ list(connection, {
597
+ name: "list_group_members",
598
+ description: "List one CCB group's participants with role and date added. Filter by leader or member status, or partial name.",
599
+ filters: {
600
+ "groupId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
601
+ description: "Group id from list_groups.",
602
+ }),
603
+ "status": Schema.optionalKey(Schema.Literals(["all", "leader", "member"]).annotate({ description: "Participant role filter." })),
604
+ "name": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({ description: "Partial participant name." })),
605
+ },
606
+ row: MEMBERSHIP_SCHEMA,
607
+ limit,
608
+ total: true,
609
+ cursor: "bound",
610
+ page: (args, cursor) => Effect.gen(function* () {
611
+ return yield* fetchPage(`/groups/${id(args["groupId"])}/members`, args, projectMembership, {
612
+ status: args["status"],
613
+ name: args["name"],
614
+ }, cursor);
615
+ }),
616
+ }),
617
+ list(connection, {
618
+ name: "list_individual_groups",
619
+ description: "List the CCB groups one individual belongs to, with their role. Defaults to member and leader roles.",
620
+ filters: {
621
+ "individualId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({ description: "Individual id." }),
622
+ "includeInactive": Schema.optionalKey(Schema.Boolean.annotate({ description: "List inactive groups instead of active ones." })),
623
+ },
624
+ row: MEMBERSHIP_SCHEMA,
625
+ limit,
626
+ total: true,
627
+ cursor: "bound",
628
+ page: (args, cursor) => Effect.gen(function* () {
629
+ return yield* fetchPage(`/individuals/${id(args["individualId"])}/groups`, args, projectMembership, {
630
+ inactive: args["includeInactive"],
631
+ }, cursor);
632
+ }),
633
+ }),
634
+ list(connection, {
635
+ name: "list_events",
636
+ description: "List CCB event occurrences by name and time range. Each row's eventId and occurrence feed the attendance tools.",
637
+ filters: {
638
+ "name": Schema.optionalKey(Schema.String.check(isMinChars(1), isMaxChars(200)).annotate({ description: "Partial event name." })),
639
+ "range": Schema.optionalKey(Schema.Literals(["ALL", "PAST", "CURRENT", "FUTURE"]).annotate({
640
+ description: "Time range relative to now.",
641
+ })),
642
+ },
643
+ row: OCCURRENCE_SCHEMA,
644
+ limit,
645
+ total: true,
646
+ cursor: "bound",
647
+ page: (args, cursor) => Effect.gen(function* () {
648
+ return yield* fetchPage("/events", args, projectOccurrence, {
649
+ name: args["name"],
650
+ range_type: args["range"],
651
+ }, cursor);
652
+ }),
653
+ }),
654
+ read(connection, {
655
+ name: "get_event",
656
+ description: "Get one CCB event's details, optionally for one occurrence with its attendance totals.",
657
+ input: Schema.Struct({
658
+ "eventId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
659
+ description: "Event id from list_events.",
660
+ }),
661
+ "occurrence": Schema.optionalKey(Schema.String.check(pattern("^\\d{4}-?\\d{2}-?\\d{2}$")).annotate({
662
+ description: "Occurrence date, YYYYMMDD or YYYY-MM-DD. Omit for the series.",
663
+ })),
664
+ "withAttendance": Schema.optionalKey(Schema.Boolean.annotate({ description: "Add attendance totals for the occurrence." })),
665
+ }),
666
+ output: EVENT_SCHEMA,
667
+ fields: true,
668
+ run: (args) => Effect.gen(function* () {
669
+ return yield* one(`/events/${id(args["eventId"])}`, projectEvent, {
670
+ occurrence: compactDate(args["occurrence"]),
671
+ attendance_info: args["withAttendance"],
672
+ });
673
+ }),
674
+ }),
675
+ read(connection, {
676
+ name: "get_event_attendance",
677
+ description: "Get one CCB event occurrence's attendance summary: met or not, totals, visitors, topic. Drops leader notes and prayer requests from the named projection.",
678
+ input: Schema.Struct({
679
+ "eventId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
680
+ description: "Event id from list_events.",
681
+ }),
682
+ "occurrence": Schema.String.check(pattern("^\\d{4}-?\\d{2}-?\\d{2}$")).annotate({
683
+ description: "Occurrence date, YYYYMMDD or YYYY-MM-DD, from list_events.",
684
+ }),
685
+ }),
686
+ output: ATTENDANCE_SCHEMA,
687
+ fields: true,
688
+ run: (args) => Effect.gen(function* () {
689
+ return yield* one(`/events/${id(args["eventId"])}/attendance/${compactDate(args["occurrence"])}`, projectAttendance, {});
690
+ }),
691
+ }),
692
+ list(connection, {
693
+ name: "list_event_attendees",
694
+ description: "List who attended one CCB event occurrence. Returns individual ids and names.",
695
+ filters: {
696
+ "eventId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
697
+ description: "Event id from list_events.",
698
+ }),
699
+ "occurrence": Schema.String.check(pattern("^\\d{4}-?\\d{2}-?\\d{2}$")).annotate({
700
+ description: "Occurrence date, YYYYMMDD or YYYY-MM-DD, from list_events.",
701
+ }),
702
+ },
703
+ row: ATTENDEE_SCHEMA,
704
+ limit,
705
+ total: true,
706
+ cursor: "bound",
707
+ page: (args, cursor) => Effect.gen(function* () {
708
+ return yield* fetchPage(`/events/${id(args["eventId"])}/attendance/${compactDate(args["occurrence"])}/attendees`, args, projectAttendee, {}, cursor);
709
+ }),
710
+ }),
711
+ list(connection, {
712
+ name: "list_individual_notes",
713
+ description: "List the notes on one CCB individual that the connection may read, with sharing level and context. Pastoral content; reduce before returning.",
714
+ filters: {
715
+ "individualId": Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({ description: "Individual id." }),
716
+ "context": Schema.optionalKey(Schema.Literals(["GROUP", "DEPARTMENT", "PROCESS_QUEUE", "GENERAL"]).annotate({
717
+ description: "Only notes in this context.",
718
+ })),
719
+ },
720
+ row: NOTE_SCHEMA,
721
+ limit,
722
+ total: true,
723
+ cursor: "bound",
724
+ page: (args, cursor) => Effect.gen(function* () {
725
+ return yield* fetchPage(`/individuals/${id(args["individualId"])}/notes`, args, projectNote, {
726
+ context: args["context"] === undefined ? undefined : [args["context"]],
727
+ include_creator: true,
728
+ }, cursor);
729
+ }),
730
+ }),
731
+ read(connection, {
732
+ name: "get_giving_metrics",
733
+ description: "Get gift counts by period for one CCB individual or family, over at most 12 months. No per-gift amounts or transactions; pledges and scheduled gifts are available through indexed reads.",
734
+ input: Schema.Struct({
735
+ "individualId": Schema.optionalKey(Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
736
+ description: "Individual id. Exactly one of individualId or familyId.",
737
+ })),
738
+ "familyId": Schema.optionalKey(Integer.check(Schema.isGreaterThanOrEqualTo(1)).annotate({
739
+ description: "Family id. Exactly one of individualId or familyId.",
740
+ })),
741
+ "start": Schema.optionalKey(Schema.String.check(pattern("^\\d{4}-\\d{2}-\\d{2}$")).annotate({
742
+ description: "Start date, YYYY-MM-DD. CCB caps the range at 12 months.",
743
+ })),
744
+ "end": Schema.optionalKey(Schema.String.check(pattern("^\\d{4}-\\d{2}-\\d{2}$")).annotate({
745
+ description: "End date, YYYY-MM-DD.",
746
+ })),
747
+ }),
748
+ output: Schema.Struct({
749
+ "periods": Schema.optionalKey(Schema.Array(Schema.Struct({
750
+ "start": Schema.optionalKey(Schema.String),
751
+ "count": Schema.optionalKey(Integer),
752
+ "members": Schema.optionalKey(Schema.Array(Schema.Struct({ "individualId": Schema.optionalKey(Integer), "count": Schema.optionalKey(Integer) }))),
753
+ }))),
754
+ }),
755
+ fields: true,
756
+ run: (args) => Effect.gen(function* () {
757
+ const individual = args["individualId"] !== undefined;
758
+ if (individual === (args["familyId"] !== undefined)) {
759
+ return yield* fail(new ConnectorCallError("invalid_args", "Pass exactly one of individualId or familyId."));
760
+ }
761
+ if (typeof args["start"] === "string" &&
762
+ typeof args["end"] === "string" &&
763
+ Date.parse(args["end"]) - Date.parse(args["start"]) > 366 * DAY_MS) {
764
+ return yield* fail(new ConnectorCallError("invalid_args", "CCB caps giving metrics at a 12-month range; narrow start and end."));
765
+ }
766
+ const path = individual
767
+ ? `/individuals/${id(args["individualId"])}/metrics/giving`
768
+ : `/families/${id(args["familyId"])}/metrics/giving`;
769
+ const { body } = yield* request({ method: "GET", path, query: { start: args["start"], end: args["end"] } });
770
+ const rows = asArray(body);
771
+ return {
772
+ periods: rows.map((value) => {
773
+ const row = asRecord(value);
774
+ return compact({
775
+ start: row["start"] ?? row["date"],
776
+ count: row["count"],
777
+ members: Array.isArray(row["members"])
778
+ ? row["members"].map((member) => {
779
+ const item = asRecord(member);
780
+ return compact({ individualId: item["id"], count: item["count"] });
781
+ })
782
+ : undefined,
783
+ });
784
+ }),
785
+ };
786
+ }),
787
+ }),
788
+ list(connection, {
789
+ name: "search_records",
790
+ review: "CCB documents the indexed advanced-search result POSTs as read-only data searches.",
791
+ description: "Search CCB church records with a reviewed read-only POST. Returns common identifiers, name, status and contact summaries; use the indexed read hatch for domain-specific response fields.",
792
+ filters: {
793
+ domain: Schema.String.check(pattern(`^(${SEARCH_DOMAINS.join("|")})$`)).annotate({
794
+ description: "Reviewed advanced-search domain; the pattern lists every allowed value.",
795
+ }),
796
+ body: Schema.Record(Schema.String, Schema.Unknown).annotate({
797
+ description: "Vendor search configuration and filters; get the operation details before choosing them.",
798
+ }),
799
+ },
800
+ row: Schema.Struct({
801
+ id: Schema.optionalKey(Integer),
802
+ name: Schema.optionalKey(Schema.String),
803
+ individualId: Schema.optionalKey(Integer),
804
+ groupId: Schema.optionalKey(Integer),
805
+ status: Schema.optionalKey(Schema.String),
806
+ active: Schema.optionalKey(Schema.Boolean),
807
+ campusId: Schema.optionalKey(Integer),
808
+ familyId: Schema.optionalKey(Integer),
809
+ membershipTypeId: Schema.optionalKey(Integer),
810
+ email: Schema.optionalKey(Schema.String),
811
+ counts: Schema.optionalKey(Schema.Struct({
812
+ stillNeeded: Schema.optionalKey(Integer),
813
+ needed: Schema.optionalKey(Integer),
814
+ accepted: Schema.optionalKey(Integer),
815
+ checkedIn: Schema.optionalKey(Integer),
816
+ declined: Schema.optionalKey(Integer),
817
+ pending: Schema.optionalKey(Integer),
818
+ })),
819
+ }),
820
+ limit,
821
+ total: true,
822
+ cursor: "bound",
823
+ page: (args, cursor) => checked(() => refuseWithheldValues(args.body, "search_records")).pipe(Effect.andThen(fetchPage("/search/" + args.domain + "/results", args, (value) => {
824
+ const row = asRecord(value);
825
+ return compact({
826
+ id: row.id,
827
+ name: row.name ?? row.title,
828
+ individualId: row.individual_id,
829
+ groupId: row.group_id,
830
+ status: row.status,
831
+ active: row.active,
832
+ campusId: row.campus_id,
833
+ familyId: row.family_id,
834
+ membershipTypeId: row.membership_type_id,
835
+ email: row.email,
836
+ counts: args.domain === "schedules_totals"
837
+ ? compact({
838
+ stillNeeded: row.still_needed,
839
+ needed: row.needed,
840
+ accepted: row.accepted,
841
+ checkedIn: row.checked_in,
842
+ declined: row.declined,
843
+ pending: row.pending,
844
+ })
845
+ : undefined,
846
+ });
847
+ }, {}, cursor, args.body))),
848
+ }),
849
+ ];
850
+ }
851
+ const DAY_MS = 86400000;
852
+ const fail = (error) => Effect.fail(new Refusal({ error }));
853
+ const pattern = (source) => Schema.makeFilter((value) => new RegExp(source).test(value), { toJsonSchema: () => ({ pattern: source }) });