@enricai/barnacle 1.0.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 (448) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +958 -0
  3. package/dist/api/errors.d.ts +88 -0
  4. package/dist/api/errors.d.ts.map +1 -0
  5. package/dist/api/errors.js +164 -0
  6. package/dist/api/errors.js.map +1 -0
  7. package/dist/api/helpers/envelope.d.ts +13 -0
  8. package/dist/api/helpers/envelope.d.ts.map +1 -0
  9. package/dist/api/helpers/envelope.js +20 -0
  10. package/dist/api/helpers/envelope.js.map +1 -0
  11. package/dist/api/helpers/reply.d.ts +9 -0
  12. package/dist/api/helpers/reply.d.ts.map +1 -0
  13. package/dist/api/helpers/reply.js +14 -0
  14. package/dist/api/helpers/reply.js.map +1 -0
  15. package/dist/api/plugins/auth.d.ts +27 -0
  16. package/dist/api/plugins/auth.d.ts.map +1 -0
  17. package/dist/api/plugins/auth.js +111 -0
  18. package/dist/api/plugins/auth.js.map +1 -0
  19. package/dist/api/plugins/error-handler.d.ts +12 -0
  20. package/dist/api/plugins/error-handler.d.ts.map +1 -0
  21. package/dist/api/plugins/error-handler.js +72 -0
  22. package/dist/api/plugins/error-handler.js.map +1 -0
  23. package/dist/api/plugins/request-context.d.ts +17 -0
  24. package/dist/api/plugins/request-context.d.ts.map +1 -0
  25. package/dist/api/plugins/request-context.js +61 -0
  26. package/dist/api/plugins/request-context.js.map +1 -0
  27. package/dist/api/routes/health.d.ts +55 -0
  28. package/dist/api/routes/health.d.ts.map +1 -0
  29. package/dist/api/routes/health.js +137 -0
  30. package/dist/api/routes/health.js.map +1 -0
  31. package/dist/api/routes/plugins-introspection.d.ts +17 -0
  32. package/dist/api/routes/plugins-introspection.d.ts.map +1 -0
  33. package/dist/api/routes/plugins-introspection.js +13 -0
  34. package/dist/api/routes/plugins-introspection.js.map +1 -0
  35. package/dist/api/schemas/common.d.ts +114 -0
  36. package/dist/api/schemas/common.d.ts.map +1 -0
  37. package/dist/api/schemas/common.js +109 -0
  38. package/dist/api/schemas/common.js.map +1 -0
  39. package/dist/api/schemas/telemetry.d.ts +66 -0
  40. package/dist/api/schemas/telemetry.d.ts.map +1 -0
  41. package/dist/api/schemas/telemetry.js +52 -0
  42. package/dist/api/schemas/telemetry.js.map +1 -0
  43. package/dist/cache/keyed-ttl-cache.d.ts +45 -0
  44. package/dist/cache/keyed-ttl-cache.d.ts.map +1 -0
  45. package/dist/cache/keyed-ttl-cache.js +69 -0
  46. package/dist/cache/keyed-ttl-cache.js.map +1 -0
  47. package/dist/cache/response-cache.d.ts +37 -0
  48. package/dist/cache/response-cache.d.ts.map +1 -0
  49. package/dist/cache/response-cache.js +114 -0
  50. package/dist/cache/response-cache.js.map +1 -0
  51. package/dist/config.d.ts +258 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/config.js +138 -0
  54. package/dist/config.js.map +1 -0
  55. package/dist/lib/applicant-payload.d.ts +28 -0
  56. package/dist/lib/applicant-payload.d.ts.map +1 -0
  57. package/dist/lib/applicant-payload.js +20 -0
  58. package/dist/lib/applicant-payload.js.map +1 -0
  59. package/dist/lib/application-address.d.ts +16 -0
  60. package/dist/lib/application-address.d.ts.map +1 -0
  61. package/dist/lib/application-address.js +20 -0
  62. package/dist/lib/application-address.js.map +1 -0
  63. package/dist/lib/application-answers.d.ts +151 -0
  64. package/dist/lib/application-answers.d.ts.map +1 -0
  65. package/dist/lib/application-answers.js +95 -0
  66. package/dist/lib/application-answers.js.map +1 -0
  67. package/dist/lib/application-identity.d.ts +18 -0
  68. package/dist/lib/application-identity.d.ts.map +1 -0
  69. package/dist/lib/application-identity.js +20 -0
  70. package/dist/lib/application-identity.js.map +1 -0
  71. package/dist/lib/application-resume.d.ts +21 -0
  72. package/dist/lib/application-resume.d.ts.map +1 -0
  73. package/dist/lib/application-resume.js +23 -0
  74. package/dist/lib/application-resume.js.map +1 -0
  75. package/dist/lib/bedrock.d.ts +22 -0
  76. package/dist/lib/bedrock.d.ts.map +1 -0
  77. package/dist/lib/bedrock.js +35 -0
  78. package/dist/lib/bedrock.js.map +1 -0
  79. package/dist/lib/case-insensitive-headers.d.ts +15 -0
  80. package/dist/lib/case-insensitive-headers.d.ts.map +1 -0
  81. package/dist/lib/case-insensitive-headers.js +29 -0
  82. package/dist/lib/case-insensitive-headers.js.map +1 -0
  83. package/dist/lib/chromium-client-hints.d.ts +11 -0
  84. package/dist/lib/chromium-client-hints.d.ts.map +1 -0
  85. package/dist/lib/chromium-client-hints.js +17 -0
  86. package/dist/lib/chromium-client-hints.js.map +1 -0
  87. package/dist/lib/cookie-value.d.ts +8 -0
  88. package/dist/lib/cookie-value.d.ts.map +1 -0
  89. package/dist/lib/cookie-value.js +14 -0
  90. package/dist/lib/cookie-value.js.map +1 -0
  91. package/dist/lib/datadog.d.ts +8 -0
  92. package/dist/lib/datadog.d.ts.map +1 -0
  93. package/dist/lib/datadog.js +27 -0
  94. package/dist/lib/datadog.js.map +1 -0
  95. package/dist/lib/dd-metrics.d.ts +28 -0
  96. package/dist/lib/dd-metrics.d.ts.map +1 -0
  97. package/dist/lib/dd-metrics.js +62 -0
  98. package/dist/lib/dd-metrics.js.map +1 -0
  99. package/dist/lib/dispatch-metrics.d.ts +19 -0
  100. package/dist/lib/dispatch-metrics.d.ts.map +1 -0
  101. package/dist/lib/dispatch-metrics.js +65 -0
  102. package/dist/lib/dispatch-metrics.js.map +1 -0
  103. package/dist/lib/env.d.ts +37 -0
  104. package/dist/lib/env.d.ts.map +1 -0
  105. package/dist/lib/env.js +70 -0
  106. package/dist/lib/env.js.map +1 -0
  107. package/dist/lib/errors.d.ts +15 -0
  108. package/dist/lib/errors.d.ts.map +1 -0
  109. package/dist/lib/errors.js +20 -0
  110. package/dist/lib/errors.js.map +1 -0
  111. package/dist/lib/http.d.ts +7 -0
  112. package/dist/lib/http.d.ts.map +1 -0
  113. package/dist/lib/http.js +14 -0
  114. package/dist/lib/http.js.map +1 -0
  115. package/dist/lib/job-tracking.d.ts +17 -0
  116. package/dist/lib/job-tracking.d.ts.map +1 -0
  117. package/dist/lib/job-tracking.js +19 -0
  118. package/dist/lib/job-tracking.js.map +1 -0
  119. package/dist/lib/llm/anthropic-client.d.ts +12 -0
  120. package/dist/lib/llm/anthropic-client.d.ts.map +1 -0
  121. package/dist/lib/llm/anthropic-client.js +23 -0
  122. package/dist/lib/llm/anthropic-client.js.map +1 -0
  123. package/dist/lib/llm/judge.d.ts +57 -0
  124. package/dist/lib/llm/judge.d.ts.map +1 -0
  125. package/dist/lib/llm/judge.js +123 -0
  126. package/dist/lib/llm/judge.js.map +1 -0
  127. package/dist/lib/llm/judges/error-messages.d.ts +38 -0
  128. package/dist/lib/llm/judges/error-messages.d.ts.map +1 -0
  129. package/dist/lib/llm/judges/error-messages.js +72 -0
  130. package/dist/lib/llm/judges/error-messages.js.map +1 -0
  131. package/dist/lib/llm/judges/invalid-fields.d.ts +43 -0
  132. package/dist/lib/llm/judges/invalid-fields.d.ts.map +1 -0
  133. package/dist/lib/llm/judges/invalid-fields.js +80 -0
  134. package/dist/lib/llm/judges/invalid-fields.js.map +1 -0
  135. package/dist/lib/llm/judges/modal-priority.d.ts +41 -0
  136. package/dist/lib/llm/judges/modal-priority.d.ts.map +1 -0
  137. package/dist/lib/llm/judges/modal-priority.js +74 -0
  138. package/dist/lib/llm/judges/modal-priority.js.map +1 -0
  139. package/dist/lib/llm/judges/select-option.d.ts +49 -0
  140. package/dist/lib/llm/judges/select-option.d.ts.map +1 -0
  141. package/dist/lib/llm/judges/select-option.js +90 -0
  142. package/dist/lib/llm/judges/select-option.js.map +1 -0
  143. package/dist/lib/llm/judges/verify-submit.d.ts +68 -0
  144. package/dist/lib/llm/judges/verify-submit.d.ts.map +1 -0
  145. package/dist/lib/llm/judges/verify-submit.js +89 -0
  146. package/dist/lib/llm/judges/verify-submit.js.map +1 -0
  147. package/dist/lib/llm/schemas.d.ts +220 -0
  148. package/dist/lib/llm/schemas.d.ts.map +1 -0
  149. package/dist/lib/llm/schemas.js +239 -0
  150. package/dist/lib/llm/schemas.js.map +1 -0
  151. package/dist/lib/logging.d.ts +39 -0
  152. package/dist/lib/logging.d.ts.map +1 -0
  153. package/dist/lib/logging.js +219 -0
  154. package/dist/lib/logging.js.map +1 -0
  155. package/dist/lib/multipart.d.ts +34 -0
  156. package/dist/lib/multipart.d.ts.map +1 -0
  157. package/dist/lib/multipart.js +55 -0
  158. package/dist/lib/multipart.js.map +1 -0
  159. package/dist/lib/option-matcher.d.ts +15 -0
  160. package/dist/lib/option-matcher.d.ts.map +1 -0
  161. package/dist/lib/option-matcher.js +69 -0
  162. package/dist/lib/option-matcher.js.map +1 -0
  163. package/dist/lib/phone.d.ts +11 -0
  164. package/dist/lib/phone.d.ts.map +1 -0
  165. package/dist/lib/phone.js +17 -0
  166. package/dist/lib/phone.js.map +1 -0
  167. package/dist/lib/random.d.ts +22 -0
  168. package/dist/lib/random.d.ts.map +1 -0
  169. package/dist/lib/random.js +33 -0
  170. package/dist/lib/random.js.map +1 -0
  171. package/dist/lib/statsd.d.ts +11 -0
  172. package/dist/lib/statsd.d.ts.map +1 -0
  173. package/dist/lib/statsd.js +68 -0
  174. package/dist/lib/statsd.js.map +1 -0
  175. package/dist/lib/telemetry/call-capture.d.ts +89 -0
  176. package/dist/lib/telemetry/call-capture.d.ts.map +1 -0
  177. package/dist/lib/telemetry/call-capture.js +190 -0
  178. package/dist/lib/telemetry/call-capture.js.map +1 -0
  179. package/dist/lib/telemetry/call-types.d.ts +65 -0
  180. package/dist/lib/telemetry/call-types.d.ts.map +1 -0
  181. package/dist/lib/telemetry/call-types.js +68 -0
  182. package/dist/lib/telemetry/call-types.js.map +1 -0
  183. package/dist/lib/telemetry/run-state.d.ts +15 -0
  184. package/dist/lib/telemetry/run-state.d.ts.map +1 -0
  185. package/dist/lib/telemetry/run-state.js +23 -0
  186. package/dist/lib/telemetry/run-state.js.map +1 -0
  187. package/dist/lib/telemetry/s3-sink.d.ts +48 -0
  188. package/dist/lib/telemetry/s3-sink.d.ts.map +1 -0
  189. package/dist/lib/telemetry/s3-sink.js +229 -0
  190. package/dist/lib/telemetry/s3-sink.js.map +1 -0
  191. package/dist/lib/telemetry/submission-capture.d.ts +45 -0
  192. package/dist/lib/telemetry/submission-capture.d.ts.map +1 -0
  193. package/dist/lib/telemetry/submission-capture.js +57 -0
  194. package/dist/lib/telemetry/submission-capture.js.map +1 -0
  195. package/dist/lib/telemetry/telemetry-paths.d.ts +59 -0
  196. package/dist/lib/telemetry/telemetry-paths.d.ts.map +1 -0
  197. package/dist/lib/telemetry/telemetry-paths.js +103 -0
  198. package/dist/lib/telemetry/telemetry-paths.js.map +1 -0
  199. package/dist/lib/tracking-click.d.ts +20 -0
  200. package/dist/lib/tracking-click.d.ts.map +1 -0
  201. package/dist/lib/tracking-click.js +75 -0
  202. package/dist/lib/tracking-click.js.map +1 -0
  203. package/dist/lib/url-capture.d.ts +8 -0
  204. package/dist/lib/url-capture.d.ts.map +1 -0
  205. package/dist/lib/url-capture.js +17 -0
  206. package/dist/lib/url-capture.js.map +1 -0
  207. package/dist/lib/us-states.d.ts +20 -0
  208. package/dist/lib/us-states.d.ts.map +1 -0
  209. package/dist/lib/us-states.js +86 -0
  210. package/dist/lib/us-states.js.map +1 -0
  211. package/dist/lib/zod-multipart.d.ts +18 -0
  212. package/dist/lib/zod-multipart.d.ts.map +1 -0
  213. package/dist/lib/zod-multipart.js +35 -0
  214. package/dist/lib/zod-multipart.js.map +1 -0
  215. package/dist/plugins/config-plugin.d.ts +77 -0
  216. package/dist/plugins/config-plugin.d.ts.map +1 -0
  217. package/dist/plugins/config-plugin.js +216 -0
  218. package/dist/plugins/config-plugin.js.map +1 -0
  219. package/dist/plugins/discover.d.ts +72 -0
  220. package/dist/plugins/discover.d.ts.map +1 -0
  221. package/dist/plugins/discover.js +265 -0
  222. package/dist/plugins/discover.js.map +1 -0
  223. package/dist/plugins/json-schema-to-zod.d.ts +47 -0
  224. package/dist/plugins/json-schema-to-zod.d.ts.map +1 -0
  225. package/dist/plugins/json-schema-to-zod.js +85 -0
  226. package/dist/plugins/json-schema-to-zod.js.map +1 -0
  227. package/dist/plugins/loader.d.ts +34 -0
  228. package/dist/plugins/loader.d.ts.map +1 -0
  229. package/dist/plugins/loader.js +348 -0
  230. package/dist/plugins/loader.js.map +1 -0
  231. package/dist/plugins/plugin-api-version.d.ts +8 -0
  232. package/dist/plugins/plugin-api-version.d.ts.map +1 -0
  233. package/dist/plugins/plugin-api-version.js +11 -0
  234. package/dist/plugins/plugin-api-version.js.map +1 -0
  235. package/dist/plugins/plugin-manifest-envelope.d.ts +16 -0
  236. package/dist/plugins/plugin-manifest-envelope.d.ts.map +1 -0
  237. package/dist/plugins/plugin-manifest-envelope.js +19 -0
  238. package/dist/plugins/plugin-manifest-envelope.js.map +1 -0
  239. package/dist/scraper/behavioral-signals.d.ts +16 -0
  240. package/dist/scraper/behavioral-signals.d.ts.map +1 -0
  241. package/dist/scraper/behavioral-signals.js +30 -0
  242. package/dist/scraper/behavioral-signals.js.map +1 -0
  243. package/dist/scraper/errors.d.ts +193 -0
  244. package/dist/scraper/errors.d.ts.map +1 -0
  245. package/dist/scraper/errors.js +226 -0
  246. package/dist/scraper/errors.js.map +1 -0
  247. package/dist/scraper/fixtures.d.ts +23 -0
  248. package/dist/scraper/fixtures.d.ts.map +1 -0
  249. package/dist/scraper/fixtures.js +48 -0
  250. package/dist/scraper/fixtures.js.map +1 -0
  251. package/dist/scraper/flow-runner.d.ts +1319 -0
  252. package/dist/scraper/flow-runner.d.ts.map +1 -0
  253. package/dist/scraper/flow-runner.js +5637 -0
  254. package/dist/scraper/flow-runner.js.map +1 -0
  255. package/dist/scraper/graphql-client.d.ts +30 -0
  256. package/dist/scraper/graphql-client.d.ts.map +1 -0
  257. package/dist/scraper/graphql-client.js +14 -0
  258. package/dist/scraper/graphql-client.js.map +1 -0
  259. package/dist/scraper/http-client.d.ts +75 -0
  260. package/dist/scraper/http-client.d.ts.map +1 -0
  261. package/dist/scraper/http-client.js +189 -0
  262. package/dist/scraper/http-client.js.map +1 -0
  263. package/dist/scraper/http-status-classifier.d.ts +12 -0
  264. package/dist/scraper/http-status-classifier.d.ts.map +1 -0
  265. package/dist/scraper/http-status-classifier.js +29 -0
  266. package/dist/scraper/http-status-classifier.js.map +1 -0
  267. package/dist/scraper/metrics.d.ts +50 -0
  268. package/dist/scraper/metrics.d.ts.map +1 -0
  269. package/dist/scraper/metrics.js +85 -0
  270. package/dist/scraper/metrics.js.map +1 -0
  271. package/dist/scraper/navigate.d.ts +20 -0
  272. package/dist/scraper/navigate.d.ts.map +1 -0
  273. package/dist/scraper/navigate.js +30 -0
  274. package/dist/scraper/navigate.js.map +1 -0
  275. package/dist/scraper/oracle-sentinels.d.ts +22 -0
  276. package/dist/scraper/oracle-sentinels.d.ts.map +1 -0
  277. package/dist/scraper/oracle-sentinels.js +40 -0
  278. package/dist/scraper/oracle-sentinels.js.map +1 -0
  279. package/dist/scraper/parse-json-response.d.ts +16 -0
  280. package/dist/scraper/parse-json-response.d.ts.map +1 -0
  281. package/dist/scraper/parse-json-response.js +37 -0
  282. package/dist/scraper/parse-json-response.js.map +1 -0
  283. package/dist/scraper/pool.d.ts +37 -0
  284. package/dist/scraper/pool.d.ts.map +1 -0
  285. package/dist/scraper/pool.js +105 -0
  286. package/dist/scraper/pool.js.map +1 -0
  287. package/dist/scraper/rate-limited-json-client.d.ts +35 -0
  288. package/dist/scraper/rate-limited-json-client.d.ts.map +1 -0
  289. package/dist/scraper/rate-limited-json-client.js +29 -0
  290. package/dist/scraper/rate-limited-json-client.js.map +1 -0
  291. package/dist/scraper/raw-fetch.d.ts +49 -0
  292. package/dist/scraper/raw-fetch.d.ts.map +1 -0
  293. package/dist/scraper/raw-fetch.js +40 -0
  294. package/dist/scraper/raw-fetch.js.map +1 -0
  295. package/dist/scraper/require-response-field.d.ts +23 -0
  296. package/dist/scraper/require-response-field.d.ts.map +1 -0
  297. package/dist/scraper/require-response-field.js +42 -0
  298. package/dist/scraper/require-response-field.js.map +1 -0
  299. package/dist/scraper/retry.d.ts +33 -0
  300. package/dist/scraper/retry.d.ts.map +1 -0
  301. package/dist/scraper/retry.js +122 -0
  302. package/dist/scraper/retry.js.map +1 -0
  303. package/dist/scraper/session-browserbase.d.ts +35 -0
  304. package/dist/scraper/session-browserbase.d.ts.map +1 -0
  305. package/dist/scraper/session-browserbase.js +198 -0
  306. package/dist/scraper/session-browserbase.js.map +1 -0
  307. package/dist/scraper/session-shared.d.ts +29 -0
  308. package/dist/scraper/session-shared.d.ts.map +1 -0
  309. package/dist/scraper/session-shared.js +35 -0
  310. package/dist/scraper/session-shared.js.map +1 -0
  311. package/dist/scraper/session-steel.d.ts +31 -0
  312. package/dist/scraper/session-steel.d.ts.map +1 -0
  313. package/dist/scraper/session-steel.js +140 -0
  314. package/dist/scraper/session-steel.js.map +1 -0
  315. package/dist/scraper/session-warmup.d.ts +31 -0
  316. package/dist/scraper/session-warmup.d.ts.map +1 -0
  317. package/dist/scraper/session-warmup.js +46 -0
  318. package/dist/scraper/session-warmup.js.map +1 -0
  319. package/dist/scraper/session.d.ts +21 -0
  320. package/dist/scraper/session.d.ts.map +1 -0
  321. package/dist/scraper/session.js +28 -0
  322. package/dist/scraper/session.js.map +1 -0
  323. package/dist/scraper/stagehand-guard.d.ts +128 -0
  324. package/dist/scraper/stagehand-guard.d.ts.map +1 -0
  325. package/dist/scraper/stagehand-guard.js +337 -0
  326. package/dist/scraper/stagehand-guard.js.map +1 -0
  327. package/dist/scraper/throttle.d.ts +21 -0
  328. package/dist/scraper/throttle.d.ts.map +1 -0
  329. package/dist/scraper/throttle.js +45 -0
  330. package/dist/scraper/throttle.js.map +1 -0
  331. package/dist/scripts/hca-inbox-poll.d.ts +19 -0
  332. package/dist/scripts/hca-inbox-poll.d.ts.map +1 -0
  333. package/dist/scripts/hca-inbox-poll.js +151 -0
  334. package/dist/scripts/hca-inbox-poll.js.map +1 -0
  335. package/dist/scripts/judge-llm-batch.d.ts +98 -0
  336. package/dist/scripts/judge-llm-batch.d.ts.map +1 -0
  337. package/dist/scripts/judge-llm-batch.js +350 -0
  338. package/dist/scripts/judge-llm-batch.js.map +1 -0
  339. package/dist/scripts/llm-heal.d.ts +165 -0
  340. package/dist/scripts/llm-heal.d.ts.map +1 -0
  341. package/dist/scripts/llm-heal.js +595 -0
  342. package/dist/scripts/llm-heal.js.map +1 -0
  343. package/dist/scripts/migrate-telemetry-dir-names.d.ts +57 -0
  344. package/dist/scripts/migrate-telemetry-dir-names.d.ts.map +1 -0
  345. package/dist/scripts/migrate-telemetry-dir-names.js +156 -0
  346. package/dist/scripts/migrate-telemetry-dir-names.js.map +1 -0
  347. package/dist/scripts/probe-setinputfiles.d.ts +28 -0
  348. package/dist/scripts/probe-setinputfiles.d.ts.map +1 -0
  349. package/dist/scripts/probe-setinputfiles.js +95 -0
  350. package/dist/scripts/probe-setinputfiles.js.map +1 -0
  351. package/dist/scripts/recon-browser.d.ts +304 -0
  352. package/dist/scripts/recon-browser.d.ts.map +1 -0
  353. package/dist/scripts/recon-browser.js +1833 -0
  354. package/dist/scripts/recon-browser.js.map +1 -0
  355. package/dist/scripts/recon-generate.d.ts +182 -0
  356. package/dist/scripts/recon-generate.d.ts.map +1 -0
  357. package/dist/scripts/recon-generate.js +2572 -0
  358. package/dist/scripts/recon-generate.js.map +1 -0
  359. package/dist/scripts/recon-heal.d.ts +176 -0
  360. package/dist/scripts/recon-heal.d.ts.map +1 -0
  361. package/dist/scripts/recon-heal.js +584 -0
  362. package/dist/scripts/recon-heal.js.map +1 -0
  363. package/dist/scripts/recon-http.d.ts +19 -0
  364. package/dist/scripts/recon-http.d.ts.map +1 -0
  365. package/dist/scripts/recon-http.js +377 -0
  366. package/dist/scripts/recon-http.js.map +1 -0
  367. package/dist/scripts/recon-replay-jobs.d.ts +21 -0
  368. package/dist/scripts/recon-replay-jobs.d.ts.map +1 -0
  369. package/dist/scripts/recon-replay-jobs.js +221 -0
  370. package/dist/scripts/recon-replay-jobs.js.map +1 -0
  371. package/dist/scripts/recon-shared.d.ts +52 -0
  372. package/dist/scripts/recon-shared.d.ts.map +1 -0
  373. package/dist/scripts/recon-shared.js +68 -0
  374. package/dist/scripts/recon-shared.js.map +1 -0
  375. package/dist/scripts/recon-summarize.d.ts +15 -0
  376. package/dist/scripts/recon-summarize.d.ts.map +1 -0
  377. package/dist/scripts/recon-summarize.js +233 -0
  378. package/dist/scripts/recon-summarize.js.map +1 -0
  379. package/dist/scripts/smoke-test.d.ts +22 -0
  380. package/dist/scripts/smoke-test.d.ts.map +1 -0
  381. package/dist/scripts/smoke-test.js +236 -0
  382. package/dist/scripts/smoke-test.js.map +1 -0
  383. package/dist/server.d.ts +10 -0
  384. package/dist/server.d.ts.map +1 -0
  385. package/dist/server.js +189 -0
  386. package/dist/server.js.map +1 -0
  387. package/dist/site-plugin.d.ts +226 -0
  388. package/dist/site-plugin.d.ts.map +1 -0
  389. package/dist/site-plugin.js +13 -0
  390. package/dist/site-plugin.js.map +1 -0
  391. package/dist/testing/answers-fixture.d.ts +13 -0
  392. package/dist/testing/answers-fixture.d.ts.map +1 -0
  393. package/dist/testing/answers-fixture.js +37 -0
  394. package/dist/testing/answers-fixture.js.map +1 -0
  395. package/dist/testing/batch-email-confirmation.d.ts +58 -0
  396. package/dist/testing/batch-email-confirmation.d.ts.map +1 -0
  397. package/dist/testing/batch-email-confirmation.js +62 -0
  398. package/dist/testing/batch-email-confirmation.js.map +1 -0
  399. package/dist/testing/batch-report.d.ts +33 -0
  400. package/dist/testing/batch-report.d.ts.map +1 -0
  401. package/dist/testing/batch-report.js +30 -0
  402. package/dist/testing/batch-report.js.map +1 -0
  403. package/dist/testing/contract-parity-suite.d.ts +55 -0
  404. package/dist/testing/contract-parity-suite.d.ts.map +1 -0
  405. package/dist/testing/contract-parity-suite.js +39 -0
  406. package/dist/testing/contract-parity-suite.js.map +1 -0
  407. package/dist/testing/coverage-guard-suite.d.ts +46 -0
  408. package/dist/testing/coverage-guard-suite.d.ts.map +1 -0
  409. package/dist/testing/coverage-guard-suite.js +39 -0
  410. package/dist/testing/coverage-guard-suite.js.map +1 -0
  411. package/dist/testing/fixtures/resume.pdf +54 -0
  412. package/dist/testing/integration-runner.d.ts +62 -0
  413. package/dist/testing/integration-runner.d.ts.map +1 -0
  414. package/dist/testing/integration-runner.js +46 -0
  415. package/dist/testing/integration-runner.js.map +1 -0
  416. package/dist/testing/mock-fetch-response.d.ts +7 -0
  417. package/dist/testing/mock-fetch-response.d.ts.map +1 -0
  418. package/dist/testing/mock-fetch-response.js +16 -0
  419. package/dist/testing/mock-fetch-response.js.map +1 -0
  420. package/dist/testing/persona-fixture.d.ts +77 -0
  421. package/dist/testing/persona-fixture.d.ts.map +1 -0
  422. package/dist/testing/persona-fixture.js +83 -0
  423. package/dist/testing/persona-fixture.js.map +1 -0
  424. package/dist/testing/replay-integration-suite.d.ts +50 -0
  425. package/dist/testing/replay-integration-suite.d.ts.map +1 -0
  426. package/dist/testing/replay-integration-suite.js +45 -0
  427. package/dist/testing/replay-integration-suite.js.map +1 -0
  428. package/dist/testing/resume-fixture.d.ts +39 -0
  429. package/dist/testing/resume-fixture.d.ts.map +1 -0
  430. package/dist/testing/resume-fixture.js +38 -0
  431. package/dist/testing/resume-fixture.js.map +1 -0
  432. package/dist/testmail/client.d.ts +61 -0
  433. package/dist/testmail/client.d.ts.map +1 -0
  434. package/dist/testmail/client.js +190 -0
  435. package/dist/testmail/client.js.map +1 -0
  436. package/dist/testmail/errors.d.ts +18 -0
  437. package/dist/testmail/errors.d.ts.map +1 -0
  438. package/dist/testmail/errors.js +29 -0
  439. package/dist/testmail/errors.js.map +1 -0
  440. package/dist/types/dispatch-metrics.d.ts +46 -0
  441. package/dist/types/dispatch-metrics.d.ts.map +1 -0
  442. package/dist/types/dispatch-metrics.js +25 -0
  443. package/dist/types/dispatch-metrics.js.map +1 -0
  444. package/dist/types/logging.d.ts +11 -0
  445. package/dist/types/logging.d.ts.map +1 -0
  446. package/dist/types/logging.js +3 -0
  447. package/dist/types/logging.js.map +1 -0
  448. package/package.json +283 -0
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEST_PERSONA = void 0;
4
+ /**
5
+ * Standard test persona used by recon runs + integration tests. Centralised
6
+ * so every plugin uses the same identity (helps cross-site audit-log
7
+ * correlation) and so we change it in one place when a field gets rejected
8
+ * by a new validator (e.g. the 555 → 310 phone-number swap during the
9
+ * AppCast recon investigation).
10
+ *
11
+ * The Email field is intentionally omitted — callers should compose the
12
+ * payload by combining this fixture with a freshly allocated testmail.app
13
+ * address. See `src/testmail/client.ts:allocateTestmailInbox`.
14
+ */
15
+ exports.TEST_PERSONA = {
16
+ FirstName: "Reginald",
17
+ LastName: "Reconaldo",
18
+ /**
19
+ * Avoid both the 555 fictional range AND famously-fictional numbers like
20
+ * 310-867-5309 ("Jenny / 867-5309" pop-song). Some ATS phone-input
21
+ * widgets reject both with "Please provide correct phone number."
22
+ *
23
+ * 208-377-2156: Boise area code, random NXX-XXXX, no known
24
+ * pop-culture meaning.
25
+ */
26
+ Phone: "+1 208-377-2156",
27
+ Address: {
28
+ Line1: "123 Test Lane",
29
+ City: "Austin",
30
+ /** Two-letter region code for forms that want abbreviations. */
31
+ StateAbbreviation: "TX",
32
+ /** Full state name for forms that want the long form (e.g. ClearCompany). */
33
+ StateName: "Texas",
34
+ PostalCode: "78701",
35
+ /** Texas county for Austin. Required by tenants (Encompass Health, etc.)
36
+ * that nest a County field inside the Address group. */
37
+ County: "Travis County",
38
+ /** Long-form for `<select>`s that show country names. */
39
+ CountryName: "United States",
40
+ /** Two-letter code for ISO-3166-style inputs. */
41
+ CountryCode: "US",
42
+ },
43
+ /**
44
+ * Throwaway values for forms that require SSN / DOB even for testing.
45
+ * 123-45-6789 is a documented IRS test SSN; 01/01/1990 is a stable adult
46
+ * birthday that won't trip age-bracket validators.
47
+ */
48
+ Ssn: "123-45-6789",
49
+ DateOfBirth: "01/01/1990",
50
+ /** Generic employment row used to fill required Employment History sections. */
51
+ Employment: {
52
+ Title: "Automation Testing Specialist",
53
+ CompanyName: "Self-employed",
54
+ CompanyPhone: "+1 310-867-5311",
55
+ StartDate: "01/01/2020",
56
+ EndDate: "12/31/2025",
57
+ PositionDescription: "Designed and executed automated browser testing workflows for healthcare application portals",
58
+ },
59
+ /** Three reference rows used by ClearCompany and similar ATSes that ask for them. */
60
+ References: [
61
+ {
62
+ FirstName: "Pat",
63
+ LastName: "Smith",
64
+ Email: "pat.smith.ref@example.com",
65
+ Phone: "+1 310-867-5312",
66
+ },
67
+ {
68
+ FirstName: "Jamie",
69
+ LastName: "Johnson",
70
+ Email: "jamie.johnson.ref@example.com",
71
+ Phone: "+1 310-867-5313",
72
+ },
73
+ {
74
+ FirstName: "Taylor",
75
+ LastName: "Brown",
76
+ Email: "taylor.brown.ref@example.com",
77
+ Phone: "+1 310-867-5314",
78
+ },
79
+ ],
80
+ /** Signature text used in legal-attestation sections. */
81
+ SignatureName: "Reginald Reconaldo",
82
+ };
83
+ //# sourceMappingURL=persona-fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persona-fixture.js","sourceRoot":"","sources":["../../src/testing/persona-fixture.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAG;IAC1B,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,WAAW;IACrB;;;;;;;OAOG;IACH,KAAK,EAAE,iBAAiB;IACxB,OAAO,EAAE;QACP,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,QAAQ;QACd,gEAAgE;QAChE,iBAAiB,EAAE,IAAI;QACvB,6EAA6E;QAC7E,SAAS,EAAE,OAAO;QAClB,UAAU,EAAE,OAAO;QACnB;gEACwD;QACxD,MAAM,EAAE,eAAe;QACvB,yDAAyD;QACzD,WAAW,EAAE,eAAe;QAC5B,iDAAiD;QACjD,WAAW,EAAE,IAAI;KAClB;IACD;;;;OAIG;IACH,GAAG,EAAE,aAAa;IAClB,WAAW,EAAE,YAAY;IACzB,gFAAgF;IAChF,UAAU,EAAE;QACV,KAAK,EAAE,+BAA+B;QACtC,WAAW,EAAE,eAAe;QAC5B,YAAY,EAAE,iBAAiB;QAC/B,SAAS,EAAE,YAAY;QACvB,OAAO,EAAE,YAAY;QACrB,mBAAmB,EACjB,8FAA8F;KACjG;IACD,qFAAqF;IACrF,UAAU,EAAE;QACV;YACE,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,2BAA2B;YAClC,KAAK,EAAE,iBAAiB;SACzB;QACD;YACE,SAAS,EAAE,OAAO;YAClB,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,+BAA+B;YACtC,KAAK,EAAE,iBAAiB;SACzB;QACD;YACE,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,8BAA8B;YACrC,KAAK,EAAE,iBAAiB;SACzB;KACF;IACD,yDAAyD;IACzD,aAAa,EAAE,oBAAoB;CAC3B,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Eliminates the repeated describe.skipIf / it.each / runIntegrationJob /
3
+ * message.subject assertion that every replay-based integration test duplicates.
4
+ * Callers supply only the site-specific plugin, job list, and payload builder;
5
+ * the generic scaffold (file load, INTEGRATION gate, fan-out, default assertion)
6
+ * lives here once.
7
+ */
8
+ import type { SitePlugin } from "../site-plugin";
9
+ import type { PollTestmailInboxOptions, TestmailInbox, TestmailMessage } from "../testmail/client";
10
+ /** Job source: either a pre-loaded array or a path resolved relative to the caller's directory. */
11
+ type JobsSource<TJob> = {
12
+ jobs: TJob[];
13
+ } | {
14
+ jobsPath: string;
15
+ dirname: string;
16
+ };
17
+ /**
18
+ * Options for `defineReplayIntegrationSuite`. The `plugin` type parameter may
19
+ * be narrower than `SitePlugin<unknown, unknown>` — the helper casts internally.
20
+ */
21
+ export interface ReplayIntegrationSuiteOptions<TJob> {
22
+ /** Human-readable suite name, passed to `describe`. */
23
+ suiteName: string;
24
+ /** The plugin under test. Internally cast to `SitePlugin<unknown, unknown>`. */
25
+ plugin: SitePlugin<unknown, unknown>;
26
+ /**
27
+ * Override `pollTestmailInbox` so unit tests avoid real network calls.
28
+ * Mirrors the same escape-hatch on `IntegrationJobOptions`.
29
+ */
30
+ pollFn?: (opts: PollTestmailInboxOptions) => Promise<TestmailMessage>;
31
+ /**
32
+ * Called with the freshly allocated testmail inbox; must return the
33
+ * site-specific dispatch payload with the inbox address embedded.
34
+ */
35
+ buildPayload: (job: TJob, inbox: TestmailInbox) => unknown;
36
+ /**
37
+ * Override the per-message assertion. Defaults to
38
+ * `expect(message.subject).toBeTruthy()` — byte-identical to both existing
39
+ * integration tests.
40
+ */
41
+ assertMessage?: (message: TestmailMessage, job: TJob) => void;
42
+ }
43
+ /**
44
+ * Defines a replay-driven integration suite. Pass a `jobs` array or a
45
+ * `jobsPath`+`dirname` pair — the file is read and JSON-parsed at suite
46
+ * definition time. The suite is skipped unless `INTEGRATION=true`.
47
+ */
48
+ export declare function defineReplayIntegrationSuite<TJob extends object>(source: JobsSource<TJob>, opts: ReplayIntegrationSuiteOptions<TJob>): void;
49
+ export {};
50
+ //# sourceMappingURL=replay-integration-suite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-integration-suite.d.ts","sourceRoot":"","sources":["../../src/testing/replay-integration-suite.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,wBAAwB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIlG,mGAAmG;AACnG,KAAK,UAAU,CAAC,IAAI,IAAI;IAAE,IAAI,EAAE,IAAI,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF;;;GAGG;AACH,MAAM,WAAW,6BAA6B,CAAC,IAAI;IACjD,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,wBAAwB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACtE;;;OAGG;IACH,YAAY,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC;IAC3D;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;CAC/D;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,SAAS,MAAM,EAC9D,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EACxB,IAAI,EAAE,6BAA6B,CAAC,IAAI,CAAC,GACxC,IAAI,CA0BN"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * Eliminates the repeated describe.skipIf / it.each / runIntegrationJob /
4
+ * message.subject assertion that every replay-based integration test duplicates.
5
+ * Callers supply only the site-specific plugin, job list, and payload builder;
6
+ * the generic scaffold (file load, INTEGRATION gate, fan-out, default assertion)
7
+ * lives here once.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.defineReplayIntegrationSuite = defineReplayIntegrationSuite;
11
+ const node_fs_1 = require("node:fs");
12
+ const node_path_1 = require("node:path");
13
+ const vitest_1 = require("vitest");
14
+ const integration_runner_1 = require("../testing/integration-runner");
15
+ const DEFAULT_TIMEOUT_MS = 600_000;
16
+ /**
17
+ * Defines a replay-driven integration suite. Pass a `jobs` array or a
18
+ * `jobsPath`+`dirname` pair — the file is read and JSON-parsed at suite
19
+ * definition time. The suite is skipped unless `INTEGRATION=true`.
20
+ */
21
+ function defineReplayIntegrationSuite(source, opts) {
22
+ const { suiteName, plugin, buildPayload, assertMessage, pollFn } = opts;
23
+ const jobs = "jobs" in source
24
+ ? source.jobs
25
+ : JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.resolve)(source.dirname, source.jobsPath), "utf8"));
26
+ vitest_1.describe.skipIf(process.env.INTEGRATION !== "true")(suiteName, () => {
27
+ vitest_1.it.each(jobs)(`submits job and receives confirmation email`, {
28
+ timeout: DEFAULT_TIMEOUT_MS,
29
+ }, async (job) => {
30
+ const { message } = await (0, integration_runner_1.runIntegrationJob)({
31
+ plugin: plugin,
32
+ baseUrl: job.baseUrl,
33
+ buildPayload: (inbox) => buildPayload(job, inbox),
34
+ ...(pollFn ? { pollFn } : {}),
35
+ });
36
+ if (assertMessage) {
37
+ assertMessage(message, job);
38
+ }
39
+ else {
40
+ (0, vitest_1.expect)(message.subject).toBeTruthy();
41
+ }
42
+ });
43
+ });
44
+ }
45
+ //# sourceMappingURL=replay-integration-suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-integration-suite.js","sourceRoot":"","sources":["../../src/testing/replay-integration-suite.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAgDH,oEA6BC;AA3ED,qCAAuC;AACvC,yCAAoC;AAEpC,mCAA8C;AAG9C,qEAAiE;AAGjE,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAgCnC;;;;GAIG;AACH,SAAgB,4BAA4B,CAC1C,MAAwB,EACxB,IAAyC;IAEzC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExE,MAAM,IAAI,GACR,MAAM,IAAI,MAAM;QACd,CAAC,CAAC,MAAM,CAAC,IAAI;QACb,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,IAAA,mBAAO,EAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAY,CAAC;IAE7F,iBAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE;QAClE,WAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,6CAA6C,EAAE;YAC3D,OAAO,EAAE,kBAAkB;SAC5B,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACf,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAA,sCAAiB,EAAC;gBAC1C,MAAM,EAAE,MAAiD;gBACzD,OAAO,EAAG,GAA+B,CAAC,OAAiB;gBAC3D,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC;gBACjD,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9B,CAAC,CAAC;YAEH,IAAI,aAAa,EAAE,CAAC;gBAClB,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAA,eAAM,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Resolved resume bytes + the metadata downstream plugins need to attach
3
+ * the file to a multipart request or a JSON resume blob. Plugins that
4
+ * accept resume uploads can destructure this shape directly into their
5
+ * payload fields.
6
+ */
7
+ export interface TestResume {
8
+ buffer: Buffer;
9
+ contentType: "application/pdf";
10
+ filename: string;
11
+ base64: string;
12
+ }
13
+ /**
14
+ * The payload-side field names that every resume-accepting site uses
15
+ * identically. Extracted so tests can spread this instead of repeating
16
+ * the four-field mapping verbatim.
17
+ */
18
+ export interface ResumePayloadFields {
19
+ Resume: Buffer;
20
+ ResumeContentType: string;
21
+ ResumeFilename: string;
22
+ ResumeBase64: string;
23
+ }
24
+ /**
25
+ * Read the shared persona PDF once and return its bytes + the per-call
26
+ * metadata fields the plugins expect. Centralised so the integration tests
27
+ * never disagree about which resume the test persona is submitting, and so
28
+ * a future swap to a different PDF is a one-file change instead of a fan-out
29
+ * across every test.
30
+ */
31
+ export declare function loadTestResume(): TestResume;
32
+ /**
33
+ * Maps a `TestResume` to the four payload field names every resume-accepting
34
+ * site shares (Resume, ResumeContentType, ResumeFilename, ResumeBase64).
35
+ * Extracted here so tests can spread `resumePayloadFields(resume)` instead
36
+ * of repeating the same literal mapping at every call site.
37
+ */
38
+ export declare function resumePayloadFields(resume: TestResume): ResumePayloadFields;
39
+ //# sourceMappingURL=resume-fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-fixture.d.ts","sourceRoot":"","sources":["../../src/testing/resume-fixture.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,iBAAiB,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAQ3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAO3E"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadTestResume = loadTestResume;
4
+ exports.resumePayloadFields = resumePayloadFields;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const RESUME_PATH = (0, node_path_1.resolve)(__dirname, "./fixtures/resume.pdf");
8
+ /**
9
+ * Read the shared persona PDF once and return its bytes + the per-call
10
+ * metadata fields the plugins expect. Centralised so the integration tests
11
+ * never disagree about which resume the test persona is submitting, and so
12
+ * a future swap to a different PDF is a one-file change instead of a fan-out
13
+ * across every test.
14
+ */
15
+ function loadTestResume() {
16
+ const buffer = (0, node_fs_1.readFileSync)(RESUME_PATH);
17
+ return {
18
+ buffer,
19
+ contentType: "application/pdf",
20
+ filename: "reginald-reconaldo.pdf",
21
+ base64: buffer.toString("base64"),
22
+ };
23
+ }
24
+ /**
25
+ * Maps a `TestResume` to the four payload field names every resume-accepting
26
+ * site shares (Resume, ResumeContentType, ResumeFilename, ResumeBase64).
27
+ * Extracted here so tests can spread `resumePayloadFields(resume)` instead
28
+ * of repeating the same literal mapping at every call site.
29
+ */
30
+ function resumePayloadFields(resume) {
31
+ return {
32
+ Resume: resume.buffer,
33
+ ResumeContentType: resume.contentType,
34
+ ResumeFilename: resume.filename,
35
+ ResumeBase64: resume.base64,
36
+ };
37
+ }
38
+ //# sourceMappingURL=resume-fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-fixture.js","sourceRoot":"","sources":["../../src/testing/resume-fixture.ts"],"names":[],"mappings":";;AAqCA,wCAQC;AAQD,kDAOC;AA5DD,qCAAuC;AACvC,yCAAoC;AA2BpC,MAAM,WAAW,GAAG,IAAA,mBAAO,EAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;AAEhE;;;;;;GAMG;AACH,SAAgB,cAAc;IAC5B,MAAM,MAAM,GAAG,IAAA,sBAAY,EAAC,WAAW,CAAC,CAAC;IACzC,OAAO;QACL,MAAM;QACN,WAAW,EAAE,iBAAiB;QAC9B,QAAQ,EAAE,wBAAwB;QAClC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAClC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,MAAkB;IACpD,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,iBAAiB,EAAE,MAAM,CAAC,WAAW;QACrC,cAAc,EAAE,MAAM,CAAC,QAAQ;QAC/B,YAAY,EAAE,MAAM,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,61 @@
1
+ /** An address allocated for a single recon run / integration test. */
2
+ export interface TestmailInbox {
3
+ /** Full address: `{namespace}.{tag}@inbox.testmail.app`. */
4
+ address: string;
5
+ /** Tag piece — used as the GraphQL query filter to scope reads to this inbox. */
6
+ tag: string;
7
+ /** Allocation timestamp (Unix ms) — passed to the inbox query so we only see emails received AFTER allocation. */
8
+ timestampFrom: number;
9
+ }
10
+ /**
11
+ * Single message returned by the inbox query. Shaped to match the GraphQL
12
+ * response one-to-one so the polling loop doesn't need to remap.
13
+ */
14
+ export interface TestmailMessage {
15
+ id: string;
16
+ from: string;
17
+ subject: string;
18
+ text: string | null;
19
+ html: string | null;
20
+ /** Unix ms timestamp (per testmail GraphQL `Float`). */
21
+ date: number;
22
+ }
23
+ export interface AllocateTestmailInboxOptions {
24
+ /** Override the configured namespace (`TESTMAIL_NAMESPACE`). Mostly useful for tests. */
25
+ namespace?: string;
26
+ }
27
+ export interface PollTestmailInboxOptions {
28
+ inbox: TestmailInbox;
29
+ /** Substring match against `subject` (case-insensitive). Omit to return any new message. */
30
+ subjectContains?: string;
31
+ /** Total wait budget in ms. Default 60_000. */
32
+ timeoutMs?: number;
33
+ /** Sleep between iterations in ms. Default 2_000. */
34
+ intervalMs?: number;
35
+ }
36
+ /**
37
+ * Allocate a fresh testmail.app inbox address. No network call — testmail
38
+ * uses dynamic subaddressing, so any `{namespace}.{tag}@inbox.testmail.app`
39
+ * is implicitly valid the moment we generate it. The 8-char random tag
40
+ * makes collisions vanishingly unlikely without persisting state.
41
+ *
42
+ * The returned `timestampFrom` is the allocation moment in Unix ms; the
43
+ * polling helper filters the inbox query by this so we never see messages
44
+ * from previous allocations (the namespace is shared across all runs).
45
+ */
46
+ export declare function allocateTestmailInbox(opts?: AllocateTestmailInboxOptions): TestmailInbox;
47
+ /** Reset the cached client. Useful when tests swap config between cases. */
48
+ export declare function resetTestmailClientForTests(): void;
49
+ /**
50
+ * Poll the testmail.app inbox until a matching message arrives or the wait
51
+ * budget runs out. Uses testmail's `livequery: true` for server-side long-
52
+ * polling (cuts the round-trip count vs. tight client-side polling) but
53
+ * also wraps in a client-side retry loop so a transient query failure
54
+ * doesn't fail the whole wait.
55
+ *
56
+ * Throws `TestmailTimeoutError` on budget expiry. Throws `TestmailApiError`
57
+ * when the API returns a non-success `result` field that doesn't recover
58
+ * across iterations.
59
+ */
60
+ export declare function pollTestmailInbox(opts: PollTestmailInboxOptions): Promise<TestmailMessage>;
61
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/testmail/client.ts"],"names":[],"mappings":"AAmDA,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ,kHAAkH;IAClH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,aAAa,CAAC;IACrB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,4BAAiC,GAAG,aAAa,CAY5F;AAoCD,4EAA4E;AAC5E,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAoBD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoFhG"}
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.allocateTestmailInbox = allocateTestmailInbox;
7
+ exports.resetTestmailClientForTests = resetTestmailClientForTests;
8
+ exports.pollTestmailInbox = pollTestmailInbox;
9
+ const node_crypto_1 = require("node:crypto");
10
+ const bottleneck_1 = __importDefault(require("bottleneck"));
11
+ const v4_1 = require("zod/v4");
12
+ const config_1 = require("../config");
13
+ const logging_1 = require("../lib/logging");
14
+ const graphql_client_1 = require("../scraper/graphql-client");
15
+ const errors_1 = require("../testmail/errors");
16
+ const logger = (0, logging_1.getLogger)({ name: "testmail/client" });
17
+ const TESTMAIL_ENDPOINT = "https://api.testmail.app/api/graphql";
18
+ /**
19
+ * Sustained per-key rate-limit ceiling per testmail docs (5 rps). Pinning
20
+ * to 4 rps leaves headroom for the inbox-query loop + any concurrent
21
+ * callers (e.g. multiple integration tests sharing the namespace).
22
+ */
23
+ const TESTMAIL_MIN_TIME_MS = 250;
24
+ /** Default total wait budget for `pollTestmailInbox`. Calibrated for typical receipt-email latency (10-30s). */
25
+ const DEFAULT_POLL_TIMEOUT_MS = 60_000;
26
+ /**
27
+ * Default per-iteration wait between inbox queries. The query itself uses
28
+ * `livequery: true` which long-polls server-side, so we sleep this much
29
+ * BETWEEN queries — not as the primary wait mechanism.
30
+ */
31
+ const DEFAULT_POLL_INTERVAL_MS = 2_000;
32
+ const InboxQueryResponseSchema = v4_1.z.object({
33
+ data: v4_1.z.object({
34
+ inbox: v4_1.z.object({
35
+ result: v4_1.z.string(),
36
+ message: v4_1.z.string().nullable().optional(),
37
+ count: v4_1.z.number(),
38
+ emails: v4_1.z.array(v4_1.z.object({
39
+ id: v4_1.z.string(),
40
+ from: v4_1.z.string(),
41
+ subject: v4_1.z.string(),
42
+ text: v4_1.z.string().nullable().optional(),
43
+ html: v4_1.z.string().nullable().optional(),
44
+ date: v4_1.z.number(),
45
+ })),
46
+ }),
47
+ }),
48
+ });
49
+ /**
50
+ * Allocate a fresh testmail.app inbox address. No network call — testmail
51
+ * uses dynamic subaddressing, so any `{namespace}.{tag}@inbox.testmail.app`
52
+ * is implicitly valid the moment we generate it. The 8-char random tag
53
+ * makes collisions vanishingly unlikely without persisting state.
54
+ *
55
+ * The returned `timestampFrom` is the allocation moment in Unix ms; the
56
+ * polling helper filters the inbox query by this so we never see messages
57
+ * from previous allocations (the namespace is shared across all runs).
58
+ */
59
+ function allocateTestmailInbox(opts = {}) {
60
+ const namespace = opts.namespace ?? config_1.config.testmail.namespace;
61
+ if (!namespace) {
62
+ throw new errors_1.TestmailApiError("TESTMAIL_NAMESPACE required to allocate an inbox; set it in .env or pass via opts.namespace");
63
+ }
64
+ const tag = `barnacle-${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
65
+ const address = `${namespace}.${tag}@inbox.testmail.app`;
66
+ const timestampFrom = Date.now();
67
+ logger.info(`allocated testmail inbox ${address} (timestampFrom=${timestampFrom})`);
68
+ return { address, tag, timestampFrom };
69
+ }
70
+ let cachedClient = null;
71
+ function getTestmailClient() {
72
+ if (cachedClient)
73
+ return cachedClient;
74
+ const apiKey = config_1.config.testmail.apiKey;
75
+ if (!apiKey) {
76
+ throw new errors_1.TestmailApiError("TESTMAIL_API_KEY required to query testmail.app; set it in .env");
77
+ }
78
+ const bottleneck = new bottleneck_1.default({ minTime: TESTMAIL_MIN_TIME_MS });
79
+ cachedClient = (0, graphql_client_1.createGraphqlClient)({
80
+ schema: InboxQueryResponseSchema,
81
+ bottleneck,
82
+ baseHeaders: {
83
+ "Content-Type": "application/json",
84
+ Accept: "application/json",
85
+ Authorization: `Bearer ${apiKey}`,
86
+ },
87
+ endpoint: TESTMAIL_ENDPOINT,
88
+ });
89
+ return cachedClient;
90
+ }
91
+ /** Reset the cached client. Useful when tests swap config between cases. */
92
+ function resetTestmailClientForTests() {
93
+ cachedClient = null;
94
+ }
95
+ const INBOX_QUERY = `
96
+ query Inbox($namespace: String!, $tag: String, $timestampFrom: Float, $livequery: Boolean) {
97
+ inbox(namespace: $namespace, tag: $tag, timestamp_from: $timestampFrom, livequery: $livequery) {
98
+ result
99
+ message
100
+ count
101
+ emails {
102
+ id
103
+ from
104
+ subject
105
+ text
106
+ html
107
+ date
108
+ }
109
+ }
110
+ }
111
+ `;
112
+ /**
113
+ * Poll the testmail.app inbox until a matching message arrives or the wait
114
+ * budget runs out. Uses testmail's `livequery: true` for server-side long-
115
+ * polling (cuts the round-trip count vs. tight client-side polling) but
116
+ * also wraps in a client-side retry loop so a transient query failure
117
+ * doesn't fail the whole wait.
118
+ *
119
+ * Throws `TestmailTimeoutError` on budget expiry. Throws `TestmailApiError`
120
+ * when the API returns a non-success `result` field that doesn't recover
121
+ * across iterations.
122
+ */
123
+ async function pollTestmailInbox(opts) {
124
+ const { inbox, subjectContains, timeoutMs = DEFAULT_POLL_TIMEOUT_MS, intervalMs = DEFAULT_POLL_INTERVAL_MS, } = opts;
125
+ const namespace = config_1.config.testmail.namespace;
126
+ if (!namespace) {
127
+ throw new errors_1.TestmailApiError("TESTMAIL_NAMESPACE required to poll an inbox; set it in .env");
128
+ }
129
+ const client = getTestmailClient();
130
+ const deadline = Date.now() + timeoutMs;
131
+ const subjectNeedle = subjectContains?.toLowerCase();
132
+ let lastApiError = null;
133
+ while (Date.now() < deadline) {
134
+ let response;
135
+ try {
136
+ // Bound the underlying fetch on the remaining deadline. testmail's
137
+ // `livequery: true` long-polls server-side (the server holds the
138
+ // connection open for ~15 min waiting for new mail), and Node's
139
+ // built-in fetch has no default timeout — without this signal a
140
+ // single query outlasts the caller's poll budget by many minutes.
141
+ const remaining = deadline - Date.now();
142
+ response = (await client("Inbox", INBOX_QUERY, {
143
+ namespace,
144
+ tag: inbox.tag,
145
+ timestampFrom: inbox.timestampFrom,
146
+ livequery: true,
147
+ }, { signal: AbortSignal.timeout(remaining) }));
148
+ }
149
+ catch (err) {
150
+ // Transient API failure — sleep + try again until deadline. Hold the
151
+ // last error so a budget expiry can report something useful.
152
+ lastApiError = new errors_1.TestmailApiError(`inbox query failed: ${err instanceof Error ? err.message : String(err)}`);
153
+ logger.warn(`testmail inbox query failed; retrying: ${lastApiError.message}`);
154
+ await sleep(Math.min(intervalMs, deadline - Date.now()));
155
+ continue;
156
+ }
157
+ const inboxData = response.data.inbox;
158
+ if (inboxData.result !== "success") {
159
+ lastApiError = new errors_1.TestmailApiError(`inbox query returned result=${inboxData.result} message=${inboxData.message ?? "<null>"}`);
160
+ logger.warn(`testmail inbox non-success result: ${lastApiError.message}`);
161
+ await sleep(Math.min(intervalMs, deadline - Date.now()));
162
+ continue;
163
+ }
164
+ const matching = inboxData.emails.find((email) => {
165
+ if (!subjectNeedle)
166
+ return true;
167
+ return email.subject.toLowerCase().includes(subjectNeedle);
168
+ });
169
+ if (matching) {
170
+ logger.info(`testmail inbox ${inbox.address} received matching message (subject="${matching.subject}", id=${matching.id})`);
171
+ return {
172
+ id: matching.id,
173
+ from: matching.from,
174
+ subject: matching.subject,
175
+ text: matching.text ?? null,
176
+ html: matching.html ?? null,
177
+ date: matching.date,
178
+ };
179
+ }
180
+ await sleep(Math.min(intervalMs, deadline - Date.now()));
181
+ }
182
+ const reason = lastApiError ? ` (last API error: ${lastApiError.message})` : "";
183
+ throw new errors_1.TestmailTimeoutError(`testmail inbox ${inbox.address} did not receive ${subjectContains ? `a message with subject containing "${subjectContains}"` : "any message"} within ${timeoutMs}ms${reason}`);
184
+ }
185
+ function sleep(ms) {
186
+ if (ms <= 0)
187
+ return Promise.resolve();
188
+ return new Promise((resolve) => setTimeout(resolve, ms));
189
+ }
190
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/testmail/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * No message matching the inbox filter arrived before the wait budget
3
+ * elapsed. Callers usually want to either widen the timeout or treat this
4
+ * as a real failure (the site didn't send the confirmation email).
5
+ */
6
+ export declare class TestmailTimeoutError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ /**
10
+ * The testmail.app GraphQL API returned a non-success `result` field or an
11
+ * HTTP error that the underlying HTTP client surfaced. Distinct from
12
+ * timeout so call-sites can decide whether to retry (rate limit, transient
13
+ * 5xx) or fail loud (bad API key, missing namespace).
14
+ */
15
+ export declare class TestmailApiError extends Error {
16
+ constructor(message: string);
17
+ }
18
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/testmail/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestmailApiError = exports.TestmailTimeoutError = void 0;
4
+ /**
5
+ * No message matching the inbox filter arrived before the wait budget
6
+ * elapsed. Callers usually want to either widen the timeout or treat this
7
+ * as a real failure (the site didn't send the confirmation email).
8
+ */
9
+ class TestmailTimeoutError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = new.target.name;
13
+ }
14
+ }
15
+ exports.TestmailTimeoutError = TestmailTimeoutError;
16
+ /**
17
+ * The testmail.app GraphQL API returned a non-success `result` field or an
18
+ * HTTP error that the underlying HTTP client surfaced. Distinct from
19
+ * timeout so call-sites can decide whether to retry (rate limit, transient
20
+ * 5xx) or fail loud (bad API key, missing namespace).
21
+ */
22
+ class TestmailApiError extends Error {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = new.target.name;
26
+ }
27
+ }
28
+ exports.TestmailApiError = TestmailApiError;
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/testmail/errors.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AALD,oDAKC;AAED;;;;;GAKG;AACH,MAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AALD,4CAKC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Structured metrics payload attached to dispatch responses so Vivian can
3
+ * forward step-level detail into Segment events for A/B warehouse analysis.
4
+ */
5
+ import { z } from "zod/v4";
6
+ export interface DispatchStepMetric {
7
+ step: string;
8
+ durationMs: number;
9
+ status: "success" | "failed" | "skipped";
10
+ error?: string;
11
+ }
12
+ export interface DispatchMetrics {
13
+ totalDurationMs: number;
14
+ path: "http" | "browser";
15
+ steps: DispatchStepMetric[];
16
+ errorType?: string;
17
+ errorStep?: string;
18
+ attemptCount: number;
19
+ startedAt: string;
20
+ endedAt: string;
21
+ recordedAt: string;
22
+ }
23
+ export declare const DispatchMetricsSchema: z.ZodObject<{
24
+ totalDurationMs: z.ZodNumber;
25
+ path: z.ZodEnum<{
26
+ http: "http";
27
+ browser: "browser";
28
+ }>;
29
+ steps: z.ZodArray<z.ZodObject<{
30
+ step: z.ZodString;
31
+ durationMs: z.ZodNumber;
32
+ status: z.ZodEnum<{
33
+ success: "success";
34
+ failed: "failed";
35
+ skipped: "skipped";
36
+ }>;
37
+ error: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strip>>;
39
+ errorType: z.ZodOptional<z.ZodString>;
40
+ errorStep: z.ZodOptional<z.ZodString>;
41
+ attemptCount: z.ZodNumber;
42
+ startedAt: z.ZodString;
43
+ endedAt: z.ZodString;
44
+ recordedAt: z.ZodString;
45
+ }, z.core.$strip>;
46
+ //# sourceMappingURL=dispatch-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-metrics.d.ts","sourceRoot":"","sources":["../../src/types/dispatch-metrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAiBhC,CAAC"}