@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.
- package/LICENSE +21 -0
- package/README.md +958 -0
- package/dist/api/errors.d.ts +88 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +164 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/helpers/envelope.d.ts +13 -0
- package/dist/api/helpers/envelope.d.ts.map +1 -0
- package/dist/api/helpers/envelope.js +20 -0
- package/dist/api/helpers/envelope.js.map +1 -0
- package/dist/api/helpers/reply.d.ts +9 -0
- package/dist/api/helpers/reply.d.ts.map +1 -0
- package/dist/api/helpers/reply.js +14 -0
- package/dist/api/helpers/reply.js.map +1 -0
- package/dist/api/plugins/auth.d.ts +27 -0
- package/dist/api/plugins/auth.d.ts.map +1 -0
- package/dist/api/plugins/auth.js +111 -0
- package/dist/api/plugins/auth.js.map +1 -0
- package/dist/api/plugins/error-handler.d.ts +12 -0
- package/dist/api/plugins/error-handler.d.ts.map +1 -0
- package/dist/api/plugins/error-handler.js +72 -0
- package/dist/api/plugins/error-handler.js.map +1 -0
- package/dist/api/plugins/request-context.d.ts +17 -0
- package/dist/api/plugins/request-context.d.ts.map +1 -0
- package/dist/api/plugins/request-context.js +61 -0
- package/dist/api/plugins/request-context.js.map +1 -0
- package/dist/api/routes/health.d.ts +55 -0
- package/dist/api/routes/health.d.ts.map +1 -0
- package/dist/api/routes/health.js +137 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/plugins-introspection.d.ts +17 -0
- package/dist/api/routes/plugins-introspection.d.ts.map +1 -0
- package/dist/api/routes/plugins-introspection.js +13 -0
- package/dist/api/routes/plugins-introspection.js.map +1 -0
- package/dist/api/schemas/common.d.ts +114 -0
- package/dist/api/schemas/common.d.ts.map +1 -0
- package/dist/api/schemas/common.js +109 -0
- package/dist/api/schemas/common.js.map +1 -0
- package/dist/api/schemas/telemetry.d.ts +66 -0
- package/dist/api/schemas/telemetry.d.ts.map +1 -0
- package/dist/api/schemas/telemetry.js +52 -0
- package/dist/api/schemas/telemetry.js.map +1 -0
- package/dist/cache/keyed-ttl-cache.d.ts +45 -0
- package/dist/cache/keyed-ttl-cache.d.ts.map +1 -0
- package/dist/cache/keyed-ttl-cache.js +69 -0
- package/dist/cache/keyed-ttl-cache.js.map +1 -0
- package/dist/cache/response-cache.d.ts +37 -0
- package/dist/cache/response-cache.d.ts.map +1 -0
- package/dist/cache/response-cache.js +114 -0
- package/dist/cache/response-cache.js.map +1 -0
- package/dist/config.d.ts +258 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/lib/applicant-payload.d.ts +28 -0
- package/dist/lib/applicant-payload.d.ts.map +1 -0
- package/dist/lib/applicant-payload.js +20 -0
- package/dist/lib/applicant-payload.js.map +1 -0
- package/dist/lib/application-address.d.ts +16 -0
- package/dist/lib/application-address.d.ts.map +1 -0
- package/dist/lib/application-address.js +20 -0
- package/dist/lib/application-address.js.map +1 -0
- package/dist/lib/application-answers.d.ts +151 -0
- package/dist/lib/application-answers.d.ts.map +1 -0
- package/dist/lib/application-answers.js +95 -0
- package/dist/lib/application-answers.js.map +1 -0
- package/dist/lib/application-identity.d.ts +18 -0
- package/dist/lib/application-identity.d.ts.map +1 -0
- package/dist/lib/application-identity.js +20 -0
- package/dist/lib/application-identity.js.map +1 -0
- package/dist/lib/application-resume.d.ts +21 -0
- package/dist/lib/application-resume.d.ts.map +1 -0
- package/dist/lib/application-resume.js +23 -0
- package/dist/lib/application-resume.js.map +1 -0
- package/dist/lib/bedrock.d.ts +22 -0
- package/dist/lib/bedrock.d.ts.map +1 -0
- package/dist/lib/bedrock.js +35 -0
- package/dist/lib/bedrock.js.map +1 -0
- package/dist/lib/case-insensitive-headers.d.ts +15 -0
- package/dist/lib/case-insensitive-headers.d.ts.map +1 -0
- package/dist/lib/case-insensitive-headers.js +29 -0
- package/dist/lib/case-insensitive-headers.js.map +1 -0
- package/dist/lib/chromium-client-hints.d.ts +11 -0
- package/dist/lib/chromium-client-hints.d.ts.map +1 -0
- package/dist/lib/chromium-client-hints.js +17 -0
- package/dist/lib/chromium-client-hints.js.map +1 -0
- package/dist/lib/cookie-value.d.ts +8 -0
- package/dist/lib/cookie-value.d.ts.map +1 -0
- package/dist/lib/cookie-value.js +14 -0
- package/dist/lib/cookie-value.js.map +1 -0
- package/dist/lib/datadog.d.ts +8 -0
- package/dist/lib/datadog.d.ts.map +1 -0
- package/dist/lib/datadog.js +27 -0
- package/dist/lib/datadog.js.map +1 -0
- package/dist/lib/dd-metrics.d.ts +28 -0
- package/dist/lib/dd-metrics.d.ts.map +1 -0
- package/dist/lib/dd-metrics.js +62 -0
- package/dist/lib/dd-metrics.js.map +1 -0
- package/dist/lib/dispatch-metrics.d.ts +19 -0
- package/dist/lib/dispatch-metrics.d.ts.map +1 -0
- package/dist/lib/dispatch-metrics.js +65 -0
- package/dist/lib/dispatch-metrics.js.map +1 -0
- package/dist/lib/env.d.ts +37 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/env.js +70 -0
- package/dist/lib/env.js.map +1 -0
- package/dist/lib/errors.d.ts +15 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +20 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/http.d.ts +7 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +14 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/job-tracking.d.ts +17 -0
- package/dist/lib/job-tracking.d.ts.map +1 -0
- package/dist/lib/job-tracking.js +19 -0
- package/dist/lib/job-tracking.js.map +1 -0
- package/dist/lib/llm/anthropic-client.d.ts +12 -0
- package/dist/lib/llm/anthropic-client.d.ts.map +1 -0
- package/dist/lib/llm/anthropic-client.js +23 -0
- package/dist/lib/llm/anthropic-client.js.map +1 -0
- package/dist/lib/llm/judge.d.ts +57 -0
- package/dist/lib/llm/judge.d.ts.map +1 -0
- package/dist/lib/llm/judge.js +123 -0
- package/dist/lib/llm/judge.js.map +1 -0
- package/dist/lib/llm/judges/error-messages.d.ts +38 -0
- package/dist/lib/llm/judges/error-messages.d.ts.map +1 -0
- package/dist/lib/llm/judges/error-messages.js +72 -0
- package/dist/lib/llm/judges/error-messages.js.map +1 -0
- package/dist/lib/llm/judges/invalid-fields.d.ts +43 -0
- package/dist/lib/llm/judges/invalid-fields.d.ts.map +1 -0
- package/dist/lib/llm/judges/invalid-fields.js +80 -0
- package/dist/lib/llm/judges/invalid-fields.js.map +1 -0
- package/dist/lib/llm/judges/modal-priority.d.ts +41 -0
- package/dist/lib/llm/judges/modal-priority.d.ts.map +1 -0
- package/dist/lib/llm/judges/modal-priority.js +74 -0
- package/dist/lib/llm/judges/modal-priority.js.map +1 -0
- package/dist/lib/llm/judges/select-option.d.ts +49 -0
- package/dist/lib/llm/judges/select-option.d.ts.map +1 -0
- package/dist/lib/llm/judges/select-option.js +90 -0
- package/dist/lib/llm/judges/select-option.js.map +1 -0
- package/dist/lib/llm/judges/verify-submit.d.ts +68 -0
- package/dist/lib/llm/judges/verify-submit.d.ts.map +1 -0
- package/dist/lib/llm/judges/verify-submit.js +89 -0
- package/dist/lib/llm/judges/verify-submit.js.map +1 -0
- package/dist/lib/llm/schemas.d.ts +220 -0
- package/dist/lib/llm/schemas.d.ts.map +1 -0
- package/dist/lib/llm/schemas.js +239 -0
- package/dist/lib/llm/schemas.js.map +1 -0
- package/dist/lib/logging.d.ts +39 -0
- package/dist/lib/logging.d.ts.map +1 -0
- package/dist/lib/logging.js +219 -0
- package/dist/lib/logging.js.map +1 -0
- package/dist/lib/multipart.d.ts +34 -0
- package/dist/lib/multipart.d.ts.map +1 -0
- package/dist/lib/multipart.js +55 -0
- package/dist/lib/multipart.js.map +1 -0
- package/dist/lib/option-matcher.d.ts +15 -0
- package/dist/lib/option-matcher.d.ts.map +1 -0
- package/dist/lib/option-matcher.js +69 -0
- package/dist/lib/option-matcher.js.map +1 -0
- package/dist/lib/phone.d.ts +11 -0
- package/dist/lib/phone.d.ts.map +1 -0
- package/dist/lib/phone.js +17 -0
- package/dist/lib/phone.js.map +1 -0
- package/dist/lib/random.d.ts +22 -0
- package/dist/lib/random.d.ts.map +1 -0
- package/dist/lib/random.js +33 -0
- package/dist/lib/random.js.map +1 -0
- package/dist/lib/statsd.d.ts +11 -0
- package/dist/lib/statsd.d.ts.map +1 -0
- package/dist/lib/statsd.js +68 -0
- package/dist/lib/statsd.js.map +1 -0
- package/dist/lib/telemetry/call-capture.d.ts +89 -0
- package/dist/lib/telemetry/call-capture.d.ts.map +1 -0
- package/dist/lib/telemetry/call-capture.js +190 -0
- package/dist/lib/telemetry/call-capture.js.map +1 -0
- package/dist/lib/telemetry/call-types.d.ts +65 -0
- package/dist/lib/telemetry/call-types.d.ts.map +1 -0
- package/dist/lib/telemetry/call-types.js +68 -0
- package/dist/lib/telemetry/call-types.js.map +1 -0
- package/dist/lib/telemetry/run-state.d.ts +15 -0
- package/dist/lib/telemetry/run-state.d.ts.map +1 -0
- package/dist/lib/telemetry/run-state.js +23 -0
- package/dist/lib/telemetry/run-state.js.map +1 -0
- package/dist/lib/telemetry/s3-sink.d.ts +48 -0
- package/dist/lib/telemetry/s3-sink.d.ts.map +1 -0
- package/dist/lib/telemetry/s3-sink.js +229 -0
- package/dist/lib/telemetry/s3-sink.js.map +1 -0
- package/dist/lib/telemetry/submission-capture.d.ts +45 -0
- package/dist/lib/telemetry/submission-capture.d.ts.map +1 -0
- package/dist/lib/telemetry/submission-capture.js +57 -0
- package/dist/lib/telemetry/submission-capture.js.map +1 -0
- package/dist/lib/telemetry/telemetry-paths.d.ts +59 -0
- package/dist/lib/telemetry/telemetry-paths.d.ts.map +1 -0
- package/dist/lib/telemetry/telemetry-paths.js +103 -0
- package/dist/lib/telemetry/telemetry-paths.js.map +1 -0
- package/dist/lib/tracking-click.d.ts +20 -0
- package/dist/lib/tracking-click.d.ts.map +1 -0
- package/dist/lib/tracking-click.js +75 -0
- package/dist/lib/tracking-click.js.map +1 -0
- package/dist/lib/url-capture.d.ts +8 -0
- package/dist/lib/url-capture.d.ts.map +1 -0
- package/dist/lib/url-capture.js +17 -0
- package/dist/lib/url-capture.js.map +1 -0
- package/dist/lib/us-states.d.ts +20 -0
- package/dist/lib/us-states.d.ts.map +1 -0
- package/dist/lib/us-states.js +86 -0
- package/dist/lib/us-states.js.map +1 -0
- package/dist/lib/zod-multipart.d.ts +18 -0
- package/dist/lib/zod-multipart.d.ts.map +1 -0
- package/dist/lib/zod-multipart.js +35 -0
- package/dist/lib/zod-multipart.js.map +1 -0
- package/dist/plugins/config-plugin.d.ts +77 -0
- package/dist/plugins/config-plugin.d.ts.map +1 -0
- package/dist/plugins/config-plugin.js +216 -0
- package/dist/plugins/config-plugin.js.map +1 -0
- package/dist/plugins/discover.d.ts +72 -0
- package/dist/plugins/discover.d.ts.map +1 -0
- package/dist/plugins/discover.js +265 -0
- package/dist/plugins/discover.js.map +1 -0
- package/dist/plugins/json-schema-to-zod.d.ts +47 -0
- package/dist/plugins/json-schema-to-zod.d.ts.map +1 -0
- package/dist/plugins/json-schema-to-zod.js +85 -0
- package/dist/plugins/json-schema-to-zod.js.map +1 -0
- package/dist/plugins/loader.d.ts +34 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +348 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/plugin-api-version.d.ts +8 -0
- package/dist/plugins/plugin-api-version.d.ts.map +1 -0
- package/dist/plugins/plugin-api-version.js +11 -0
- package/dist/plugins/plugin-api-version.js.map +1 -0
- package/dist/plugins/plugin-manifest-envelope.d.ts +16 -0
- package/dist/plugins/plugin-manifest-envelope.d.ts.map +1 -0
- package/dist/plugins/plugin-manifest-envelope.js +19 -0
- package/dist/plugins/plugin-manifest-envelope.js.map +1 -0
- package/dist/scraper/behavioral-signals.d.ts +16 -0
- package/dist/scraper/behavioral-signals.d.ts.map +1 -0
- package/dist/scraper/behavioral-signals.js +30 -0
- package/dist/scraper/behavioral-signals.js.map +1 -0
- package/dist/scraper/errors.d.ts +193 -0
- package/dist/scraper/errors.d.ts.map +1 -0
- package/dist/scraper/errors.js +226 -0
- package/dist/scraper/errors.js.map +1 -0
- package/dist/scraper/fixtures.d.ts +23 -0
- package/dist/scraper/fixtures.d.ts.map +1 -0
- package/dist/scraper/fixtures.js +48 -0
- package/dist/scraper/fixtures.js.map +1 -0
- package/dist/scraper/flow-runner.d.ts +1319 -0
- package/dist/scraper/flow-runner.d.ts.map +1 -0
- package/dist/scraper/flow-runner.js +5637 -0
- package/dist/scraper/flow-runner.js.map +1 -0
- package/dist/scraper/graphql-client.d.ts +30 -0
- package/dist/scraper/graphql-client.d.ts.map +1 -0
- package/dist/scraper/graphql-client.js +14 -0
- package/dist/scraper/graphql-client.js.map +1 -0
- package/dist/scraper/http-client.d.ts +75 -0
- package/dist/scraper/http-client.d.ts.map +1 -0
- package/dist/scraper/http-client.js +189 -0
- package/dist/scraper/http-client.js.map +1 -0
- package/dist/scraper/http-status-classifier.d.ts +12 -0
- package/dist/scraper/http-status-classifier.d.ts.map +1 -0
- package/dist/scraper/http-status-classifier.js +29 -0
- package/dist/scraper/http-status-classifier.js.map +1 -0
- package/dist/scraper/metrics.d.ts +50 -0
- package/dist/scraper/metrics.d.ts.map +1 -0
- package/dist/scraper/metrics.js +85 -0
- package/dist/scraper/metrics.js.map +1 -0
- package/dist/scraper/navigate.d.ts +20 -0
- package/dist/scraper/navigate.d.ts.map +1 -0
- package/dist/scraper/navigate.js +30 -0
- package/dist/scraper/navigate.js.map +1 -0
- package/dist/scraper/oracle-sentinels.d.ts +22 -0
- package/dist/scraper/oracle-sentinels.d.ts.map +1 -0
- package/dist/scraper/oracle-sentinels.js +40 -0
- package/dist/scraper/oracle-sentinels.js.map +1 -0
- package/dist/scraper/parse-json-response.d.ts +16 -0
- package/dist/scraper/parse-json-response.d.ts.map +1 -0
- package/dist/scraper/parse-json-response.js +37 -0
- package/dist/scraper/parse-json-response.js.map +1 -0
- package/dist/scraper/pool.d.ts +37 -0
- package/dist/scraper/pool.d.ts.map +1 -0
- package/dist/scraper/pool.js +105 -0
- package/dist/scraper/pool.js.map +1 -0
- package/dist/scraper/rate-limited-json-client.d.ts +35 -0
- package/dist/scraper/rate-limited-json-client.d.ts.map +1 -0
- package/dist/scraper/rate-limited-json-client.js +29 -0
- package/dist/scraper/rate-limited-json-client.js.map +1 -0
- package/dist/scraper/raw-fetch.d.ts +49 -0
- package/dist/scraper/raw-fetch.d.ts.map +1 -0
- package/dist/scraper/raw-fetch.js +40 -0
- package/dist/scraper/raw-fetch.js.map +1 -0
- package/dist/scraper/require-response-field.d.ts +23 -0
- package/dist/scraper/require-response-field.d.ts.map +1 -0
- package/dist/scraper/require-response-field.js +42 -0
- package/dist/scraper/require-response-field.js.map +1 -0
- package/dist/scraper/retry.d.ts +33 -0
- package/dist/scraper/retry.d.ts.map +1 -0
- package/dist/scraper/retry.js +122 -0
- package/dist/scraper/retry.js.map +1 -0
- package/dist/scraper/session-browserbase.d.ts +35 -0
- package/dist/scraper/session-browserbase.d.ts.map +1 -0
- package/dist/scraper/session-browserbase.js +198 -0
- package/dist/scraper/session-browserbase.js.map +1 -0
- package/dist/scraper/session-shared.d.ts +29 -0
- package/dist/scraper/session-shared.d.ts.map +1 -0
- package/dist/scraper/session-shared.js +35 -0
- package/dist/scraper/session-shared.js.map +1 -0
- package/dist/scraper/session-steel.d.ts +31 -0
- package/dist/scraper/session-steel.d.ts.map +1 -0
- package/dist/scraper/session-steel.js +140 -0
- package/dist/scraper/session-steel.js.map +1 -0
- package/dist/scraper/session-warmup.d.ts +31 -0
- package/dist/scraper/session-warmup.d.ts.map +1 -0
- package/dist/scraper/session-warmup.js +46 -0
- package/dist/scraper/session-warmup.js.map +1 -0
- package/dist/scraper/session.d.ts +21 -0
- package/dist/scraper/session.d.ts.map +1 -0
- package/dist/scraper/session.js +28 -0
- package/dist/scraper/session.js.map +1 -0
- package/dist/scraper/stagehand-guard.d.ts +128 -0
- package/dist/scraper/stagehand-guard.d.ts.map +1 -0
- package/dist/scraper/stagehand-guard.js +337 -0
- package/dist/scraper/stagehand-guard.js.map +1 -0
- package/dist/scraper/throttle.d.ts +21 -0
- package/dist/scraper/throttle.d.ts.map +1 -0
- package/dist/scraper/throttle.js +45 -0
- package/dist/scraper/throttle.js.map +1 -0
- package/dist/scripts/hca-inbox-poll.d.ts +19 -0
- package/dist/scripts/hca-inbox-poll.d.ts.map +1 -0
- package/dist/scripts/hca-inbox-poll.js +151 -0
- package/dist/scripts/hca-inbox-poll.js.map +1 -0
- package/dist/scripts/judge-llm-batch.d.ts +98 -0
- package/dist/scripts/judge-llm-batch.d.ts.map +1 -0
- package/dist/scripts/judge-llm-batch.js +350 -0
- package/dist/scripts/judge-llm-batch.js.map +1 -0
- package/dist/scripts/llm-heal.d.ts +165 -0
- package/dist/scripts/llm-heal.d.ts.map +1 -0
- package/dist/scripts/llm-heal.js +595 -0
- package/dist/scripts/llm-heal.js.map +1 -0
- package/dist/scripts/migrate-telemetry-dir-names.d.ts +57 -0
- package/dist/scripts/migrate-telemetry-dir-names.d.ts.map +1 -0
- package/dist/scripts/migrate-telemetry-dir-names.js +156 -0
- package/dist/scripts/migrate-telemetry-dir-names.js.map +1 -0
- package/dist/scripts/probe-setinputfiles.d.ts +28 -0
- package/dist/scripts/probe-setinputfiles.d.ts.map +1 -0
- package/dist/scripts/probe-setinputfiles.js +95 -0
- package/dist/scripts/probe-setinputfiles.js.map +1 -0
- package/dist/scripts/recon-browser.d.ts +304 -0
- package/dist/scripts/recon-browser.d.ts.map +1 -0
- package/dist/scripts/recon-browser.js +1833 -0
- package/dist/scripts/recon-browser.js.map +1 -0
- package/dist/scripts/recon-generate.d.ts +182 -0
- package/dist/scripts/recon-generate.d.ts.map +1 -0
- package/dist/scripts/recon-generate.js +2572 -0
- package/dist/scripts/recon-generate.js.map +1 -0
- package/dist/scripts/recon-heal.d.ts +176 -0
- package/dist/scripts/recon-heal.d.ts.map +1 -0
- package/dist/scripts/recon-heal.js +584 -0
- package/dist/scripts/recon-heal.js.map +1 -0
- package/dist/scripts/recon-http.d.ts +19 -0
- package/dist/scripts/recon-http.d.ts.map +1 -0
- package/dist/scripts/recon-http.js +377 -0
- package/dist/scripts/recon-http.js.map +1 -0
- package/dist/scripts/recon-replay-jobs.d.ts +21 -0
- package/dist/scripts/recon-replay-jobs.d.ts.map +1 -0
- package/dist/scripts/recon-replay-jobs.js +221 -0
- package/dist/scripts/recon-replay-jobs.js.map +1 -0
- package/dist/scripts/recon-shared.d.ts +52 -0
- package/dist/scripts/recon-shared.d.ts.map +1 -0
- package/dist/scripts/recon-shared.js +68 -0
- package/dist/scripts/recon-shared.js.map +1 -0
- package/dist/scripts/recon-summarize.d.ts +15 -0
- package/dist/scripts/recon-summarize.d.ts.map +1 -0
- package/dist/scripts/recon-summarize.js +233 -0
- package/dist/scripts/recon-summarize.js.map +1 -0
- package/dist/scripts/smoke-test.d.ts +22 -0
- package/dist/scripts/smoke-test.d.ts.map +1 -0
- package/dist/scripts/smoke-test.js +236 -0
- package/dist/scripts/smoke-test.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +189 -0
- package/dist/server.js.map +1 -0
- package/dist/site-plugin.d.ts +226 -0
- package/dist/site-plugin.d.ts.map +1 -0
- package/dist/site-plugin.js +13 -0
- package/dist/site-plugin.js.map +1 -0
- package/dist/testing/answers-fixture.d.ts +13 -0
- package/dist/testing/answers-fixture.d.ts.map +1 -0
- package/dist/testing/answers-fixture.js +37 -0
- package/dist/testing/answers-fixture.js.map +1 -0
- package/dist/testing/batch-email-confirmation.d.ts +58 -0
- package/dist/testing/batch-email-confirmation.d.ts.map +1 -0
- package/dist/testing/batch-email-confirmation.js +62 -0
- package/dist/testing/batch-email-confirmation.js.map +1 -0
- package/dist/testing/batch-report.d.ts +33 -0
- package/dist/testing/batch-report.d.ts.map +1 -0
- package/dist/testing/batch-report.js +30 -0
- package/dist/testing/batch-report.js.map +1 -0
- package/dist/testing/contract-parity-suite.d.ts +55 -0
- package/dist/testing/contract-parity-suite.d.ts.map +1 -0
- package/dist/testing/contract-parity-suite.js +39 -0
- package/dist/testing/contract-parity-suite.js.map +1 -0
- package/dist/testing/coverage-guard-suite.d.ts +46 -0
- package/dist/testing/coverage-guard-suite.d.ts.map +1 -0
- package/dist/testing/coverage-guard-suite.js +39 -0
- package/dist/testing/coverage-guard-suite.js.map +1 -0
- package/dist/testing/fixtures/resume.pdf +54 -0
- package/dist/testing/integration-runner.d.ts +62 -0
- package/dist/testing/integration-runner.d.ts.map +1 -0
- package/dist/testing/integration-runner.js +46 -0
- package/dist/testing/integration-runner.js.map +1 -0
- package/dist/testing/mock-fetch-response.d.ts +7 -0
- package/dist/testing/mock-fetch-response.d.ts.map +1 -0
- package/dist/testing/mock-fetch-response.js +16 -0
- package/dist/testing/mock-fetch-response.js.map +1 -0
- package/dist/testing/persona-fixture.d.ts +77 -0
- package/dist/testing/persona-fixture.d.ts.map +1 -0
- package/dist/testing/persona-fixture.js +83 -0
- package/dist/testing/persona-fixture.js.map +1 -0
- package/dist/testing/replay-integration-suite.d.ts +50 -0
- package/dist/testing/replay-integration-suite.d.ts.map +1 -0
- package/dist/testing/replay-integration-suite.js +45 -0
- package/dist/testing/replay-integration-suite.js.map +1 -0
- package/dist/testing/resume-fixture.d.ts +39 -0
- package/dist/testing/resume-fixture.d.ts.map +1 -0
- package/dist/testing/resume-fixture.js +38 -0
- package/dist/testing/resume-fixture.js.map +1 -0
- package/dist/testmail/client.d.ts +61 -0
- package/dist/testmail/client.d.ts.map +1 -0
- package/dist/testmail/client.js +190 -0
- package/dist/testmail/client.js.map +1 -0
- package/dist/testmail/errors.d.ts +18 -0
- package/dist/testmail/errors.d.ts.map +1 -0
- package/dist/testmail/errors.js +29 -0
- package/dist/testmail/errors.js.map +1 -0
- package/dist/types/dispatch-metrics.d.ts +46 -0
- package/dist/types/dispatch-metrics.d.ts.map +1 -0
- package/dist/types/dispatch-metrics.js +25 -0
- package/dist/types/dispatch-metrics.js.map +1 -0
- package/dist/types/logging.d.ts +11 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/logging.js +3 -0
- package/dist/types/logging.js.map +1 -0
- 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"}
|