@storyshelf/core 0.7.0 → 0.8.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/dist/adapter/capture-queue.d.mts +0 -2
- package/dist/adapter/capture-runner.d.mts +9 -4
- package/dist/adapter/capture-runner.mjs +6 -2
- package/dist/adapter/database.d.mts +63 -3
- package/dist/adapter/database.mjs +4 -3
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/design.d.mts +0 -2
- package/dist/adapter/design.mjs +1 -2
- package/dist/adapter/email-sender.d.mts +0 -2
- package/dist/adapter/metadata.d.mts +0 -2
- package/dist/adapter/oauth.d.mts +0 -2
- package/dist/adapter/setup.d.mts +0 -2
- package/dist/adapter/setup.mjs +1 -2
- package/dist/adapter/storage.d.mts +1 -3
- package/dist/adapter/webhook-events.d.mts +0 -2
- package/dist/adapter/webhook-events.mjs +12 -13
- package/dist/adapter/webhook-events.mjs.map +1 -1
- package/dist/adapters/capture-target-offers.d.mts +0 -2
- package/dist/adapters/capture-target-offers.mjs +1 -2
- package/dist/adapters/capture-target.d.mts +0 -2
- package/dist/adapters/capture-target.mjs +1 -2
- package/dist/adapters/notifier/build-comment.d.mts +0 -2
- package/dist/adapters/notifier/build-comment.mjs +1 -2
- package/dist/adapters/notifier/build-state.d.mts +0 -2
- package/dist/adapters/notifier/build-state.mjs +1 -2
- package/dist/adapters/notifier/events.d.mts +0 -2
- package/dist/adapters/notifier/events.mjs +1 -2
- package/dist/adapters/notifier/format.d.mts +0 -2
- package/dist/adapters/notifier/format.mjs +1 -2
- package/dist/adapters/notifier/provider.d.mts +0 -2
- package/dist/adapters/notifier/provider.mjs +1 -2
- package/dist/adapters/notifier/state.d.mts +0 -2
- package/dist/adapters/notifier/state.mjs +1 -2
- package/dist/adapters/notifier/types.d.mts +0 -2
- package/dist/adapters/remote-browser.d.mts +112 -31
- package/dist/adapters/remote-browser.mjs +132 -34
- package/dist/adapters/remote-browser.mjs.map +1 -1
- package/dist/adapters/remote-lease-attempt.mjs +39 -0
- package/dist/adapters/remote-lease-attempt.mjs.map +1 -0
- package/dist/adapters/remote-lease-error.d.mts +25 -0
- package/dist/adapters/remote-lease-error.mjs +54 -0
- package/dist/adapters/remote-lease-error.mjs.map +1 -0
- package/dist/adapters/remote-lease-held.d.mts +15 -0
- package/dist/adapters/remote-lease-held.mjs +86 -0
- package/dist/adapters/remote-lease-held.mjs.map +1 -0
- package/dist/adapters/remote-lease-shutdown.d.mts +12 -0
- package/dist/adapters/remote-lease-shutdown.mjs +32 -0
- package/dist/adapters/remote-lease-shutdown.mjs.map +1 -0
- package/dist/adapters/remote-lease.d.mts +39 -0
- package/dist/adapters/remote-lease.mjs +175 -0
- package/dist/adapters/remote-lease.mjs.map +1 -0
- package/dist/adapters/remote-limiter.mjs +121 -0
- package/dist/adapters/remote-limiter.mjs.map +1 -0
- package/dist/adapters/remote-pool.d.mts +56 -0
- package/dist/adapters/remote-pool.mjs +195 -0
- package/dist/adapters/remote-pool.mjs.map +1 -0
- package/dist/adapters/render-runs.d.mts +0 -2
- package/dist/adapters/render-runs.mjs +1 -2
- package/dist/adapters/setup-runner.d.mts +0 -2
- package/dist/adapters/setup-runner.mjs +1 -2
- package/dist/adapters/sources.d.mts +0 -2
- package/dist/adapters/sources.mjs +1 -2
- package/dist/adapters/validate.d.mts +0 -2
- package/dist/adapters/validate.mjs +2 -2
- package/dist/adapters/validate.mjs.map +1 -1
- package/dist/ai.d.mts +0 -2
- package/dist/ai.mjs +1 -2
- package/dist/auth.d.mts +0 -2
- package/dist/auth.mjs +1 -2
- package/dist/brand-packs.d.mts +0 -2
- package/dist/brand-packs.mjs +0 -1
- package/dist/capture/a11y/axe-source.d.mts +0 -2
- package/dist/capture/a11y/axe-source.mjs +1 -2
- package/dist/capture/a11y/in-page.d.mts +1 -3
- package/dist/capture/a11y/in-page.mjs +3 -4
- package/dist/capture/a11y/in-page.mjs.map +1 -1
- package/dist/capture/a11y/map.d.mts +0 -2
- package/dist/capture/a11y/map.mjs +1 -2
- package/dist/capture/a11y/options.d.mts +0 -2
- package/dist/capture/a11y/options.mjs +1 -2
- package/dist/capture/adapter.d.mts +5 -2
- package/dist/capture/adapter.mjs +1 -2
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +0 -2
- package/dist/capture/affected.mjs +1 -2
- package/dist/capture/attempt-logger.mjs +1 -2
- package/dist/capture/browsers.d.mts +0 -2
- package/dist/capture/browsers.mjs +1 -2
- package/dist/capture/build-state/deliver.d.mts +0 -2
- package/dist/capture/build-state/deliver.mjs +1 -2
- package/dist/capture/build-state/notify-job.d.mts +0 -2
- package/dist/capture/build-state/notify-job.mjs +1 -2
- package/dist/capture/build-state/publisher.d.mts +0 -2
- package/dist/capture/build-state/publisher.mjs +1 -2
- package/dist/capture/build-state/resume.d.mts +0 -2
- package/dist/capture/build-state/resume.mjs +1 -2
- package/dist/capture/build-state/types.d.mts +1 -3
- package/dist/capture/catalog/catalogue.d.mts +0 -2
- package/dist/capture/catalog/catalogue.mjs +1 -2
- package/dist/capture/catalog/components.d.mts +0 -2
- package/dist/capture/catalog/components.mjs +1 -2
- package/dist/capture/catalog/history.d.mts +0 -2
- package/dist/capture/catalog/history.mjs +1 -2
- package/dist/capture/catalog/hook.d.mts +0 -2
- package/dist/capture/catalog/hook.mjs +1 -2
- package/dist/capture/catalog/index.d.mts +2 -2
- package/dist/capture/catalog/load.d.mts +0 -2
- package/dist/capture/catalog/load.mjs +1 -2
- package/dist/capture/catalog/parse.d.mts +0 -2
- package/dist/capture/catalog/parse.mjs +1 -2
- package/dist/capture/catalog/read.d.mts +6 -3
- package/dist/capture/catalog/read.mjs +14 -8
- package/dist/capture/catalog/read.mjs.map +1 -1
- package/dist/capture/catalog/types.d.mts +0 -2
- package/dist/capture/comparison-reference.d.mts +27 -0
- package/dist/capture/comparison-reference.mjs +75 -0
- package/dist/capture/comparison-reference.mjs.map +1 -0
- package/dist/capture/consumer/capture-handler.d.mts +1 -3
- package/dist/capture/consumer/capture-handler.mjs +1 -2
- package/dist/capture/consumer/idle.d.mts +0 -2
- package/dist/capture/consumer/idle.mjs +1 -2
- package/dist/capture/consumer/index.d.mts +0 -2
- package/dist/capture/consumer/index.mjs +1 -2
- package/dist/capture/consumer/loop.mjs +1 -2
- package/dist/capture/consumer/metrics.d.mts +0 -2
- package/dist/capture/consumer/metrics.mjs +1 -2
- package/dist/capture/consumer/retry.d.mts +0 -2
- package/dist/capture/consumer/retry.mjs +1 -2
- package/dist/capture/consumer/run-job.mjs +1 -2
- package/dist/capture/consumer/startup.mjs +1 -2
- package/dist/capture/consumer/types.d.mts +0 -2
- package/dist/capture/crash-failure.d.mts +0 -2
- package/dist/capture/crash-failure.mjs +1 -2
- package/dist/capture/db-queue/cadence.d.mts +0 -2
- package/dist/capture/db-queue/cadence.mjs +1 -2
- package/dist/capture/db-queue/claim.d.mts +0 -2
- package/dist/capture/db-queue/claim.mjs +20 -4
- package/dist/capture/db-queue/claim.mjs.map +1 -1
- package/dist/capture/db-queue/clock.mjs +1 -2
- package/dist/capture/db-queue/codec.mjs +1 -2
- package/dist/capture/db-queue/index.d.mts +0 -2
- package/dist/capture/db-queue/index.mjs +3 -3
- package/dist/capture/db-queue/index.mjs.map +1 -1
- package/dist/capture/db-queue/keeper.d.mts +0 -2
- package/dist/capture/db-queue/keeper.mjs +1 -2
- package/dist/capture/db-queue/lease.mjs +1 -2
- package/dist/capture/db-queue/lifecycle.mjs +1 -2
- package/dist/capture/db-queue/operations.mjs +1 -2
- package/dist/capture/db-queue/poll-loop.d.mts +0 -2
- package/dist/capture/db-queue/poll-loop.mjs +1 -2
- package/dist/capture/db-queue/poll.d.mts +0 -2
- package/dist/capture/db-queue/poll.mjs +1 -2
- package/dist/capture/db-queue/timers.d.mts +0 -2
- package/dist/capture/db-queue/timers.mjs +1 -2
- package/dist/capture/db-queue/types.d.mts +0 -2
- package/dist/capture/db-queue/types.mjs +1 -2
- package/dist/capture/db-queue/types.mjs.map +1 -1
- package/dist/capture/db-queue/wake.mjs +1 -2
- package/dist/capture/design.mjs +1 -2
- package/dist/capture/diff-record.mjs +1 -2
- package/dist/capture/dispatch.d.mts +1 -3
- package/dist/capture/dispatch.mjs +17 -5
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/enrich.mjs +1 -2
- package/dist/capture/failure-sets.mjs +1 -2
- package/dist/capture/fingerprint.d.mts +0 -2
- package/dist/capture/fingerprint.mjs +1 -2
- package/dist/capture/forked/channel.d.mts +0 -2
- package/dist/capture/forked/child.d.mts +0 -2
- package/dist/capture/forked/child.mjs +1 -2
- package/dist/capture/forked/crash-tracker.mjs +1 -2
- package/dist/capture/forked/decision.d.mts +0 -2
- package/dist/capture/forked/decision.mjs +1 -2
- package/dist/capture/forked/exit.mjs +1 -2
- package/dist/capture/forked/fork.d.mts +0 -2
- package/dist/capture/forked/fork.mjs +1 -2
- package/dist/capture/forked/forked-capture.d.mts +0 -2
- package/dist/capture/forked/forked-capture.mjs +1 -2
- package/dist/capture/forked/lease-book.mjs +1 -2
- package/dist/capture/forked/protocol.d.mts +0 -2
- package/dist/capture/forked/protocol.mjs +1 -2
- package/dist/capture/forked/runs.mjs +1 -2
- package/dist/capture/guards.mjs +1 -2
- package/dist/capture/ignore-regions.d.mts +36 -0
- package/dist/capture/ignore-regions.mjs +65 -0
- package/dist/capture/ignore-regions.mjs.map +1 -0
- package/dist/capture/isolate.mjs +1 -2
- package/dist/capture/job-lease.d.mts +0 -2
- package/dist/capture/job-lease.mjs +1 -2
- package/dist/capture/matrix.mjs +4 -4
- package/dist/capture/matrix.mjs.map +1 -1
- package/dist/capture/modes.d.mts +0 -2
- package/dist/capture/modes.mjs +2 -3
- package/dist/capture/modes.mjs.map +1 -1
- package/dist/capture/orchestrator.d.mts +0 -2
- package/dist/capture/orchestrator.mjs +2 -3
- package/dist/capture/pipeline.d.mts +0 -2
- package/dist/capture/pipeline.mjs +37 -6
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/progress.d.mts +0 -2
- package/dist/capture/progress.mjs +1 -2
- package/dist/capture/publish/accept.d.mts +0 -2
- package/dist/capture/publish/accept.mjs +1 -2
- package/dist/capture/publish/complete.d.mts +1 -3
- package/dist/capture/publish/complete.mjs +1 -2
- package/dist/capture/publish/extract.d.mts +0 -2
- package/dist/capture/publish/extract.mjs +6 -5
- package/dist/capture/publish/extract.mjs.map +1 -1
- package/dist/capture/publish/handler.d.mts +1 -3
- package/dist/capture/publish/handler.mjs +1 -2
- package/dist/capture/publish/index.d.mts +2 -1
- package/dist/capture/publish/invalid-zip.d.mts +8 -0
- package/dist/capture/publish/invalid-zip.mjs +11 -0
- package/dist/capture/publish/invalid-zip.mjs.map +1 -0
- package/dist/capture/publish/limits.d.mts +0 -2
- package/dist/capture/publish/limits.mjs +1 -2
- package/dist/capture/publish/published.d.mts +0 -2
- package/dist/capture/publish/published.mjs +1 -2
- package/dist/capture/publish/run.d.mts +1 -3
- package/dist/capture/publish/run.mjs +1 -2
- package/dist/capture/rediff.d.mts +1 -3
- package/dist/capture/rediff.mjs +19 -6
- package/dist/capture/rediff.mjs.map +1 -1
- package/dist/capture/render.mjs +1 -2
- package/dist/capture/render.mjs.map +1 -1
- package/dist/capture/scratch.d.mts +0 -2
- package/dist/capture/scratch.mjs +2 -4
- package/dist/capture/scratch.mjs.map +1 -1
- package/dist/capture/shard-plan.mjs +1 -2
- package/dist/capture/shards/context.mjs +3 -3
- package/dist/capture/shards/context.mjs.map +1 -1
- package/dist/capture/shards/execute.mjs +4 -3
- package/dist/capture/shards/execute.mjs.map +1 -1
- package/dist/capture/shards/fan-out.mjs +1 -2
- package/dist/capture/shards/history.mjs +1 -2
- package/dist/capture/shards/reduce.mjs +1 -2
- package/dist/capture/sizing.d.mts +0 -2
- package/dist/capture/sizing.mjs +1 -2
- package/dist/capture/skip-checks.mjs +1 -2
- package/dist/capture/statics.d.mts +0 -2
- package/dist/capture/statics.mjs +2 -4
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/storybook-urls.d.mts +0 -2
- package/dist/capture/storybook-urls.mjs +3 -3
- package/dist/capture/storybook-urls.mjs.map +1 -1
- package/dist/capture/storybook.d.mts +0 -2
- package/dist/capture/storybook.mjs +8 -4
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture/target.mjs +1 -2
- package/dist/capture/targets.d.mts +0 -2
- package/dist/capture/targets.mjs +1 -2
- package/dist/capture/tests.d.mts +0 -2
- package/dist/capture/tests.mjs +13 -3
- package/dist/capture/tests.mjs.map +1 -1
- package/dist/capture/token-chunks.mjs +24 -7
- package/dist/capture/token-chunks.mjs.map +1 -1
- package/dist/capture.d.mts +5 -2
- package/dist/capture.mjs +5 -2
- package/dist/config.d.mts +16 -3
- package/dist/config.mjs +6 -3
- package/dist/config.mjs.map +1 -1
- package/dist/diff.d.mts +0 -2
- package/dist/diff.mjs +1 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/insights/budget.d.mts +0 -2
- package/dist/insights/budget.mjs +1 -2
- package/dist/insights/envelope.d.mts +0 -2
- package/dist/insights/envelope.mjs +1 -2
- package/dist/insights/evidence-health.d.mts +0 -2
- package/dist/insights/evidence-health.mjs +1 -2
- package/dist/insights/evidence.d.mts +0 -2
- package/dist/insights/evidence.mjs +1 -2
- package/dist/insights/hash.d.mts +0 -2
- package/dist/insights/hash.mjs +1 -2
- package/dist/insights/limits.d.mts +0 -2
- package/dist/insights/limits.mjs +1 -2
- package/dist/insights/prompts/v1.d.mts +0 -2
- package/dist/insights/prompts/v1.mjs +1 -2
- package/dist/insights/redact.d.mts +0 -2
- package/dist/insights/redact.mjs +1 -2
- package/dist/insights/text.mjs +1 -2
- package/dist/logger.d.mts +0 -2
- package/dist/logger.mjs +1 -2
- package/dist/models/ai-budget-alert.d.mts +0 -2
- package/dist/models/ai-budget-alert.mjs +1 -2
- package/dist/models/ai-usage.d.mts +0 -2
- package/dist/models/ai-usage.mjs +1 -2
- package/dist/models/baseline-approval.d.mts +18 -0
- package/dist/models/baseline-approval.mjs +41 -0
- package/dist/models/baseline-approval.mjs.map +1 -0
- package/dist/models/baseline-archive.d.mts +0 -2
- package/dist/models/baseline-archive.mjs +1 -2
- package/dist/models/baseline-atomic.mjs +66 -0
- package/dist/models/baseline-atomic.mjs.map +1 -0
- package/dist/models/baseline-conflict.d.mts +6 -0
- package/dist/models/baseline-conflict.mjs +9 -0
- package/dist/models/baseline-conflict.mjs.map +1 -0
- package/dist/models/baseline-export.d.mts +0 -2
- package/dist/models/baseline-export.mjs +1 -2
- package/dist/models/baseline-import.mjs +1 -2
- package/dist/models/baseline-origin.d.mts +16 -0
- package/dist/models/baseline-origin.mjs +35 -0
- package/dist/models/baseline-origin.mjs.map +1 -0
- package/dist/models/baseline-status.d.mts +0 -2
- package/dist/models/baseline-status.mjs +1 -2
- package/dist/models/baseline-transfer.d.mts +1 -2
- package/dist/models/baseline-transfer.mjs +30 -2
- package/dist/models/baseline-transfer.mjs.map +1 -1
- package/dist/models/baseline.d.mts +5 -2
- package/dist/models/baseline.mjs +91 -12
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build-component.d.mts +0 -2
- package/dist/models/build-component.mjs +1 -2
- package/dist/models/build-review-status.d.mts +0 -2
- package/dist/models/build-review-status.mjs +1 -2
- package/dist/models/build-review.d.mts +0 -2
- package/dist/models/build-review.mjs +1 -2
- package/dist/models/build.d.mts +1 -3
- package/dist/models/build.mjs +14 -15
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +0 -2
- package/dist/models/capture-attempt.mjs +1 -2
- package/dist/models/capture-job.d.mts +0 -2
- package/dist/models/capture-job.mjs +1 -2
- package/dist/models/capture-log.d.mts +0 -2
- package/dist/models/capture-log.mjs +1 -2
- package/dist/models/capture-shard.d.mts +0 -2
- package/dist/models/capture-shard.mjs +1 -2
- package/dist/models/changeset.d.mts +0 -2
- package/dist/models/changeset.mjs +1 -2
- package/dist/models/columns.mjs +1 -2
- package/dist/models/comment.d.mts +0 -2
- package/dist/models/comment.mjs +1 -2
- package/dist/models/component.d.mts +0 -2
- package/dist/models/component.mjs +1 -2
- package/dist/models/connections.d.mts +0 -2
- package/dist/models/connections.mjs +1 -2
- package/dist/models/content-ref.d.mts +0 -2
- package/dist/models/content-ref.mjs +1 -2
- package/dist/models/credentials.d.mts +0 -2
- package/dist/models/credentials.mjs +1 -2
- package/dist/models/design-credentials.d.mts +0 -2
- package/dist/models/design-credentials.mjs +1 -2
- package/dist/models/design-health.d.mts +0 -2
- package/dist/models/design-health.mjs +1 -2
- package/dist/models/design-nodes.d.mts +2 -4
- package/dist/models/design-nodes.mjs +1 -2
- package/dist/models/design-renders.mjs +1 -2
- package/dist/models/design-resolve.d.mts +0 -2
- package/dist/models/design-resolve.mjs +1 -2
- package/dist/models/design.d.mts +0 -2
- package/dist/models/design.mjs +1 -2
- package/dist/models/inherited-ratio.d.mts +0 -2
- package/dist/models/inherited-ratio.mjs +1 -2
- package/dist/models/insight.d.mts +0 -2
- package/dist/models/insight.mjs +1 -2
- package/dist/models/label.d.mts +0 -2
- package/dist/models/label.mjs +1 -2
- package/dist/models/member.d.mts +0 -2
- package/dist/models/member.mjs +1 -2
- package/dist/models/notification-channel.d.mts +0 -2
- package/dist/models/notification-channel.mjs +1 -2
- package/dist/models/notification-subscription.d.mts +0 -2
- package/dist/models/notification-subscription.mjs +1 -2
- package/dist/models/project-group-mapping.d.mts +0 -2
- package/dist/models/project-group-mapping.mjs +1 -2
- package/dist/models/project.d.mts +0 -2
- package/dist/models/project.mjs +1 -2
- package/dist/models/public-origin.d.mts +0 -2
- package/dist/models/public-origin.mjs +1 -2
- package/dist/models/review-switch-off.d.mts +0 -2
- package/dist/models/review-switch-off.mjs +1 -2
- package/dist/models/site-settings.d.mts +0 -2
- package/dist/models/site-settings.mjs +1 -2
- package/dist/models/snapshot.d.mts +3 -2
- package/dist/models/snapshot.mjs +4 -2
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/token.d.mts +0 -2
- package/dist/models/token.mjs +1 -2
- package/dist/models/usage.d.mts +0 -2
- package/dist/models/usage.mjs +1 -2
- package/dist/models/user.d.mts +0 -2
- package/dist/models/user.mjs +1 -2
- package/dist/models/webhook.d.mts +0 -2
- package/dist/models/webhook.mjs +1 -2
- package/dist/models.d.mts +5 -2
- package/dist/models.mjs +5 -2
- package/dist/options.d.mts +0 -2
- package/dist/options.mjs +2 -4
- package/dist/options.mjs.map +1 -1
- package/dist/paths.d.mts +3 -3
- package/dist/paths.mjs +7 -3
- package/dist/paths.mjs.map +1 -1
- package/dist/retention/ai.d.mts +1 -3
- package/dist/retention/ai.mjs +0 -1
- package/dist/retention/pending.mjs +1 -2
- package/dist/retention/published-gzip-sweep.mjs +28 -0
- package/dist/retention/published-gzip-sweep.mjs.map +1 -0
- package/dist/retention/screenshot-sweep.d.mts +0 -2
- package/dist/retention/screenshot-sweep.mjs +1 -2
- package/dist/retention.d.mts +0 -2
- package/dist/retention.mjs +5 -2
- package/dist/retention.mjs.map +1 -1
- package/dist/schema/baseline.d.mts +2 -2
- package/dist/schema/build-component.d.mts +0 -2
- package/dist/schema/build-review.d.mts +0 -2
- package/dist/schema/build.d.mts +0 -2
- package/dist/schema/capture-attempt.d.mts +0 -2
- package/dist/schema/capture-job.d.mts +0 -2
- package/dist/schema/capture-shard.d.mts +0 -2
- package/dist/schema/comment.d.mts +0 -2
- package/dist/schema/connection.d.mts +0 -2
- package/dist/schema/content-ref.d.mts +0 -2
- package/dist/schema/design.d.mts +0 -2
- package/dist/schema/insight.d.mts +0 -2
- package/dist/schema/label.d.mts +0 -2
- package/dist/schema/member.d.mts +0 -2
- package/dist/schema/notification.d.mts +0 -2
- package/dist/schema/project-group-mapping.d.mts +0 -2
- package/dist/schema/project.d.mts +0 -2
- package/dist/schema/site-setting.d.mts +0 -2
- package/dist/schema/snapshot.d.mts +5 -2
- package/dist/schema/token.d.mts +0 -2
- package/dist/schema/usage.d.mts +0 -2
- package/dist/schema/user.d.mts +0 -2
- package/dist/schema/webhook.d.mts +0 -2
- package/dist/schema.d.mts +4 -6
- package/dist/serverless.d.mts +0 -2
- package/dist/serverless.mjs +1 -2
- package/dist/test-helpers/build-reference-contract.d.mts +14 -0
- package/dist/test-helpers/build-reference-contract.mjs +66 -0
- package/dist/test-helpers/build-reference-contract.mjs.map +1 -0
- package/dist/test-helpers/create-project.d.mts +0 -2
- package/dist/test-helpers/create-project.mjs +1 -2
- package/dist/test-helpers/database-contract.d.mts +0 -2
- package/dist/test-helpers/database-contract.mjs +37 -2
- package/dist/test-helpers/database-contract.mjs.map +1 -1
- package/dist/test-helpers/deferred.d.mts +0 -2
- package/dist/test-helpers/deferred.mjs +1 -2
- package/dist/test-helpers/design-contract.d.mts +0 -2
- package/dist/test-helpers/design-contract.mjs +1 -2
- package/dist/test-helpers/fake-adapters.d.mts +0 -2
- package/dist/test-helpers/fake-adapters.mjs +1 -2
- package/dist/test-helpers/fake-database.d.mts +0 -2
- package/dist/test-helpers/fake-database.mjs +7 -2
- package/dist/test-helpers/fake-database.mjs.map +1 -1
- package/dist/test-helpers/fake-design.d.mts +0 -2
- package/dist/test-helpers/fake-design.mjs +1 -2
- package/dist/test-helpers/fake-notifier.d.mts +0 -2
- package/dist/test-helpers/fake-notifier.mjs +1 -2
- package/dist/test-helpers/fake-storage.d.mts +0 -2
- package/dist/test-helpers/fake-storage.mjs +1 -2
- package/dist/test-helpers/fake-tables.mjs +5 -2
- package/dist/test-helpers/fake-tables.mjs.map +1 -1
- package/dist/test-helpers/manual-clock.d.mts +0 -2
- package/dist/test-helpers/manual-clock.mjs +1 -2
- package/dist/test-helpers/notifier-contract.d.mts +0 -2
- package/dist/test-helpers/notifier-contract.mjs +1 -2
- package/dist/test-helpers/queue-contract.d.mts +0 -2
- package/dist/test-helpers/queue-contract.mjs +1 -2
- package/dist/test-helpers/queue-multi-instance.d.mts +0 -2
- package/dist/test-helpers/queue-multi-instance.mjs +1 -2
- package/dist/test-helpers/runner-contract.d.mts +0 -2
- package/dist/test-helpers/runner-contract.mjs +1 -2
- package/dist/test-helpers/sql-chunks.mjs +2 -2
- package/dist/test-helpers/sql-chunks.mjs.map +1 -1
- package/dist/test-helpers/storage-contract.d.mts +0 -2
- package/dist/test-helpers/storage-contract.mjs +1 -2
- package/dist/test-helpers.d.mts +2 -1
- package/dist/test-helpers.mjs +2 -1
- package/dist/tracing.mjs +36 -6
- package/dist/tracing.mjs.map +1 -1
- package/dist/types.d.mts +0 -2
- package/dist/types.mjs +1 -2
- package/dist/urls.d.mts +0 -2
- package/dist/urls.mjs +1 -2
- package/dist/utils/adaptive-concurrency.d.mts +0 -2
- package/dist/utils/adaptive-concurrency.mjs +1 -2
- package/dist/utils/connect-retry.d.mts +2 -2
- package/dist/utils/connect-retry.mjs +2 -3
- package/dist/utils/connect-retry.mjs.map +1 -1
- package/dist/utils/encrypt.d.mts +0 -2
- package/dist/utils/encrypt.mjs +1 -2
- package/dist/utils/environment.d.mts +0 -2
- package/dist/utils/environment.mjs +1 -2
- package/dist/utils/hash.d.mts +0 -2
- package/dist/utils/hash.mjs +1 -2
- package/dist/utils/http.d.mts +13 -3
- package/dist/utils/http.mjs +79 -17
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/map-adaptive.d.mts +0 -2
- package/dist/utils/map-adaptive.mjs +1 -2
- package/dist/utils/map-limit.d.mts +0 -2
- package/dist/utils/map-limit.mjs +1 -2
- package/dist/utils/mime.d.mts +0 -2
- package/dist/utils/mime.mjs +1 -2
- package/dist/utils/page-limiter.d.mts +0 -2
- package/dist/utils/page-limiter.mjs +1 -2
- package/dist/utils/path-security.d.mts +0 -2
- package/dist/utils/path-security.mjs +2 -4
- package/dist/utils/path-security.mjs.map +1 -1
- package/dist/utils/public-origin.d.mts +0 -2
- package/dist/utils/public-origin.mjs +1 -2
- package/dist/utils/redact.d.mts +0 -2
- package/dist/utils/redact.mjs +1 -2
- package/dist/utils/remote-environment.d.mts +40 -3
- package/dist/utils/remote-environment.mjs +52 -3
- package/dist/utils/remote-environment.mjs.map +1 -1
- package/dist/utils/resources.d.mts +0 -2
- package/dist/utils/resources.mjs +1 -2
- package/dist/utils/screenshot-store.d.mts +0 -2
- package/dist/utils/screenshot-store.mjs +1 -2
- package/dist/utils/session-gate.d.mts +7 -6
- package/dist/utils/session-gate.mjs +28 -12
- package/dist/utils/session-gate.mjs.map +1 -1
- package/dist/utils/storybook-token.d.mts +11 -3
- package/dist/utils/storybook-token.mjs +10 -9
- package/dist/utils/storybook-token.mjs.map +1 -1
- package/dist/utils/storybook-url.d.mts +0 -2
- package/dist/utils/storybook-url.mjs +1 -2
- package/dist/utils/timing.d.mts +0 -2
- package/dist/utils/timing.mjs +1 -2
- package/dist/utils/ulid.d.mts +0 -2
- package/dist/utils/ulid.mjs +1 -2
- package/dist/utils/zip-read.mjs +1 -2
- package/dist/utils/zip-write.d.mts +0 -2
- package/dist/utils/zip-write.mjs +1 -2
- package/dist/utils.d.mts +5 -5
- package/dist/utils.mjs +5 -5
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":[],"sources":["../../../src/capture/db-queue/types.ts"],"sourcesContent":["/** Option, job and runtime types of the database capture queue. */\nimport type {\n CaptureJob,\n LeaseRenewal,\n PollableCaptureQueue,\n PollableJob,\n} from \"../../adapters/capture-queue.ts\";\nimport type { AdapterLifecycle } from \"../../adapters/metadata.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport type { CaptureJobModel } from \"../../models/capture-job.ts\";\nimport type { CaptureJobKind } from \"../../schema/capture-job.ts\";\nimport type { QueueTimers } from \"./timers.ts\";\nimport type { WakeSignal } from \"./wake.ts\";\n\n/** Options of {@link createDatabaseCaptureQueue}. */\nexport interface DatabaseCaptureQueueOptions {\n /** Job kinds this instance polls (default `[\"capture\"]`); enqueue accepts every kind. */\n kinds?: readonly CaptureJobKind[];\n /** Lease granted per attempt, renewed by a heartbeat and by progress (default {@link DEFAULT_LEASE_MS}, 5 min; `testing.leaseSeconds`). */\n leaseMs?: number;\n /** Retries after the first attempt (`testing.retries`, default 2: three attempts in total). */\n retries?: number;\n /** Identity written on the attempt rows this instance holds (default host, pid and a random tag). */\n owner?: string;\n /** Clock in epoch ms (default `Date.now`); tests inject one to drive leases and visibility. */\n now?: () => number;\n /** Timers of the local wake wait (default the global timers); tests inject a manual clock. */\n timers?: QueueTimers;\n /** Explicit logger override; the host normally binds one through `setLogger`. */\n logger?: Logger;\n /**\n * Called after a job failed because its last attempt lost its lease: nothing was running to\n * record the failure, so the host writes it (a build left `capturing`). May run on every\n * instance that finds the job, so it must be idempotent; a throw is logged and ignored.\n */\n onExhausted?: (job: DatabaseJob, error: string) => Promise<void>;\n}\n\n/** Default lease per attempt: long enough for a slow stage, short enough to recover a crash. */\nexport const DEFAULT_LEASE_MS = 5 * 60_000;\n\n/** Default `testing.retries` (ADR 0006, decision 11). */\nexport const DEFAULT_RETRIES = 2;\n\n/** A job of any kind, as `enqueueJob` takes it. */\nexport interface QueueJobInput {\n kind: CaptureJobKind;\n /** Build the job works on; notify jobs may have none. */\n buildId?: string | null;\n /** `capture_shards` row, for a shard capture job. */\n shard?: string;\n reqId?: string;\n traceparent?: string;\n /** Kind-specific fields (channel id, zip key, …), stored as JSON. */\n data?: Record<string, unknown>;\n /** Attempts allowed in total for this job; defaults to the queue's (`retries` + 1). */\n maxAttempts?: number;\n}\n\n/** A job claimed from the database queue. */\nexport interface DatabaseJob extends PollableJob {\n /** Id of the job row (`receipt` is the attempt row, `<jobId>:<attempt>`). */\n jobId: string;\n kind: CaptureJobKind;\n /** Attempt number, from 1 (`attempts` is the number made before this one). */\n attempt: number;\n maxAttempts: number;\n /** Kind-specific fields given at enqueue. */\n data: Record<string, unknown>;\n}\n\n/** The database queue: a {@link PollableCaptureQueue} plus multi-kind enqueue and a local wake. */\nexport interface DatabaseCaptureQueue extends PollableCaptureQueue {\n readonly lifecycle: AdapterLifecycle;\n poll(options?: { waitMs?: number }): Promise<DatabaseJob | null>;\n extend(job: PollableJob): Promise<LeaseRenewal>;\n /** Put a job of any kind on the queue; resolves to its job id. */\n enqueueJob(job: QueueJobInput): Promise<string>;\n /** Cancel a job by job id, or every unfinished job of a build (every kind) by build id. */\n cancel(id: string): Promise<boolean>;\n /** Read the job's state without renewing its lease (the 5 s cancel check). */\n inspect(job: PollableJob): Promise<LeaseRenewal>;\n /**\n * Resolve true when this instance enqueues a job (including one enqueued since the last `poll`\n * began, so no wake-up is lost), false after `ms`.\n */\n waitForWork(ms: number): Promise<boolean>;\n}\n\n/** State shared by the queue's modules. */\nexport interface QueueRuntime {\n model: CaptureJobModel;\n kinds: readonly CaptureJobKind[];\n leaseMs: number;\n maxAttempts: number;\n owner: string;\n now: () => number;\n wake: WakeSignal;\n /** Wake version read when the latest poll began. */\n pollVersion: number;\n logger?: Logger;\n onExhausted?: DatabaseCaptureQueueOptions[\"onExhausted\"];\n}\n\n/** The capture-shaped job `enqueue` takes, re-exported for the modules. */\nexport type { CaptureJob };\n"],"mappings":";;;;;AAuCA,MAAa,mBAAmB;;AAGhC,MAAa,kBAAkB"}
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../../src/capture/db-queue/types.ts"],"sourcesContent":["/** Option, job and runtime types of the database capture queue. */\nimport type {\n CaptureJob,\n LeaseRenewal,\n PollableCaptureQueue,\n PollableJob,\n} from \"../../adapters/capture-queue.ts\";\nimport type { AdapterLifecycle } from \"../../adapters/metadata.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport type { CaptureJobModel } from \"../../models/capture-job.ts\";\nimport type { CaptureJobKind } from \"../../schema/capture-job.ts\";\nimport type { QueueTimers } from \"./timers.ts\";\nimport type { WakeSignal } from \"./wake.ts\";\n\n/** Options of {@link createDatabaseCaptureQueue}. */\nexport interface DatabaseCaptureQueueOptions {\n /** Job kinds this instance polls (default `[\"capture\"]`); enqueue accepts every kind. */\n kinds?: readonly CaptureJobKind[];\n /** Lease granted per attempt, renewed by a heartbeat and by progress (default {@link DEFAULT_LEASE_MS}, 5 min; `testing.leaseSeconds`). */\n leaseMs?: number;\n /** Retries after the first attempt (`testing.retries`, default 2: three attempts in total). */\n retries?: number;\n /** Identity written on the attempt rows this instance holds (default host, pid and a random tag). */\n owner?: string;\n /** Clock in epoch ms (default `Date.now`); tests inject one to drive leases and visibility. */\n now?: () => number;\n /** Timers of the local wake wait (default the global timers); tests inject a manual clock. */\n timers?: QueueTimers;\n /** Explicit logger override; the host normally binds one through `setLogger`. */\n logger?: Logger;\n /**\n * Called after a job failed because its last attempt lost its lease: nothing was running to\n * record the failure, so the host writes it (a build left `capturing`). May run on every\n * instance that finds the job, so it must be idempotent; a throw is logged and ignored.\n */\n onExhausted?: (job: DatabaseJob, error: string) => Promise<void>;\n}\n\n/** Default lease per attempt: long enough for a slow stage, short enough to recover a crash. */\nexport const DEFAULT_LEASE_MS = 5 * 60_000;\n\n/** Default `testing.retries` (ADR 0006, decision 11). */\nexport const DEFAULT_RETRIES = 2;\n\n/** A job of any kind, as `enqueueJob` takes it. */\nexport interface QueueJobInput {\n kind: CaptureJobKind;\n /** Build the job works on; notify jobs may have none. */\n buildId?: string | null;\n /** `capture_shards` row, for a shard capture job. */\n shard?: string;\n reqId?: string;\n traceparent?: string;\n /** Kind-specific fields (channel id, zip key, …), stored as JSON. */\n data?: Record<string, unknown>;\n /** Attempts allowed in total for this job; defaults to the queue's (`retries` + 1). */\n maxAttempts?: number;\n}\n\n/** A job claimed from the database queue. */\nexport interface DatabaseJob extends PollableJob {\n /** Id of the job row (`receipt` is the attempt row, `<jobId>:<attempt>`). */\n jobId: string;\n kind: CaptureJobKind;\n /** Attempt number, from 1 (`attempts` is the number made before this one). */\n attempt: number;\n maxAttempts: number;\n /** Kind-specific fields given at enqueue. */\n data: Record<string, unknown>;\n}\n\n/** The database queue: a {@link PollableCaptureQueue} plus multi-kind enqueue and a local wake. */\nexport interface DatabaseCaptureQueue extends PollableCaptureQueue {\n readonly lifecycle: AdapterLifecycle;\n poll(options?: { waitMs?: number }): Promise<DatabaseJob | null>;\n extend(job: PollableJob): Promise<LeaseRenewal>;\n /** Put a job of any kind on the queue; resolves to its job id. */\n enqueueJob(job: QueueJobInput): Promise<string>;\n /** Cancel a job by job id, or every unfinished job of a build (every kind) by build id. */\n cancel(id: string): Promise<boolean>;\n /** Read the job's state without renewing its lease (the 5 s cancel check). */\n inspect(job: PollableJob): Promise<LeaseRenewal>;\n /**\n * Resolve true when this instance enqueues a job (including one enqueued since the last `poll`\n * began, so no wake-up is lost), false after `ms`.\n */\n waitForWork(ms: number): Promise<boolean>;\n}\n\n/** State shared by the queue's modules. */\nexport interface QueueRuntime {\n model: CaptureJobModel;\n kinds: readonly CaptureJobKind[];\n leaseMs: number;\n maxAttempts: number;\n owner: string;\n now: () => number;\n timers?: QueueTimers;\n wake: WakeSignal;\n /** Wake version read when the latest poll began. */\n pollVersion: number;\n logger?: Logger;\n onExhausted?: DatabaseCaptureQueueOptions[\"onExhausted\"];\n}\n\n/** The capture-shaped job `enqueue` takes, re-exported for the modules. */\nexport type { CaptureJob };\n"],"mappings":";;;;;AAuCA,MAAa,mBAAmB;;AAGhC,MAAa,kBAAkB"}
|
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { REAL_TIMERS } from "./timers.mjs";
|
|
5
|
-
|
|
5
|
+
// src/capture/db-queue/wake.ts
|
|
6
6
|
/** In-process wake signal: an enqueue on this instance wakes its waiting poller at once. */
|
|
7
7
|
/** Create a wake signal over `timers` (unref'd globals by default). */
|
|
8
8
|
function createWakeSignal(timers = REAL_TIMERS) {
|
|
@@ -42,7 +42,6 @@ async function waitFor(timers, waiters, ms) {
|
|
|
42
42
|
waiters.add(settle);
|
|
43
43
|
return await promise;
|
|
44
44
|
}
|
|
45
|
-
//#endregion
|
|
46
45
|
export { createWakeSignal };
|
|
47
46
|
|
|
48
47
|
//# sourceMappingURL=wake.mjs.map
|
package/dist/capture/design.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/design.ts
|
|
5
5
|
/**
|
|
6
6
|
* Resolve a story's design URL. `storyshelf.figma` (plain string) wins over the
|
|
7
7
|
* `design` addon shape (`string | {url} | {type,url} | {type,url}[]`, first URL wins).
|
|
@@ -33,7 +33,6 @@ function logInvalidDesigns(logger, stories) {
|
|
|
33
33
|
design: story.designInvalid
|
|
34
34
|
}, "ignored invalid design url");
|
|
35
35
|
}
|
|
36
|
-
//#endregion
|
|
37
36
|
export { extractDesignUrl, logInvalidDesigns };
|
|
38
37
|
|
|
39
38
|
//# sourceMappingURL=design.mjs.map
|
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { DEFAULT_DIFF_OPTIONS, diffImagesAsync } from "@storyshelf/image";
|
|
5
|
-
|
|
5
|
+
// src/capture/diff-record.ts
|
|
6
6
|
/** Diff a stored screenshot against a baseline and persist the overlay; shared by capture and re-diff. */
|
|
7
7
|
/** Per-story `diffThreshold` when it is a finite number in 0..1; otherwise the project threshold. */
|
|
8
8
|
function resolvePixelThreshold(projectThreshold, override) {
|
|
@@ -44,7 +44,6 @@ async function writeDiffOverlay(storage, path, result, passed) {
|
|
|
44
44
|
await storage.write(path, result.diffImage);
|
|
45
45
|
return path;
|
|
46
46
|
}
|
|
47
|
-
//#endregion
|
|
48
47
|
export { diffStoredScreenshots, resolvePixelThreshold, writeDiffOverlay };
|
|
49
48
|
|
|
50
49
|
//# sourceMappingURL=diff-record.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
3
|
import { Logger } from "../logger.mjs";
|
|
4
|
+
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
5
5
|
import { BuildTables } from "../models/build.mjs";
|
|
6
6
|
import { CaptureAttemptTables } from "../models/capture-attempt.mjs";
|
|
7
7
|
import { CaptureLogTables } from "../models/capture-log.mjs";
|
|
@@ -9,7 +9,6 @@ import { ProjectTables } from "../models/project.mjs";
|
|
|
9
9
|
import { JobLease } from "./job-lease.mjs";
|
|
10
10
|
import { CaptureJobOptions } from "./orchestrator.mjs";
|
|
11
11
|
import { BuildStatePublisher } from "./build-state/types.mjs";
|
|
12
|
-
//#region src/capture/dispatch.d.ts
|
|
13
12
|
/** Build the queue's job runner: post pending, apply skip rules, capture, report. */
|
|
14
13
|
declare function createDispatchJob(deps: DispatchDeps): (job: CaptureDispatchJob, lease?: JobLease) => Promise<void>;
|
|
15
14
|
/** Table handles required by dispatch. */
|
|
@@ -36,6 +35,5 @@ interface CaptureDispatchJob {
|
|
|
36
35
|
/** W3C `traceparent` continuing the enqueueing request's trace. */
|
|
37
36
|
traceparent?: string;
|
|
38
37
|
}
|
|
39
|
-
//#endregion
|
|
40
38
|
export { CaptureDispatchJob, DispatchDeps, DispatchTables, createDispatchJob };
|
|
41
39
|
//# sourceMappingURL=dispatch.d.mts.map
|
|
@@ -4,6 +4,7 @@ import.meta.url;
|
|
|
4
4
|
import { redactSecrets } from "../utils/redact.mjs";
|
|
5
5
|
import { CaptureAttemptModel, emitAttemptLog } from "../models/capture-attempt.mjs";
|
|
6
6
|
import { BuildModel } from "../models/build.mjs";
|
|
7
|
+
import { SignedUrlLifetimeError } from "./token-chunks.mjs";
|
|
7
8
|
import { CaptureShardModel } from "../models/capture-shard.mjs";
|
|
8
9
|
import { ProjectModel } from "../models/project.mjs";
|
|
9
10
|
import { executeCaptureJob } from "./orchestrator.mjs";
|
|
@@ -11,7 +12,7 @@ import { CaptureLogModel } from "../models/capture-log.mjs";
|
|
|
11
12
|
import { leaseProgress } from "./progress.mjs";
|
|
12
13
|
import { executeCaptureShard } from "./shards/execute.mjs";
|
|
13
14
|
import { hasApprovedBuildForSha } from "./skip-checks.mjs";
|
|
14
|
-
|
|
15
|
+
// src/capture/dispatch.ts
|
|
15
16
|
/** Build the queue's job runner: post pending, apply skip rules, capture, report. */
|
|
16
17
|
function createDispatchJob(deps) {
|
|
17
18
|
return async (job, lease) => {
|
|
@@ -119,11 +120,23 @@ async function runAndReport(ctx, job) {
|
|
|
119
120
|
progress: ctx.progress
|
|
120
121
|
}, deps.jobOptions));
|
|
121
122
|
} catch (error) {
|
|
122
|
-
await
|
|
123
|
-
await deps.buildState.request(build.id);
|
|
124
|
-
throw error;
|
|
123
|
+
await reportFailure(ctx, error);
|
|
125
124
|
}
|
|
126
125
|
}
|
|
126
|
+
/** Record a failed run, then rethrow so the job is redelivered, unless another try cannot help. */
|
|
127
|
+
async function reportFailure(ctx, error) {
|
|
128
|
+
const { deps, build } = ctx;
|
|
129
|
+
await finishAttempt(ctx, "failed", errorText(error));
|
|
130
|
+
await deps.buildState.request(build.id);
|
|
131
|
+
if (error instanceof SignedUrlLifetimeError) {
|
|
132
|
+
deps.logger.error({
|
|
133
|
+
buildId: build.id,
|
|
134
|
+
err: error
|
|
135
|
+
}, "capture not retried");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
127
140
|
/** Load the build + project for a job, running orphan jobs directly. */
|
|
128
141
|
async function loadJobTarget(deps, job) {
|
|
129
142
|
const build = await new BuildModel(deps.db, deps.tables).get(job.buildId);
|
|
@@ -180,7 +193,6 @@ async function loadClosing(deps, buildId) {
|
|
|
180
193
|
project
|
|
181
194
|
} : null;
|
|
182
195
|
}
|
|
183
|
-
//#endregion
|
|
184
196
|
export { createDispatchJob };
|
|
185
197
|
|
|
186
198
|
//# sourceMappingURL=dispatch.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.mjs","names":[],"sources":["../../src/capture/dispatch.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { Logger } from \"../logger.ts\";\nimport { BuildModel, type BuildTables } from \"../models/build.ts\";\nimport {\n CaptureAttemptModel,\n emitAttemptLog,\n type AttemptLogRecorder,\n type CaptureAttemptTables,\n} from \"../models/capture-attempt.ts\";\nimport { CaptureLogModel, type CaptureLogTables } from \"../models/capture-log.ts\";\nimport { CaptureShardModel } from \"../models/capture-shard.ts\";\nimport { ProjectModel, type ProjectTables } from \"../models/project.ts\";\nimport type { Build } from \"../schema/build.ts\";\nimport type { CaptureAttempt } from \"../schema/capture-attempt.ts\";\nimport type { Project } from \"../schema/project.ts\";\nimport { redactSecrets } from \"../utils/redact.ts\";\nimport type { BuildStatePublisher } from \"./build-state/types.ts\";\nimport type { JobLease } from \"./job-lease.ts\";\nimport { executeCaptureJob, type CaptureJobOptions, type CaptureSummary } from \"./orchestrator.ts\";\nimport { leaseProgress, type CaptureProgress } from \"./progress.ts\";\nimport { executeCaptureShard } from \"./shards/execute.ts\";\nimport type { FinalSummary } from \"./shards/reduce.ts\";\nimport { hasApprovedBuildForSha } from \"./skip-checks.ts\";\n\n/** Build the queue's job runner: post pending, apply skip rules, capture, report. */\nexport function createDispatchJob(\n deps: DispatchDeps,\n): (job: CaptureDispatchJob, lease?: JobLease) => Promise<void> {\n return async (job: CaptureDispatchJob, lease?: JobLease): Promise<void> => {\n await (job.shard\n ? runShardJob(deps, { ...job, shard: job.shard }, lease)\n : runBuildJob(deps, job, lease));\n };\n}\n\n/** The build's own job: post pending, apply skip rules, capture (or plan), report. */\nasync function runBuildJob(\n deps: DispatchDeps,\n job: CaptureDispatchJob,\n lease?: JobLease,\n): Promise<void> {\n const target = await loadJobTarget(deps, job);\n if (!target) {\n return;\n }\n await deps.buildState.request(job.buildId);\n const { attempt, recordLog } = await beginAttempt(\n deps,\n target.project,\n target.build,\n job.reqId,\n lease,\n );\n const ctx: JobContext = {\n deps,\n build: target.build,\n project: target.project,\n attempt,\n recordLog,\n progress: leaseProgress(lease),\n };\n if (await maybeSkipDuplicate(ctx)) {\n return;\n }\n await runAndReport(ctx, job);\n}\n\n/** Table handles required by dispatch. */\nexport type DispatchTables = BuildTables & ProjectTables & CaptureAttemptTables & CaptureLogTables;\n\n/** Dependencies for building the capture queue's job runner. */\nexport interface DispatchDeps {\n db: DatabaseAdapter;\n tables: DispatchTables;\n jobOptions: CaptureJobOptions;\n /** Shows a build's current state on its git channels; called at every transition. */\n buildState: BuildStatePublisher;\n logger: Logger;\n /** Redeliveries the queue allows a failing job; a shard's last try is its final word. */\n maxRetries?: number | undefined;\n}\n\n/** A queued capture job. */\nexport interface CaptureDispatchJob {\n buildId: string;\n /** A `capture_shards` row to render; absent for the build's own (plan or whole-build) job. */\n shard?: string | undefined;\n /** Times the queue has already delivered this job and seen it fail. */\n attempts?: number | undefined;\n reqId?: string;\n /** W3C `traceparent` continuing the enqueueing request's trace. */\n traceparent?: string;\n}\n\ninterface JobContext {\n deps: DispatchDeps;\n build: Build;\n project: Project;\n attempt: CaptureAttempt;\n recordLog: AttemptLogRecorder;\n progress: CaptureProgress | undefined;\n}\n\n/** Open a new attempt row for this run and return its log recorder. */\nasync function beginAttempt(\n deps: DispatchDeps,\n project: Project,\n build: Build,\n reqId: string | undefined,\n lease?: JobLease,\n): Promise<{ attempt: CaptureAttempt; recordLog: AttemptLogRecorder }> {\n const attempts = new CaptureAttemptModel(deps.db, deps.tables);\n const logs = new CaptureLogModel(deps.db, deps.tables);\n const attempt = await attempts.startAttempt(project.id, build.id, reqId);\n // Every attempt-log line (stages, render progress, runner output) counts as progress.\n const recordLog: AttemptLogRecorder = async (level, message, fields) => {\n lease?.touch();\n await logs.append(project.id, build.id, attempt.id, level, message, fields);\n };\n await emitAttemptLog(recordLog, deps.logger, \"info\", \"capture queued\", {\n buildId: build.id,\n attemptNo: attempt.attemptNo,\n });\n return { attempt, recordLog };\n}\n\n/** Close the attempt row with its terminal status, counts, and error. */\nasync function finishAttempt(\n ctx: JobContext,\n status: \"completed\" | \"failed\" | \"cancelled\",\n error?: string,\n counts?: { storyCount: number; failedCount: number },\n): Promise<void> {\n const { deps, attempt } = ctx;\n await new CaptureAttemptModel(deps.db, deps.tables).markFinished(\n attempt.id,\n status,\n error,\n counts,\n );\n await emitAttemptLog(\n ctx.recordLog,\n deps.logger,\n status === \"failed\" ? \"error\" : \"info\",\n `capture ${status}`,\n { attemptNo: attempt.attemptNo },\n );\n}\n\n/** Full error text for an attempt row (message plus stack when available). */\nfunction errorText(reason: unknown): string {\n // A runner's error can quote the signed Storybook URL it failed to open.\n return redactSecrets(reason instanceof Error ? (reason.stack ?? reason.message) : String(reason));\n}\n\nasync function approveWithoutCapture(ctx: JobContext, reason: string): Promise<void> {\n const { deps, build } = ctx;\n deps.logger.info({ buildId: build.id, sha: build.gitSha, branch: build.gitBranch }, reason);\n await emitAttemptLog(ctx.recordLog, deps.logger, \"info\", reason, {\n sha: build.gitSha,\n branch: build.gitBranch,\n });\n await finishAttempt(ctx, \"completed\");\n await new BuildModel(deps.db, deps.tables).setStatus(build.id, \"approved\").catch(() => {}); // Intentionally empty — fire-and-forget\n await deps.buildState.request(build.id);\n}\n\nasync function maybeSkipDuplicate(ctx: JobContext): Promise<boolean> {\n const { deps, build, project } = ctx;\n const dup = await hasApprovedBuildForSha(\n deps.db,\n deps.tables,\n project.id,\n build.gitSha,\n build.id,\n );\n if (dup) {\n await approveWithoutCapture(ctx, \"skipping capture — duplicate sha already approved\");\n return true;\n }\n return false;\n}\n\n/** A sharded build's attempt stays open: the worker that finishes the last shard closes it. */\nasync function finishUnlessSharded(ctx: JobContext, summary: CaptureSummary): Promise<void> {\n if (summary.shards) {\n await emitAttemptLog(ctx.recordLog, ctx.deps.logger, \"info\", \"capture sharded\", {\n shards: summary.shards,\n });\n return;\n }\n await finishAttempt(ctx, \"completed\", undefined, summary);\n await ctx.deps.buildState.request(ctx.build.id);\n}\n\nasync function runAndReport(ctx: JobContext, job: CaptureDispatchJob): Promise<void> {\n const { deps, build } = ctx;\n await new CaptureAttemptModel(deps.db, deps.tables).markRunning(ctx.attempt.id);\n await emitAttemptLog(ctx.recordLog, deps.logger, \"info\", \"capture started\", {\n buildId: build.id,\n attemptNo: ctx.attempt.attemptNo,\n });\n try {\n const summary = await executeCaptureJob(\n {\n buildId: job.buildId,\n reqId: job.reqId,\n traceparent: job.traceparent,\n attempt: {\n id: ctx.attempt.id,\n attemptNo: ctx.attempt.attemptNo,\n projectId: ctx.project.id,\n },\n recordLog: ctx.recordLog,\n progress: ctx.progress,\n },\n deps.jobOptions,\n );\n await finishUnlessSharded(ctx, summary);\n } catch (error: unknown) {\n await finishAttempt(ctx, \"failed\", errorText(error));\n await deps.buildState.request(build.id);\n throw error;\n }\n}\n\n/** Load the build + project for a job, running orphan jobs directly. */\nasync function loadJobTarget(\n deps: DispatchDeps,\n job: CaptureDispatchJob,\n): Promise<{ build: Build; project: Project } | null> {\n const build = await new BuildModel(deps.db, deps.tables).get(job.buildId);\n const project = build ? await new ProjectModel(deps.db, deps.tables).get(build.projectId) : null;\n if (!build || !project) {\n await executeCaptureJob(\n { buildId: job.buildId, reqId: job.reqId, traceparent: job.traceparent },\n deps.jobOptions,\n );\n return null;\n }\n return { build, project };\n}\n\n/**\n * Run one render shard. Only the run that finalized the build closes the plan's attempt and posts\n * the terminal status, whether its shard succeeded or failed; every other run leaves them alone.\n */\nasync function runShardJob(\n deps: DispatchDeps,\n job: CaptureDispatchJob & { shard: string },\n lease?: JobLease,\n): Promise<void> {\n const final = (job.attempts ?? 0) >= (deps.maxRetries ?? 0);\n await executeCaptureShard(\n {\n buildId: job.buildId,\n shard: job.shard,\n reqId: job.reqId,\n final,\n progress: leaseProgress(lease),\n onFinalized: async (summary, error) => {\n await closeShardedBuild(deps, job.buildId, summary, error);\n },\n },\n deps.jobOptions,\n );\n}\n\n/** End the plan's attempt with the finalizer's counts and report the build's terminal status. */\nasync function closeShardedBuild(\n deps: DispatchDeps,\n buildId: string,\n summary: FinalSummary,\n error?: unknown,\n): Promise<void> {\n const loaded = await loadClosing(deps, buildId);\n if (!loaded) {\n return;\n }\n const failure = error === undefined ? summary.error : errorText(error);\n const failed = failure !== undefined || summary.buildStatus === \"failed\";\n const attemptId = summary.attemptId ?? (await planAttemptId(deps, buildId));\n if (attemptId) {\n await new CaptureAttemptModel(deps.db, deps.tables)\n .markFinished(attemptId, failed ? \"failed\" : \"completed\", failure, summary)\n .catch((closeError: unknown) => {\n deps.logger.error({ err: closeError }, \"failed to close attempt\");\n });\n }\n await deps.buildState.request(buildId);\n}\n\nasync function planAttemptId(deps: DispatchDeps, buildId: string): Promise<string | null> {\n const plan = await new CaptureShardModel(deps.db).plan(buildId);\n return plan?.attemptId ?? null;\n}\n\nasync function loadClosing(\n deps: DispatchDeps,\n buildId: string,\n): Promise<{ build: Build; project: Project } | null> {\n const build = await new BuildModel(deps.db, deps.tables).get(buildId);\n const project = build ? await new ProjectModel(deps.db, deps.tables).get(build.projectId) : null;\n return build && project ? { build, project } : null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dispatch.mjs","names":[],"sources":["../../src/capture/dispatch.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { Logger } from \"../logger.ts\";\nimport { BuildModel, type BuildTables } from \"../models/build.ts\";\nimport {\n CaptureAttemptModel,\n emitAttemptLog,\n type AttemptLogRecorder,\n type CaptureAttemptTables,\n} from \"../models/capture-attempt.ts\";\nimport { CaptureLogModel, type CaptureLogTables } from \"../models/capture-log.ts\";\nimport { CaptureShardModel } from \"../models/capture-shard.ts\";\nimport { ProjectModel, type ProjectTables } from \"../models/project.ts\";\nimport type { Build } from \"../schema/build.ts\";\nimport type { CaptureAttempt } from \"../schema/capture-attempt.ts\";\nimport type { Project } from \"../schema/project.ts\";\nimport { redactSecrets } from \"../utils/redact.ts\";\nimport type { BuildStatePublisher } from \"./build-state/types.ts\";\nimport type { JobLease } from \"./job-lease.ts\";\nimport { executeCaptureJob, type CaptureJobOptions, type CaptureSummary } from \"./orchestrator.ts\";\nimport { leaseProgress, type CaptureProgress } from \"./progress.ts\";\nimport { executeCaptureShard } from \"./shards/execute.ts\";\nimport type { FinalSummary } from \"./shards/reduce.ts\";\nimport { hasApprovedBuildForSha } from \"./skip-checks.ts\";\nimport { SignedUrlLifetimeError } from \"./token-chunks.ts\";\n\n/** Build the queue's job runner: post pending, apply skip rules, capture, report. */\nexport function createDispatchJob(\n deps: DispatchDeps,\n): (job: CaptureDispatchJob, lease?: JobLease) => Promise<void> {\n return async (job: CaptureDispatchJob, lease?: JobLease): Promise<void> => {\n await (job.shard\n ? runShardJob(deps, { ...job, shard: job.shard }, lease)\n : runBuildJob(deps, job, lease));\n };\n}\n\n/** The build's own job: post pending, apply skip rules, capture (or plan), report. */\nasync function runBuildJob(\n deps: DispatchDeps,\n job: CaptureDispatchJob,\n lease?: JobLease,\n): Promise<void> {\n const target = await loadJobTarget(deps, job);\n if (!target) {\n return;\n }\n await deps.buildState.request(job.buildId);\n const { attempt, recordLog } = await beginAttempt(\n deps,\n target.project,\n target.build,\n job.reqId,\n lease,\n );\n const ctx: JobContext = {\n deps,\n build: target.build,\n project: target.project,\n attempt,\n recordLog,\n progress: leaseProgress(lease),\n };\n if (await maybeSkipDuplicate(ctx)) {\n return;\n }\n await runAndReport(ctx, job);\n}\n\n/** Table handles required by dispatch. */\nexport type DispatchTables = BuildTables & ProjectTables & CaptureAttemptTables & CaptureLogTables;\n\n/** Dependencies for building the capture queue's job runner. */\nexport interface DispatchDeps {\n db: DatabaseAdapter;\n tables: DispatchTables;\n jobOptions: CaptureJobOptions;\n /** Shows a build's current state on its git channels; called at every transition. */\n buildState: BuildStatePublisher;\n logger: Logger;\n /** Redeliveries the queue allows a failing job; a shard's last try is its final word. */\n maxRetries?: number | undefined;\n}\n\n/** A queued capture job. */\nexport interface CaptureDispatchJob {\n buildId: string;\n /** A `capture_shards` row to render; absent for the build's own (plan or whole-build) job. */\n shard?: string | undefined;\n /** Times the queue has already delivered this job and seen it fail. */\n attempts?: number | undefined;\n reqId?: string;\n /** W3C `traceparent` continuing the enqueueing request's trace. */\n traceparent?: string;\n}\n\ninterface JobContext {\n deps: DispatchDeps;\n build: Build;\n project: Project;\n attempt: CaptureAttempt;\n recordLog: AttemptLogRecorder;\n progress: CaptureProgress | undefined;\n}\n\n/** Open a new attempt row for this run and return its log recorder. */\nasync function beginAttempt(\n deps: DispatchDeps,\n project: Project,\n build: Build,\n reqId: string | undefined,\n lease?: JobLease,\n): Promise<{ attempt: CaptureAttempt; recordLog: AttemptLogRecorder }> {\n const attempts = new CaptureAttemptModel(deps.db, deps.tables);\n const logs = new CaptureLogModel(deps.db, deps.tables);\n const attempt = await attempts.startAttempt(project.id, build.id, reqId);\n // Every attempt-log line (stages, render progress, runner output) counts as progress.\n const recordLog: AttemptLogRecorder = async (level, message, fields) => {\n lease?.touch();\n await logs.append(project.id, build.id, attempt.id, level, message, fields);\n };\n await emitAttemptLog(recordLog, deps.logger, \"info\", \"capture queued\", {\n buildId: build.id,\n attemptNo: attempt.attemptNo,\n });\n return { attempt, recordLog };\n}\n\n/** Close the attempt row with its terminal status, counts, and error. */\nasync function finishAttempt(\n ctx: JobContext,\n status: \"completed\" | \"failed\" | \"cancelled\",\n error?: string,\n counts?: { storyCount: number; failedCount: number },\n): Promise<void> {\n const { deps, attempt } = ctx;\n await new CaptureAttemptModel(deps.db, deps.tables).markFinished(\n attempt.id,\n status,\n error,\n counts,\n );\n await emitAttemptLog(\n ctx.recordLog,\n deps.logger,\n status === \"failed\" ? \"error\" : \"info\",\n `capture ${status}`,\n { attemptNo: attempt.attemptNo },\n );\n}\n\n/** Full error text for an attempt row (message plus stack when available). */\nfunction errorText(reason: unknown): string {\n // A runner's error can quote the signed Storybook URL it failed to open.\n return redactSecrets(reason instanceof Error ? (reason.stack ?? reason.message) : String(reason));\n}\n\nasync function approveWithoutCapture(ctx: JobContext, reason: string): Promise<void> {\n const { deps, build } = ctx;\n deps.logger.info({ buildId: build.id, sha: build.gitSha, branch: build.gitBranch }, reason);\n await emitAttemptLog(ctx.recordLog, deps.logger, \"info\", reason, {\n sha: build.gitSha,\n branch: build.gitBranch,\n });\n await finishAttempt(ctx, \"completed\");\n await new BuildModel(deps.db, deps.tables).setStatus(build.id, \"approved\").catch(() => {}); // Intentionally empty — fire-and-forget\n await deps.buildState.request(build.id);\n}\n\nasync function maybeSkipDuplicate(ctx: JobContext): Promise<boolean> {\n const { deps, build, project } = ctx;\n const dup = await hasApprovedBuildForSha(\n deps.db,\n deps.tables,\n project.id,\n build.gitSha,\n build.id,\n );\n if (dup) {\n await approveWithoutCapture(ctx, \"skipping capture — duplicate sha already approved\");\n return true;\n }\n return false;\n}\n\n/** A sharded build's attempt stays open: the worker that finishes the last shard closes it. */\nasync function finishUnlessSharded(ctx: JobContext, summary: CaptureSummary): Promise<void> {\n if (summary.shards) {\n await emitAttemptLog(ctx.recordLog, ctx.deps.logger, \"info\", \"capture sharded\", {\n shards: summary.shards,\n });\n return;\n }\n await finishAttempt(ctx, \"completed\", undefined, summary);\n await ctx.deps.buildState.request(ctx.build.id);\n}\n\nasync function runAndReport(ctx: JobContext, job: CaptureDispatchJob): Promise<void> {\n const { deps, build } = ctx;\n await new CaptureAttemptModel(deps.db, deps.tables).markRunning(ctx.attempt.id);\n await emitAttemptLog(ctx.recordLog, deps.logger, \"info\", \"capture started\", {\n buildId: build.id,\n attemptNo: ctx.attempt.attemptNo,\n });\n try {\n const summary = await executeCaptureJob(\n {\n buildId: job.buildId,\n reqId: job.reqId,\n traceparent: job.traceparent,\n attempt: {\n id: ctx.attempt.id,\n attemptNo: ctx.attempt.attemptNo,\n projectId: ctx.project.id,\n },\n recordLog: ctx.recordLog,\n progress: ctx.progress,\n },\n deps.jobOptions,\n );\n await finishUnlessSharded(ctx, summary);\n } catch (error: unknown) {\n await reportFailure(ctx, error);\n }\n}\n\n/** Record a failed run, then rethrow so the job is redelivered, unless another try cannot help. */\nasync function reportFailure(ctx: JobContext, error: unknown): Promise<void> {\n const { deps, build } = ctx;\n await finishAttempt(ctx, \"failed\", errorText(error));\n await deps.buildState.request(build.id);\n if (error instanceof SignedUrlLifetimeError) {\n // A configuration problem: another delivery would fail the same way. The build is failed.\n deps.logger.error({ buildId: build.id, err: error }, \"capture not retried\");\n return;\n }\n throw error;\n}\n\n/** Load the build + project for a job, running orphan jobs directly. */\nasync function loadJobTarget(\n deps: DispatchDeps,\n job: CaptureDispatchJob,\n): Promise<{ build: Build; project: Project } | null> {\n const build = await new BuildModel(deps.db, deps.tables).get(job.buildId);\n const project = build ? await new ProjectModel(deps.db, deps.tables).get(build.projectId) : null;\n if (!build || !project) {\n await executeCaptureJob(\n { buildId: job.buildId, reqId: job.reqId, traceparent: job.traceparent },\n deps.jobOptions,\n );\n return null;\n }\n return { build, project };\n}\n\n/**\n * Run one render shard. Only the run that finalized the build closes the plan's attempt and posts\n * the terminal status, whether its shard succeeded or failed; every other run leaves them alone.\n */\nasync function runShardJob(\n deps: DispatchDeps,\n job: CaptureDispatchJob & { shard: string },\n lease?: JobLease,\n): Promise<void> {\n const final = (job.attempts ?? 0) >= (deps.maxRetries ?? 0);\n await executeCaptureShard(\n {\n buildId: job.buildId,\n shard: job.shard,\n reqId: job.reqId,\n final,\n progress: leaseProgress(lease),\n onFinalized: async (summary, error) => {\n await closeShardedBuild(deps, job.buildId, summary, error);\n },\n },\n deps.jobOptions,\n );\n}\n\n/** End the plan's attempt with the finalizer's counts and report the build's terminal status. */\nasync function closeShardedBuild(\n deps: DispatchDeps,\n buildId: string,\n summary: FinalSummary,\n error?: unknown,\n): Promise<void> {\n const loaded = await loadClosing(deps, buildId);\n if (!loaded) {\n return;\n }\n const failure = error === undefined ? summary.error : errorText(error);\n const failed = failure !== undefined || summary.buildStatus === \"failed\";\n const attemptId = summary.attemptId ?? (await planAttemptId(deps, buildId));\n if (attemptId) {\n await new CaptureAttemptModel(deps.db, deps.tables)\n .markFinished(attemptId, failed ? \"failed\" : \"completed\", failure, summary)\n .catch((closeError: unknown) => {\n deps.logger.error({ err: closeError }, \"failed to close attempt\");\n });\n }\n await deps.buildState.request(buildId);\n}\n\nasync function planAttemptId(deps: DispatchDeps, buildId: string): Promise<string | null> {\n const plan = await new CaptureShardModel(deps.db).plan(buildId);\n return plan?.attemptId ?? null;\n}\n\nasync function loadClosing(\n deps: DispatchDeps,\n buildId: string,\n): Promise<{ build: Build; project: Project } | null> {\n const build = await new BuildModel(deps.db, deps.tables).get(buildId);\n const project = build ? await new ProjectModel(deps.db, deps.tables).get(build.projectId) : null;\n return build && project ? { build, project } : null;\n}\n"],"mappings":"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"}
|
package/dist/capture/enrich.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import.meta.url;
|
|
|
4
4
|
import { filterModes } from "./modes.mjs";
|
|
5
5
|
import { renderBudgetMs } from "./render.mjs";
|
|
6
6
|
import { resolveStoryViewports } from "./storybook.mjs";
|
|
7
|
-
|
|
7
|
+
// src/capture/enrich.ts
|
|
8
8
|
/**
|
|
9
9
|
* Merge runtime-resolved parameters (project/component/story levels stacked by
|
|
10
10
|
* Storybook) over the index's, then apply the project's mode allowlist. A
|
|
@@ -54,7 +54,6 @@ async function extractSafely(input) {
|
|
|
54
54
|
return {};
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
//#endregion
|
|
58
57
|
export { assertModeCaps, enrichStories };
|
|
59
58
|
|
|
60
59
|
//# sourceMappingURL=enrich.mjs.map
|
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { isFlakyStory } from "./adapter.mjs";
|
|
5
|
-
|
|
5
|
+
// src/capture/failure-sets.ts
|
|
6
6
|
/** Classify render failures: `a11y:` errors, then flaky stories, then everything else is blocking. */
|
|
7
7
|
function classifyFailures(stories, failures) {
|
|
8
8
|
const flakyIds = new Set(stories.filter((story) => isFlakyStory(story)).map((story) => story.id));
|
|
@@ -16,7 +16,6 @@ function classifyFailures(stories, failures) {
|
|
|
16
16
|
else sets.blocking.add(failure.storyId);
|
|
17
17
|
return sets;
|
|
18
18
|
}
|
|
19
|
-
//#endregion
|
|
20
19
|
export { classifyFailures };
|
|
21
20
|
|
|
22
21
|
//# sourceMappingURL=failure-sets.mjs.map
|
|
@@ -3,7 +3,6 @@ import __tsdown_shims_url from 'node:url';
|
|
|
3
3
|
import { Viewport } from "./adapter.mjs";
|
|
4
4
|
import { CaptureEnvironment } from "../adapter/capture-runner.mjs";
|
|
5
5
|
import { SIZING_DEFAULTS } from "./sizing.mjs";
|
|
6
|
-
//#region src/capture/fingerprint.d.ts
|
|
7
6
|
/** The components behind a snapshot's `infraHash`, kept so a mismatch can say what changed. */
|
|
8
7
|
interface Fingerprint {
|
|
9
8
|
engine: string;
|
|
@@ -37,6 +36,5 @@ interface EnvironmentChange {
|
|
|
37
36
|
from: Fingerprint | null;
|
|
38
37
|
to: Fingerprint;
|
|
39
38
|
}
|
|
40
|
-
//#endregion
|
|
41
39
|
export { EnvironmentChange, Fingerprint, buildFingerprint, changedFields, fingerprintHash, parseFingerprint };
|
|
42
40
|
//# sourceMappingURL=fingerprint.d.mts.map
|
|
@@ -3,7 +3,7 @@ import "node:url";
|
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { sha256 } from "../utils/hash.mjs";
|
|
5
5
|
import { SIZING_DEFAULTS } from "./sizing.mjs";
|
|
6
|
-
|
|
6
|
+
// src/capture/fingerprint.ts
|
|
7
7
|
/** Build the fingerprint of one capture. Missing environment fields stay `null` (runner did not report them). */
|
|
8
8
|
function buildFingerprint(engine, viewport, environment) {
|
|
9
9
|
return {
|
|
@@ -77,7 +77,6 @@ function parseFingerprint(raw) {
|
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
//#endregion
|
|
81
80
|
export { buildFingerprint, changedFields, fingerprintHash, mergeFingerprint, parseFingerprint };
|
|
82
81
|
|
|
83
82
|
//# sourceMappingURL=fingerprint.mjs.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { ChildMessage, ParentMessage } from "./protocol.mjs";
|
|
4
|
-
//#region src/capture/forked/channel.d.ts
|
|
5
4
|
/** How the parent sees the capture child (`child_process.fork` adapts to this). */
|
|
6
5
|
interface ChildProcessHandle {
|
|
7
6
|
send(message: ParentMessage): void;
|
|
@@ -20,6 +19,5 @@ interface ParentPort {
|
|
|
20
19
|
onMessage(listener: (message: unknown) => void): void;
|
|
21
20
|
onDisconnect(listener: () => void): void;
|
|
22
21
|
}
|
|
23
|
-
//#endregion
|
|
24
22
|
export { ChildProcessHandle, ParentPort };
|
|
25
23
|
//# sourceMappingURL=channel.d.mts.map
|
|
@@ -4,7 +4,6 @@ import { Logger } from "../../logger.mjs";
|
|
|
4
4
|
import { CaptureHandlerOptions } from "../consumer/capture-handler.mjs";
|
|
5
5
|
import { CaptureConsumerOptions } from "../consumer/types.mjs";
|
|
6
6
|
import { ChildMessage } from "./protocol.mjs";
|
|
7
|
-
//#region src/capture/forked/child.d.ts
|
|
8
7
|
/** Handler options minus the shard hand-out, which the child wires to the database queue. */
|
|
9
8
|
type CaptureChildOptions = Omit<CaptureHandlerOptions, "enqueue" | "logger"> & Pick<CaptureConsumerOptions, "images" | "compare"> & {
|
|
10
9
|
logger?: Logger;
|
|
@@ -29,6 +28,5 @@ interface ChildHost {
|
|
|
29
28
|
* @throws When not running as a forked child (no IPC channel), or when the image engine cannot load.
|
|
30
29
|
*/
|
|
31
30
|
declare function runCaptureChild(options: CaptureChildOptions, host?: ChildHost): Promise<void>;
|
|
32
|
-
//#endregion
|
|
33
31
|
export { CaptureChildOptions, ChildHost, runCaptureChild };
|
|
34
32
|
//# sourceMappingURL=child.d.mts.map
|
|
@@ -10,7 +10,7 @@ import { createCaptureHandler, originOf } from "../consumer/capture-handler.mjs"
|
|
|
10
10
|
import { applyImageSettings, ensureImageEngine } from "../consumer/startup.mjs";
|
|
11
11
|
import "./fork.mjs";
|
|
12
12
|
import { isParentMessage } from "./protocol.mjs";
|
|
13
|
-
|
|
13
|
+
// src/capture/forked/child.ts
|
|
14
14
|
/**
|
|
15
15
|
* Entry helper for a forked capture child (`testing.workerEntry`). The app is the consumer: it
|
|
16
16
|
* polls the database queue, holds the slots and the lease, and pushes each leased job here over
|
|
@@ -196,7 +196,6 @@ function processHost() {
|
|
|
196
196
|
exit: (code) => process.exit(code)
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
|
-
//#endregion
|
|
200
199
|
export { runCaptureChild };
|
|
201
200
|
|
|
202
201
|
//# sourceMappingURL=child.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/crash-tracker.ts
|
|
5
5
|
/** Counts child crashes inside a sliding window, to tell a flaky child from a crash loop. */
|
|
6
6
|
var CrashTracker = class {
|
|
7
7
|
#limit;
|
|
@@ -17,7 +17,6 @@ var CrashTracker = class {
|
|
|
17
17
|
return this.#times.length >= this.#limit;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
-
//#endregion
|
|
21
20
|
export { CrashTracker };
|
|
22
21
|
|
|
23
22
|
//# sourceMappingURL=crash-tracker.mjs.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/capture/forked/decision.d.ts
|
|
4
3
|
/** Whether a capture child is worth forking on this host (ADR 0005 phase 3 fallback rules). */
|
|
5
4
|
/** What the decision looks at. */
|
|
6
5
|
interface ForkHost {
|
|
@@ -21,6 +20,5 @@ declare const FORK_MIN_CPUS = 2;
|
|
|
21
20
|
declare const FORK_MIN_MEMORY_BYTES: number;
|
|
22
21
|
/** Pick the capture process model for a host. */
|
|
23
22
|
declare function decideCaptureProcess(host: ForkHost): ForkDecision;
|
|
24
|
-
//#endregion
|
|
25
23
|
export { FORK_MIN_CPUS, FORK_MIN_MEMORY_BYTES, ForkDecision, ForkHost, decideCaptureProcess };
|
|
26
24
|
//# sourceMappingURL=decision.d.mts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/decision.ts
|
|
5
5
|
/** Smallest host that still gains from a second process: below this the child only costs memory. */
|
|
6
6
|
const FORK_MIN_CPUS = 2;
|
|
7
7
|
const FORK_MIN_MEMORY_BYTES = 2 * 1024 ** 3;
|
|
@@ -21,7 +21,6 @@ function decideCaptureProcess(host) {
|
|
|
21
21
|
};
|
|
22
22
|
return { mode: "fork" };
|
|
23
23
|
}
|
|
24
|
-
//#endregion
|
|
25
24
|
export { FORK_MIN_CPUS, FORK_MIN_MEMORY_BYTES, decideCaptureProcess };
|
|
26
25
|
|
|
27
26
|
//# sourceMappingURL=decision.mjs.map
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/exit.ts
|
|
5
5
|
/** `signal SIGKILL` or `code 1`. */
|
|
6
6
|
function describeExit(info) {
|
|
7
7
|
return info.signal ? `signal ${info.signal}` : `code ${info.code}`;
|
|
8
8
|
}
|
|
9
|
-
//#endregion
|
|
10
9
|
export { describeExit };
|
|
11
10
|
|
|
12
11
|
//# sourceMappingURL=exit.mjs.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { ChildProcessHandle } from "./channel.mjs";
|
|
4
|
-
//#region src/capture/forked/fork.d.ts
|
|
5
4
|
/** Environment variable the forked child sees; set to this value so a module can tell it is the child. */
|
|
6
5
|
declare const CAPTURE_WORKER_ROLE = "capture-worker";
|
|
7
6
|
/** Environment variable carrying the parent's `testing.retries` to the child, which stamps it on the shard jobs it queues. */
|
|
@@ -26,6 +25,5 @@ interface ForkOptions {
|
|
|
26
25
|
* @throws When the runtime cannot fork, or the fork itself throws.
|
|
27
26
|
*/
|
|
28
27
|
declare function forkCaptureChild(options: ForkOptions): ChildProcessHandle;
|
|
29
|
-
//#endregion
|
|
30
28
|
export { CAPTURE_RETRIES_ENV, CAPTURE_SHARD_SIZE_ENV, CAPTURE_WORKER_ROLE, ForkOptions, canForkCaptureChild, forkCaptureChild };
|
|
31
29
|
//# sourceMappingURL=fork.d.mts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/fork.ts
|
|
5
5
|
/** Environment variable the forked child sees; set to this value so a module can tell it is the child. */
|
|
6
6
|
const CAPTURE_WORKER_ROLE = "capture-worker";
|
|
7
7
|
/** Environment variable carrying the parent's `testing.retries` to the child, which stamps it on the shard jobs it queues. */
|
|
@@ -87,7 +87,6 @@ function wrap(child, stopOnExit) {
|
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
-
//#endregion
|
|
91
90
|
export { CAPTURE_RETRIES_ENV, CAPTURE_SHARD_SIZE_ENV, CAPTURE_WORKER_ROLE, canForkCaptureChild, forkCaptureChild };
|
|
92
91
|
|
|
93
92
|
//# sourceMappingURL=fork.mjs.map
|
|
@@ -3,7 +3,6 @@ import __tsdown_shims_url from 'node:url';
|
|
|
3
3
|
import { Logger } from "../../logger.mjs";
|
|
4
4
|
import { ConsumerJob, KindHandler } from "../consumer/types.mjs";
|
|
5
5
|
import { ChildProcessHandle } from "./channel.mjs";
|
|
6
|
-
//#region src/capture/forked/forked-capture.d.ts
|
|
7
6
|
/** Options of {@link createForkedCaptureHandler}. */
|
|
8
7
|
interface ForkedCaptureOptions {
|
|
9
8
|
/** Start the capture child. Throwing counts as "fork failed" and trips the fallback. */
|
|
@@ -35,6 +34,5 @@ interface ForkedCaptureHandler extends KindHandler {
|
|
|
35
34
|
}
|
|
36
35
|
/** Create the handler; the child is forked when the first job arrives. */
|
|
37
36
|
declare function createForkedCaptureHandler(options: ForkedCaptureOptions): ForkedCaptureHandler;
|
|
38
|
-
//#endregion
|
|
39
37
|
export { ForkedCaptureHandler, ForkedCaptureOptions, createForkedCaptureHandler };
|
|
40
38
|
//# sourceMappingURL=forked-capture.d.mts.map
|
|
@@ -8,7 +8,7 @@ import { CrashTracker } from "./crash-tracker.mjs";
|
|
|
8
8
|
import { describeExit } from "./exit.mjs";
|
|
9
9
|
import { LeaseBook } from "./lease-book.mjs";
|
|
10
10
|
import { RunBook, jobKey } from "./runs.mjs";
|
|
11
|
-
|
|
11
|
+
// src/capture/forked/forked-capture.ts
|
|
12
12
|
/** Create the handler; the child is forked when the first job arrives. */
|
|
13
13
|
function createForkedCaptureHandler(options) {
|
|
14
14
|
const forked = new ForkedCapture(options);
|
|
@@ -234,7 +234,6 @@ async function delay(ms) {
|
|
|
234
234
|
setTimeout(resolve, ms).unref();
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
|
-
//#endregion
|
|
238
237
|
export { createForkedCaptureHandler };
|
|
239
238
|
|
|
240
239
|
//# sourceMappingURL=forked-capture.mjs.map
|
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { ProgressLease } from "../job-lease.mjs";
|
|
5
|
-
|
|
5
|
+
// src/capture/forked/lease-book.ts
|
|
6
6
|
/** Progress leases for jobs out with the capture child: no progress within the lease means the child is hung. */
|
|
7
7
|
/** One {@link ProgressLease} per in-flight receipt. A `leaseMs` of 0 disables the whole book. */
|
|
8
8
|
var LeaseBook = class {
|
|
@@ -40,7 +40,6 @@ var LeaseBook = class {
|
|
|
40
40
|
this.#leases.clear();
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
-
//#endregion
|
|
44
43
|
export { LeaseBook };
|
|
45
44
|
|
|
46
45
|
//# sourceMappingURL=lease-book.mjs.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { ConsumerJob } from "../consumer/types.mjs";
|
|
4
|
-
//#region src/capture/forked/protocol.d.ts
|
|
5
4
|
/** Parent to child. `runId` names one push of a job; a re-push after a crash gets a new one. */
|
|
6
5
|
type ParentMessage =
|
|
7
6
|
/** Run this leased job. The child holds the same database, storage and runner configuration. */
|
|
@@ -33,6 +32,5 @@ type ChildMessage =
|
|
|
33
32
|
runId: string;
|
|
34
33
|
error: string;
|
|
35
34
|
};
|
|
36
|
-
//#endregion
|
|
37
35
|
export { ChildMessage, ParentMessage };
|
|
38
36
|
//# sourceMappingURL=protocol.d.mts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/protocol.ts
|
|
5
5
|
function isRecord(value) {
|
|
6
6
|
return typeof value === "object" && value !== null;
|
|
7
7
|
}
|
|
@@ -19,7 +19,6 @@ function isParentMessage(value) {
|
|
|
19
19
|
if (!isRecord(value) || typeof value["runId"] !== "string") return false;
|
|
20
20
|
return value["type"] === "cancel" || value["type"] === "run" && isJob(value["job"]);
|
|
21
21
|
}
|
|
22
|
-
//#endregion
|
|
23
22
|
export { isChildMessage, isParentMessage };
|
|
24
23
|
|
|
25
24
|
//# sourceMappingURL=protocol.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/forked/runs.ts
|
|
5
5
|
/** In-flight runs by id, plus the admission rule for solo runs and a signal for waiters. */
|
|
6
6
|
var RunBook = class {
|
|
7
7
|
#runs = /* @__PURE__ */ new Map();
|
|
@@ -69,7 +69,6 @@ var RunBook = class {
|
|
|
69
69
|
function jobKey(job) {
|
|
70
70
|
return job.receipt ?? `${job.buildId}:${job.shard ?? ""}`;
|
|
71
71
|
}
|
|
72
|
-
//#endregion
|
|
73
72
|
export { RunBook, jobKey };
|
|
74
73
|
|
|
75
74
|
//# sourceMappingURL=runs.mjs.map
|
package/dist/capture/guards.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/capture/guards.ts
|
|
5
5
|
/**
|
|
6
6
|
* Capture output guards: a third-party runner returning garbage (or
|
|
7
7
|
* gigabytes) must fail here, before bytes reach storage or baselines.
|
|
@@ -25,7 +25,6 @@ function assertScreenshotBuffer(buffer) {
|
|
|
25
25
|
if (buffer.length > 26214400) throw new Error(`Screenshot exceeds ${MAX_SCREENSHOT_BYTES} bytes`);
|
|
26
26
|
if (!PNG_MAGIC.every((byte, index) => buffer[index] === byte)) throw new Error("Screenshot is not a PNG");
|
|
27
27
|
}
|
|
28
|
-
//#endregion
|
|
29
28
|
export { MAX_SCREENSHOT_BYTES, assertScreenshotBuffer };
|
|
30
29
|
|
|
31
30
|
//# sourceMappingURL=guards.mjs.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* Ignore regions: elements a story marks as dynamic (timestamps, avatars, ads) are hidden before
|
|
5
|
+
* the screenshot so they never produce a diff. Both runners inject the stylesheet built here, so
|
|
6
|
+
* the mask is identical across engines. Baseline keys and diff math are untouched.
|
|
7
|
+
*/
|
|
8
|
+
/** Most selectors one story may declare; the rest are dropped. */
|
|
9
|
+
declare const MAX_IGNORE_SELECTORS = 50;
|
|
10
|
+
/** Selectors that always apply: StoryShelf's attribute, then the Chromatic migration spellings. */
|
|
11
|
+
declare const DEFAULT_IGNORE_SELECTORS: readonly string[];
|
|
12
|
+
/** Whether `selector` is non-empty text that cannot break out of a single CSS rule. */
|
|
13
|
+
declare function isSafeIgnoreSelector(selector: unknown): selector is string;
|
|
14
|
+
/** The result of reading a story's `ignoreSelectors`. */
|
|
15
|
+
interface IgnoreSelectorList {
|
|
16
|
+
/** Trimmed, deduplicated, safe selectors, at most {@link MAX_IGNORE_SELECTORS}. */
|
|
17
|
+
selectors: string[];
|
|
18
|
+
/** Entries that were refused (not a string, empty, or unsafe) or cut by the cap. */
|
|
19
|
+
skipped: string[];
|
|
20
|
+
}
|
|
21
|
+
/** Clean the declared `ignoreSelectors` value; anything that is not an array yields no selectors. */
|
|
22
|
+
declare function cleanIgnoreSelectors(value: unknown): IgnoreSelectorList;
|
|
23
|
+
/**
|
|
24
|
+
* The string entries of a declared `ignoreSelectors` value, untouched, or `undefined` when there
|
|
25
|
+
* are none. Safety and the cap are applied later by {@link cleanIgnoreSelectors}, in the runner,
|
|
26
|
+
* so a refused selector can still be reported on the snapshot log.
|
|
27
|
+
*/
|
|
28
|
+
declare function declaredIgnoreSelectors(value: unknown): string[] | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The stylesheet that masks `selectors` plus {@link DEFAULT_IGNORE_SELECTORS}. One rule per
|
|
31
|
+
* selector, so a selector the browser rejects cannot take the others down with it. Unsafe selectors
|
|
32
|
+
* are dropped here as well.
|
|
33
|
+
*/
|
|
34
|
+
declare function ignoreStylesheet(selectors?: readonly string[]): string;
|
|
35
|
+
export { DEFAULT_IGNORE_SELECTORS, IgnoreSelectorList, MAX_IGNORE_SELECTORS, cleanIgnoreSelectors, declaredIgnoreSelectors, ignoreStylesheet, isSafeIgnoreSelector };
|
|
36
|
+
//# sourceMappingURL=ignore-regions.d.mts.map
|