@storyshelf/core 0.6.2 → 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/README.md +49 -32
- package/dist/adapter/capture-queue.d.mts +44 -4
- package/dist/adapter/capture-runner.d.mts +134 -12
- package/dist/adapter/capture-runner.mjs +9 -12
- package/dist/adapter/database.d.mts +89 -10
- package/dist/adapter/database.mjs +4 -3
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/design.d.mts +83 -0
- package/dist/adapter/design.mjs +27 -0
- package/dist/adapter/design.mjs.map +1 -0
- package/dist/adapter/email-sender.d.mts +0 -2
- package/dist/adapter/metadata.d.mts +3 -12
- package/dist/adapter/notifier.d.mts +6 -3
- package/dist/adapter/notifier.mjs +5 -1
- package/dist/adapter/oauth.d.mts +50 -0
- package/dist/adapter/setup.d.mts +4 -7
- package/dist/adapter/setup.mjs +3 -3
- package/dist/adapter/setup.mjs.map +1 -1
- package/dist/adapter/storage.d.mts +1 -3
- package/dist/adapter/webhook-events.d.mts +0 -2
- package/dist/adapter/webhook-events.mjs +13 -14
- package/dist/adapter/webhook-events.mjs.map +1 -1
- package/dist/adapters/capture-target-offers.d.mts +26 -0
- package/dist/adapters/capture-target-offers.mjs +57 -0
- package/dist/adapters/capture-target-offers.mjs.map +1 -0
- package/dist/adapters/capture-target.d.mts +69 -0
- package/dist/adapters/capture-target.mjs +75 -0
- package/dist/adapters/capture-target.mjs.map +1 -0
- package/dist/adapters/notifier/build-comment.d.mts +22 -0
- package/dist/adapters/notifier/build-comment.mjs +23 -0
- package/dist/adapters/notifier/build-comment.mjs.map +1 -0
- package/dist/adapters/notifier/build-state.d.mts +97 -0
- package/dist/adapters/notifier/build-state.mjs +217 -0
- package/dist/adapters/notifier/build-state.mjs.map +1 -0
- package/dist/adapters/notifier/events.d.mts +4 -4
- package/dist/adapters/notifier/events.mjs +32 -20
- package/dist/adapters/notifier/events.mjs.map +1 -1
- package/dist/adapters/notifier/format.d.mts +0 -2
- package/dist/adapters/notifier/format.mjs +1 -2
- package/dist/adapters/notifier/provider.d.mts +53 -9
- package/dist/adapters/notifier/provider.mjs +11 -0
- package/dist/adapters/notifier/provider.mjs.map +1 -0
- package/dist/adapters/notifier/state.d.mts +22 -0
- package/dist/adapters/notifier/state.mjs +65 -0
- package/dist/adapters/notifier/state.mjs.map +1 -0
- package/dist/adapters/notifier/types.d.mts +51 -4
- package/dist/adapters/remote-browser.d.mts +168 -0
- package/dist/adapters/remote-browser.mjs +201 -0
- package/dist/adapters/remote-browser.mjs.map +1 -0
- 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 +23 -0
- package/dist/adapters/render-runs.mjs +40 -0
- package/dist/adapters/render-runs.mjs.map +1 -0
- package/dist/adapters/setup-runner.d.mts +0 -2
- package/dist/adapters/setup-runner.mjs +3 -6
- package/dist/adapters/setup-runner.mjs.map +1 -1
- package/dist/adapters/sources.d.mts +10 -0
- package/dist/adapters/sources.mjs +19 -0
- package/dist/adapters/sources.mjs.map +1 -0
- package/dist/adapters/validate.d.mts +0 -2
- package/dist/adapters/validate.mjs +27 -20
- package/dist/adapters/validate.mjs.map +1 -1
- package/dist/ai.d.mts +103 -0
- package/dist/ai.mjs +18 -0
- package/dist/ai.mjs.map +1 -0
- 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 +16 -0
- package/dist/capture/a11y/axe-source.mjs +36 -0
- package/dist/capture/a11y/axe-source.mjs.map +1 -0
- package/dist/capture/a11y/in-page.d.mts +25 -0
- package/dist/capture/a11y/in-page.mjs +59 -0
- package/dist/capture/a11y/in-page.mjs.map +1 -0
- package/dist/capture/a11y/map.d.mts +22 -0
- package/dist/capture/a11y/map.mjs +47 -0
- package/dist/capture/a11y/map.mjs.map +1 -0
- package/dist/capture/a11y/options.d.mts +21 -0
- package/dist/capture/a11y/options.mjs +74 -0
- package/dist/capture/a11y/options.mjs.map +1 -0
- package/dist/capture/adapter.d.mts +46 -5
- package/dist/capture/adapter.mjs +1 -2
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +2 -2
- package/dist/capture/affected.mjs +14 -6
- package/dist/capture/affected.mjs.map +1 -1
- package/dist/capture/attempt-logger.mjs +83 -0
- package/dist/capture/attempt-logger.mjs.map +1 -0
- package/dist/capture/browsers.d.mts +33 -0
- package/dist/capture/browsers.mjs +66 -0
- package/dist/capture/browsers.mjs.map +1 -0
- package/dist/capture/build-state/deliver.d.mts +30 -0
- package/dist/capture/build-state/deliver.mjs +117 -0
- package/dist/capture/build-state/deliver.mjs.map +1 -0
- package/dist/capture/build-state/index.d.mts +8 -0
- package/dist/capture/build-state/notify-job.d.mts +54 -0
- package/dist/capture/build-state/notify-job.mjs +132 -0
- package/dist/capture/build-state/notify-job.mjs.map +1 -0
- package/dist/capture/build-state/publisher.d.mts +21 -0
- package/dist/capture/build-state/publisher.mjs +106 -0
- package/dist/capture/build-state/publisher.mjs.map +1 -0
- package/dist/capture/build-state/resume.d.mts +7 -0
- package/dist/capture/build-state/resume.mjs +46 -0
- package/dist/capture/build-state/resume.mjs.map +1 -0
- package/dist/capture/build-state/types.d.mts +47 -0
- package/dist/capture/catalog/catalogue.d.mts +20 -0
- package/dist/capture/catalog/catalogue.mjs +52 -0
- package/dist/capture/catalog/catalogue.mjs.map +1 -0
- package/dist/capture/catalog/components.d.mts +21 -0
- package/dist/capture/catalog/components.mjs +54 -0
- package/dist/capture/catalog/components.mjs.map +1 -0
- package/dist/capture/catalog/history.d.mts +28 -0
- package/dist/capture/catalog/history.mjs +50 -0
- package/dist/capture/catalog/history.mjs.map +1 -0
- package/dist/capture/catalog/hook.d.mts +12 -0
- package/dist/capture/catalog/hook.mjs +18 -0
- package/dist/capture/catalog/hook.mjs.map +1 -0
- package/dist/capture/catalog/index.d.mts +11 -0
- package/dist/capture/catalog/load.d.mts +24 -0
- package/dist/capture/catalog/load.mjs +48 -0
- package/dist/capture/catalog/load.mjs.map +1 -0
- package/dist/capture/catalog/parse.d.mts +13 -0
- package/dist/capture/catalog/parse.mjs +55 -0
- package/dist/capture/catalog/parse.mjs.map +1 -0
- package/dist/capture/catalog/read.d.mts +15 -0
- package/dist/capture/catalog/read.mjs +39 -0
- package/dist/capture/catalog/read.mjs.map +1 -0
- package/dist/capture/catalog/types.d.mts +31 -0
- 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 +56 -0
- package/dist/capture/consumer/capture-handler.mjs +117 -0
- package/dist/capture/consumer/capture-handler.mjs.map +1 -0
- package/dist/capture/consumer/idle.d.mts +15 -0
- package/dist/capture/consumer/idle.mjs +24 -0
- package/dist/capture/consumer/idle.mjs.map +1 -0
- package/dist/capture/consumer/index.d.mts +11 -0
- package/dist/capture/consumer/index.mjs +138 -0
- package/dist/capture/consumer/index.mjs.map +1 -0
- package/dist/capture/consumer/loop.mjs +109 -0
- package/dist/capture/consumer/loop.mjs.map +1 -0
- package/dist/capture/consumer/metrics.d.mts +39 -0
- package/dist/capture/consumer/metrics.mjs +37 -0
- package/dist/capture/consumer/metrics.mjs.map +1 -0
- package/dist/capture/consumer/retry.d.mts +31 -0
- package/dist/capture/consumer/retry.mjs +33 -0
- package/dist/capture/consumer/retry.mjs.map +1 -0
- package/dist/capture/consumer/run-job.mjs +194 -0
- package/dist/capture/consumer/run-job.mjs.map +1 -0
- package/dist/capture/consumer/startup.mjs +37 -0
- package/dist/capture/consumer/startup.mjs.map +1 -0
- package/dist/capture/consumer/types.d.mts +95 -0
- package/dist/capture/crash-failure.d.mts +23 -0
- package/dist/capture/crash-failure.mjs +69 -0
- package/dist/capture/crash-failure.mjs.map +1 -0
- package/dist/capture/db-queue/cadence.d.mts +30 -0
- package/dist/capture/db-queue/cadence.mjs +37 -0
- package/dist/capture/db-queue/cadence.mjs.map +1 -0
- package/dist/capture/db-queue/claim.d.mts +7 -0
- package/dist/capture/db-queue/claim.mjs +148 -0
- package/dist/capture/db-queue/claim.mjs.map +1 -0
- package/dist/capture/db-queue/clock.mjs +11 -0
- package/dist/capture/db-queue/clock.mjs.map +1 -0
- package/dist/capture/db-queue/codec.mjs +75 -0
- package/dist/capture/db-queue/codec.mjs.map +1 -0
- package/dist/capture/db-queue/index.d.mts +18 -0
- package/dist/capture/db-queue/index.mjs +89 -0
- package/dist/capture/db-queue/index.mjs.map +1 -0
- package/dist/capture/db-queue/keeper.d.mts +34 -0
- package/dist/capture/db-queue/keeper.mjs +91 -0
- package/dist/capture/db-queue/keeper.mjs.map +1 -0
- package/dist/capture/db-queue/lease.mjs +45 -0
- package/dist/capture/db-queue/lease.mjs.map +1 -0
- package/dist/capture/db-queue/lifecycle.mjs +35 -0
- package/dist/capture/db-queue/lifecycle.mjs.map +1 -0
- package/dist/capture/db-queue/operations.mjs +93 -0
- package/dist/capture/db-queue/operations.mjs.map +1 -0
- package/dist/capture/db-queue/poll-loop.d.mts +28 -0
- package/dist/capture/db-queue/poll-loop.mjs +88 -0
- package/dist/capture/db-queue/poll-loop.mjs.map +1 -0
- package/dist/capture/db-queue/poll.d.mts +8 -0
- package/dist/capture/db-queue/poll.mjs +68 -0
- package/dist/capture/db-queue/poll.mjs.map +1 -0
- package/dist/capture/db-queue/timers.d.mts +10 -0
- package/dist/capture/db-queue/timers.mjs +36 -0
- package/dist/capture/db-queue/timers.mjs.map +1 -0
- package/dist/capture/db-queue/types.d.mts +81 -0
- package/dist/capture/db-queue/types.mjs +11 -0
- package/dist/capture/db-queue/types.mjs.map +1 -0
- package/dist/capture/db-queue/wake.mjs +47 -0
- package/dist/capture/db-queue/wake.mjs.map +1 -0
- package/dist/capture/design.mjs +38 -0
- package/dist/capture/design.mjs.map +1 -0
- package/dist/capture/diff-record.mjs +24 -5
- package/dist/capture/diff-record.mjs.map +1 -1
- package/dist/capture/dispatch.d.mts +13 -10
- package/dist/capture/dispatch.mjs +102 -111
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/enrich.mjs +59 -0
- package/dist/capture/enrich.mjs.map +1 -0
- package/dist/capture/failure-sets.mjs +21 -0
- package/dist/capture/failure-sets.mjs.map +1 -0
- package/dist/capture/fingerprint.d.mts +40 -0
- package/dist/capture/fingerprint.mjs +82 -0
- package/dist/capture/fingerprint.mjs.map +1 -0
- package/dist/capture/forked/channel.d.mts +23 -0
- package/dist/capture/forked/child.d.mts +32 -0
- package/dist/capture/forked/child.mjs +201 -0
- package/dist/capture/forked/child.mjs.map +1 -0
- package/dist/capture/forked/crash-tracker.mjs +22 -0
- package/dist/capture/forked/crash-tracker.mjs.map +1 -0
- package/dist/capture/forked/decision.d.mts +24 -0
- package/dist/capture/forked/decision.mjs +26 -0
- package/dist/capture/forked/decision.mjs.map +1 -0
- package/dist/capture/forked/exit.mjs +11 -0
- package/dist/capture/forked/exit.mjs.map +1 -0
- package/dist/capture/forked/fork.d.mts +29 -0
- package/dist/capture/forked/fork.mjs +92 -0
- package/dist/capture/forked/fork.mjs.map +1 -0
- package/dist/capture/forked/forked-capture.d.mts +38 -0
- package/dist/capture/forked/forked-capture.mjs +239 -0
- package/dist/capture/forked/forked-capture.mjs.map +1 -0
- package/dist/capture/forked/lease-book.mjs +45 -0
- package/dist/capture/forked/lease-book.mjs.map +1 -0
- package/dist/capture/forked/protocol.d.mts +36 -0
- package/dist/capture/forked/protocol.mjs +24 -0
- package/dist/capture/forked/protocol.mjs.map +1 -0
- package/dist/capture/forked/runs.mjs +74 -0
- package/dist/capture/forked/runs.mjs.map +1 -0
- 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 +140 -0
- package/dist/capture/isolate.mjs.map +1 -0
- package/dist/capture/job-lease.d.mts +26 -0
- package/dist/capture/job-lease.mjs +56 -0
- package/dist/capture/job-lease.mjs.map +1 -0
- package/dist/capture/matrix.mjs +298 -0
- package/dist/capture/matrix.mjs.map +1 -0
- package/dist/capture/modes.d.mts +23 -0
- package/dist/capture/modes.mjs +106 -0
- package/dist/capture/modes.mjs.map +1 -0
- package/dist/capture/orchestrator.d.mts +37 -7
- package/dist/capture/orchestrator.mjs +120 -110
- package/dist/capture/orchestrator.mjs.map +1 -1
- package/dist/capture/pipeline.d.mts +9 -4
- package/dist/capture/pipeline.mjs +284 -48
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/progress.d.mts +9 -0
- package/dist/capture/progress.mjs +27 -0
- package/dist/capture/progress.mjs.map +1 -0
- package/dist/capture/publish/accept.d.mts +37 -0
- package/dist/capture/publish/accept.mjs +27 -0
- package/dist/capture/publish/accept.mjs.map +1 -0
- package/dist/capture/publish/complete.d.mts +44 -0
- package/dist/capture/publish/complete.mjs +63 -0
- package/dist/capture/publish/complete.mjs.map +1 -0
- package/dist/capture/publish/extract.d.mts +18 -0
- package/dist/capture/publish/extract.mjs +120 -0
- package/dist/capture/publish/extract.mjs.map +1 -0
- package/dist/capture/publish/handler.d.mts +26 -0
- package/dist/capture/publish/handler.mjs +61 -0
- package/dist/capture/publish/handler.mjs.map +1 -0
- package/dist/capture/publish/index.d.mts +11 -0
- 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 +35 -0
- package/dist/capture/publish/limits.mjs +38 -0
- package/dist/capture/publish/limits.mjs.map +1 -0
- package/dist/capture/publish/published.d.mts +13 -0
- package/dist/capture/publish/published.mjs +17 -0
- package/dist/capture/publish/published.mjs.map +1 -0
- package/dist/capture/publish/run.d.mts +31 -0
- package/dist/capture/publish/run.mjs +29 -0
- package/dist/capture/publish/run.mjs.map +1 -0
- package/dist/capture/rediff.d.mts +1 -3
- package/dist/capture/rediff.mjs +23 -9
- package/dist/capture/rediff.mjs.map +1 -1
- package/dist/capture/render.mjs +52 -0
- package/dist/capture/render.mjs.map +1 -0
- package/dist/capture/scratch.d.mts +42 -0
- package/dist/capture/scratch.mjs +136 -0
- package/dist/capture/scratch.mjs.map +1 -0
- package/dist/capture/shard-plan.mjs +127 -0
- package/dist/capture/shard-plan.mjs.map +1 -0
- package/dist/capture/shards/context.mjs +51 -0
- package/dist/capture/shards/context.mjs.map +1 -0
- package/dist/capture/shards/execute.mjs +175 -0
- package/dist/capture/shards/execute.mjs.map +1 -0
- package/dist/capture/shards/fan-out.mjs +125 -0
- package/dist/capture/shards/fan-out.mjs.map +1 -0
- package/dist/capture/shards/history.mjs +34 -0
- package/dist/capture/shards/history.mjs.map +1 -0
- package/dist/capture/shards/reduce.mjs +96 -0
- package/dist/capture/shards/reduce.mjs.map +1 -0
- package/dist/capture/sizing.d.mts +0 -2
- package/dist/capture/sizing.mjs +2 -13
- package/dist/capture/sizing.mjs.map +1 -1
- package/dist/capture/skip-checks.mjs +3 -67
- package/dist/capture/skip-checks.mjs.map +1 -1
- package/dist/capture/statics.d.mts +7 -10
- package/dist/capture/statics.mjs +26 -74
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/storybook-urls.d.mts +38 -0
- package/dist/capture/storybook-urls.mjs +41 -0
- package/dist/capture/storybook-urls.mjs.map +1 -0
- package/dist/capture/storybook.d.mts +12 -6
- package/dist/capture/storybook.mjs +63 -19
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture/target.mjs +20 -0
- package/dist/capture/target.mjs.map +1 -0
- package/dist/capture/targets.d.mts +23 -0
- package/dist/capture/targets.mjs +31 -0
- package/dist/capture/targets.mjs.map +1 -0
- package/dist/capture/tests.d.mts +35 -0
- package/dist/capture/tests.mjs +136 -0
- package/dist/capture/tests.mjs.map +1 -0
- package/dist/capture/token-chunks.mjs +91 -0
- package/dist/capture/token-chunks.mjs.map +1 -0
- package/dist/capture.d.mts +63 -7
- package/dist/capture.mjs +51 -3
- package/dist/config.d.mts +136 -14
- package/dist/config.mjs +14 -8
- package/dist/config.mjs.map +1 -1
- package/dist/diff.d.mts +7 -3
- package/dist/diff.mjs +15 -3
- package/dist/diff.mjs.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/insights/budget.d.mts +18 -0
- package/dist/insights/budget.mjs +32 -0
- package/dist/insights/budget.mjs.map +1 -0
- package/dist/insights/envelope.d.mts +57 -0
- package/dist/insights/envelope.mjs +59 -0
- package/dist/insights/envelope.mjs.map +1 -0
- package/dist/insights/evidence-health.d.mts +30 -0
- package/dist/insights/evidence-health.mjs +27 -0
- package/dist/insights/evidence-health.mjs.map +1 -0
- package/dist/insights/evidence.d.mts +53 -0
- package/dist/insights/evidence.mjs +63 -0
- package/dist/insights/evidence.mjs.map +1 -0
- package/dist/insights/hash.d.mts +16 -0
- package/dist/insights/hash.mjs +20 -0
- package/dist/insights/hash.mjs.map +1 -0
- package/dist/insights/limits.d.mts +22 -0
- package/dist/insights/limits.mjs +23 -0
- package/dist/insights/limits.mjs.map +1 -0
- package/dist/insights/prompts/v1.d.mts +11 -0
- package/dist/insights/prompts/v1.mjs +33 -0
- package/dist/insights/prompts/v1.mjs.map +1 -0
- package/dist/insights/redact.d.mts +7 -0
- package/dist/insights/redact.mjs +23 -0
- package/dist/insights/redact.mjs.map +1 -0
- package/dist/insights/text.mjs +43 -0
- package/dist/insights/text.mjs.map +1 -0
- package/dist/insights.d.mts +11 -0
- package/dist/insights.mjs +12 -0
- package/dist/logger.d.mts +0 -2
- package/dist/logger.mjs +18 -3
- package/dist/logger.mjs.map +1 -1
- package/dist/models/ai-budget-alert.d.mts +21 -0
- package/dist/models/ai-budget-alert.mjs +37 -0
- package/dist/models/ai-budget-alert.mjs.map +1 -0
- package/dist/models/ai-usage.d.mts +38 -0
- package/dist/models/ai-usage.mjs +60 -0
- package/dist/models/ai-usage.mjs.map +1 -0
- 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 +82 -0
- package/dist/models/baseline-archive.mjs +105 -0
- package/dist/models/baseline-archive.mjs.map +1 -0
- 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 +17 -0
- package/dist/models/baseline-export.mjs +135 -0
- package/dist/models/baseline-export.mjs.map +1 -0
- package/dist/models/baseline-import.mjs +117 -0
- package/dist/models/baseline-import.mjs.map +1 -0
- 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 +48 -0
- package/dist/models/baseline-transfer.mjs +149 -0
- package/dist/models/baseline-transfer.mjs.map +1 -0
- package/dist/models/baseline.d.mts +37 -7
- package/dist/models/baseline.mjs +152 -28
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build-component.d.mts +26 -0
- package/dist/models/build-component.mjs +54 -0
- package/dist/models/build-component.mjs.map +1 -0
- package/dist/models/build-review-status.d.mts +27 -0
- package/dist/models/build-review-status.mjs +36 -0
- package/dist/models/build-review-status.mjs.map +1 -0
- package/dist/models/build-review.d.mts +26 -0
- package/dist/models/build-review.mjs +53 -0
- package/dist/models/build-review.mjs.map +1 -0
- package/dist/models/build.d.mts +25 -5
- package/dist/models/build.mjs +53 -15
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +7 -3
- package/dist/models/capture-attempt.mjs +30 -6
- package/dist/models/capture-attempt.mjs.map +1 -1
- package/dist/models/capture-job.d.mts +104 -0
- package/dist/models/capture-job.mjs +287 -0
- package/dist/models/capture-job.mjs.map +1 -0
- package/dist/models/capture-log.d.mts +1 -3
- package/dist/models/capture-log.mjs +5 -5
- package/dist/models/capture-log.mjs.map +1 -1
- package/dist/models/capture-shard.d.mts +60 -0
- package/dist/models/capture-shard.mjs +189 -0
- package/dist/models/capture-shard.mjs.map +1 -0
- package/dist/models/changeset.d.mts +46 -0
- package/dist/models/changeset.mjs +80 -0
- package/dist/models/changeset.mjs.map +1 -0
- package/dist/models/columns.mjs +18 -0
- package/dist/models/columns.mjs.map +1 -0
- package/dist/models/comment.d.mts +4 -3
- package/dist/models/comment.mjs +8 -6
- package/dist/models/comment.mjs.map +1 -1
- package/dist/models/component.d.mts +41 -0
- package/dist/models/component.mjs +59 -0
- package/dist/models/component.mjs.map +1 -0
- package/dist/models/connections.d.mts +39 -0
- package/dist/models/connections.mjs +111 -0
- package/dist/models/connections.mjs.map +1 -0
- package/dist/models/content-ref.d.mts +1 -3
- package/dist/models/content-ref.mjs +2 -3
- package/dist/models/content-ref.mjs.map +1 -1
- package/dist/models/credentials.d.mts +0 -2
- package/dist/models/credentials.mjs +13 -4
- package/dist/models/credentials.mjs.map +1 -1
- package/dist/models/design-credentials.d.mts +39 -0
- package/dist/models/design-credentials.mjs +85 -0
- package/dist/models/design-credentials.mjs.map +1 -0
- package/dist/models/design-health.d.mts +14 -0
- package/dist/models/design-health.mjs +24 -0
- package/dist/models/design-health.mjs.map +1 -0
- package/dist/models/design-nodes.d.mts +81 -0
- package/dist/models/design-nodes.mjs +221 -0
- package/dist/models/design-nodes.mjs.map +1 -0
- package/dist/models/design-renders.mjs +73 -0
- package/dist/models/design-renders.mjs.map +1 -0
- package/dist/models/design-resolve.d.mts +27 -0
- package/dist/models/design-resolve.mjs +40 -0
- package/dist/models/design-resolve.mjs.map +1 -0
- package/dist/models/design.d.mts +37 -0
- package/dist/models/design.mjs +89 -0
- package/dist/models/design.mjs.map +1 -0
- package/dist/models/inherited-ratio.d.mts +19 -0
- package/dist/models/inherited-ratio.mjs +21 -0
- package/dist/models/inherited-ratio.mjs.map +1 -0
- package/dist/models/insight.d.mts +68 -0
- package/dist/models/insight.mjs +161 -0
- package/dist/models/insight.mjs.map +1 -0
- package/dist/models/label.d.mts +4 -4
- package/dist/models/label.mjs +26 -12
- package/dist/models/label.mjs.map +1 -1
- package/dist/models/member.d.mts +1 -3
- package/dist/models/member.mjs +6 -6
- package/dist/models/member.mjs.map +1 -1
- package/dist/models/notification-channel.d.mts +37 -5
- package/dist/models/notification-channel.mjs +89 -11
- package/dist/models/notification-channel.mjs.map +1 -1
- package/dist/models/notification-subscription.d.mts +1 -4
- package/dist/models/notification-subscription.mjs +8 -11
- package/dist/models/notification-subscription.mjs.map +1 -1
- package/dist/models/project-group-mapping.d.mts +6 -3
- package/dist/models/project-group-mapping.mjs +15 -6
- package/dist/models/project-group-mapping.mjs.map +1 -1
- package/dist/models/project.d.mts +9 -3
- package/dist/models/project.mjs +10 -6
- package/dist/models/project.mjs.map +1 -1
- package/dist/models/public-origin.d.mts +61 -0
- package/dist/models/public-origin.mjs +113 -0
- package/dist/models/public-origin.mjs.map +1 -0
- package/dist/models/review-switch-off.d.mts +12 -0
- package/dist/models/review-switch-off.mjs +25 -0
- package/dist/models/review-switch-off.mjs.map +1 -0
- package/dist/models/site-settings.d.mts +21 -0
- package/dist/models/site-settings.mjs +47 -0
- package/dist/models/site-settings.mjs.map +1 -0
- package/dist/models/snapshot.d.mts +39 -3
- package/dist/models/snapshot.mjs +54 -5
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/token.d.mts +13 -3
- package/dist/models/token.mjs +24 -7
- package/dist/models/token.mjs.map +1 -1
- package/dist/models/usage.d.mts +74 -0
- package/dist/models/usage.mjs +148 -0
- package/dist/models/usage.mjs.map +1 -0
- package/dist/models/user.d.mts +1 -3
- package/dist/models/user.mjs +5 -5
- package/dist/models/user.mjs.map +1 -1
- package/dist/models/webhook.d.mts +15 -3
- package/dist/models/webhook.mjs +34 -6
- package/dist/models/webhook.mjs.map +1 -1
- package/dist/models.d.mts +30 -4
- package/dist/models.mjs +31 -6
- package/dist/options.d.mts +16 -0
- package/dist/options.mjs +88 -0
- package/dist/options.mjs.map +1 -0
- package/dist/paths.d.mts +21 -6
- package/dist/paths.mjs +57 -12
- package/dist/paths.mjs.map +1 -1
- package/dist/retention/ai.d.mts +16 -0
- package/dist/retention/ai.mjs +22 -0
- package/dist/retention/ai.mjs.map +1 -0
- package/dist/retention/pending.mjs +46 -0
- package/dist/retention/pending.mjs.map +1 -0
- 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 +49 -0
- package/dist/retention/screenshot-sweep.mjs +127 -0
- package/dist/retention/screenshot-sweep.mjs.map +1 -0
- package/dist/retention.d.mts +16 -4
- package/dist/retention.mjs +76 -16
- package/dist/retention.mjs.map +1 -1
- package/dist/schema/baseline.d.mts +8 -2
- package/dist/schema/build-component.d.mts +23 -0
- package/dist/schema/build-review.d.mts +15 -0
- package/dist/schema/build.d.mts +7 -2
- package/dist/schema/capture-attempt.d.mts +0 -2
- package/dist/schema/capture-job.d.mts +58 -0
- package/dist/schema/capture-shard.d.mts +33 -0
- package/dist/schema/comment.d.mts +2 -2
- package/dist/schema/connection.d.mts +22 -0
- package/dist/schema/content-ref.d.mts +0 -2
- package/dist/schema/design.d.mts +56 -0
- package/dist/schema/insight.d.mts +52 -0
- package/dist/schema/label.d.mts +0 -2
- package/dist/schema/member.d.mts +0 -2
- package/dist/schema/notification.d.mts +4 -2
- package/dist/schema/project-group-mapping.d.mts +0 -2
- package/dist/schema/project.d.mts +21 -2
- package/dist/schema/site-setting.d.mts +19 -0
- package/dist/schema/snapshot.d.mts +17 -2
- package/dist/schema/token.d.mts +0 -2
- package/dist/schema/usage.d.mts +28 -0
- package/dist/schema/user.d.mts +0 -2
- package/dist/schema/webhook.d.mts +0 -2
- package/dist/schema.d.mts +12 -6
- package/dist/serverless.d.mts +19 -0
- package/dist/serverless.mjs +36 -0
- package/dist/serverless.mjs.map +1 -0
- 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 +1 -3
- 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 +37 -0
- package/dist/test-helpers/deferred.mjs +60 -0
- package/dist/test-helpers/deferred.mjs.map +1 -0
- package/dist/test-helpers/design-contract.d.mts +19 -0
- package/dist/test-helpers/design-contract.mjs +39 -0
- package/dist/test-helpers/design-contract.mjs.map +1 -0
- 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 +21 -4
- package/dist/test-helpers/fake-database.mjs.map +1 -1
- package/dist/test-helpers/fake-design.d.mts +41 -0
- package/dist/test-helpers/fake-design.mjs +113 -0
- package/dist/test-helpers/fake-design.mjs.map +1 -0
- package/dist/test-helpers/fake-notifier.d.mts +19 -0
- package/dist/test-helpers/fake-notifier.mjs +43 -0
- package/dist/test-helpers/fake-notifier.mjs.map +1 -0
- 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 +260 -69
- package/dist/test-helpers/fake-tables.mjs.map +1 -1
- package/dist/test-helpers/manual-clock.d.mts +25 -0
- package/dist/test-helpers/manual-clock.mjs +55 -0
- package/dist/test-helpers/manual-clock.mjs.map +1 -0
- package/dist/test-helpers/notifier-contract.d.mts +7 -3
- package/dist/test-helpers/notifier-contract.mjs +33 -5
- package/dist/test-helpers/notifier-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-contract.d.mts +16 -4
- package/dist/test-helpers/queue-contract.mjs +196 -3
- package/dist/test-helpers/queue-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-multi-instance.d.mts +18 -0
- package/dist/test-helpers/queue-multi-instance.mjs +205 -0
- package/dist/test-helpers/queue-multi-instance.mjs.map +1 -0
- package/dist/test-helpers/runner-contract.d.mts +0 -2
- package/dist/test-helpers/runner-contract.mjs +12 -2
- package/dist/test-helpers/runner-contract.mjs.map +1 -1
- package/dist/test-helpers/sql-chunks.mjs +25 -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 +2 -3
- package/dist/test-helpers.d.mts +10 -4
- package/dist/test-helpers.mjs +9 -3
- package/dist/tracing.mjs +36 -6
- package/dist/tracing.mjs.map +1 -1
- package/dist/types.d.mts +14 -5
- package/dist/types.mjs +22 -6
- package/dist/types.mjs.map +1 -1
- package/dist/urls.d.mts +4 -2
- package/dist/urls.mjs +12 -4
- package/dist/urls.mjs.map +1 -1
- package/dist/utils/adaptive-concurrency.d.mts +64 -0
- package/dist/utils/adaptive-concurrency.mjs +148 -0
- package/dist/utils/adaptive-concurrency.mjs.map +1 -0
- package/dist/utils/connect-retry.d.mts +26 -0
- package/dist/utils/connect-retry.mjs +42 -0
- package/dist/utils/connect-retry.mjs.map +1 -0
- package/dist/utils/encrypt.d.mts +0 -2
- package/dist/utils/encrypt.mjs +1 -2
- package/dist/utils/environment.d.mts +17 -0
- package/dist/utils/environment.mjs +58 -0
- package/dist/utils/environment.mjs.map +1 -0
- package/dist/utils/hash.d.mts +0 -2
- package/dist/utils/hash.mjs +1 -2
- package/dist/utils/http.d.mts +29 -3
- package/dist/utils/http.mjs +100 -19
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/map-adaptive.d.mts +13 -0
- package/dist/utils/map-adaptive.mjs +71 -0
- package/dist/utils/map-adaptive.mjs.map +1 -0
- package/dist/utils/map-limit.d.mts +8 -0
- package/dist/utils/map-limit.mjs +31 -0
- package/dist/utils/map-limit.mjs.map +1 -0
- package/dist/utils/mime.d.mts +0 -2
- package/dist/utils/mime.mjs +1 -2
- package/dist/utils/page-limiter.d.mts +35 -0
- package/dist/utils/page-limiter.mjs +55 -0
- package/dist/utils/page-limiter.mjs.map +1 -0
- 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 +18 -0
- package/dist/utils/public-origin.mjs +74 -0
- package/dist/utils/public-origin.mjs.map +1 -0
- package/dist/utils/redact.d.mts +0 -2
- package/dist/utils/redact.mjs +4 -2
- package/dist/utils/redact.mjs.map +1 -1
- package/dist/utils/remote-environment.d.mts +76 -0
- package/dist/utils/remote-environment.mjs +163 -0
- package/dist/utils/remote-environment.mjs.map +1 -0
- package/dist/utils/resources.d.mts +62 -0
- package/dist/utils/resources.mjs +121 -0
- package/dist/utils/resources.mjs.map +1 -0
- package/dist/utils/screenshot-store.d.mts +13 -0
- package/dist/utils/screenshot-store.mjs +40 -0
- package/dist/utils/screenshot-store.mjs.map +1 -0
- package/dist/utils/session-gate.d.mts +23 -0
- package/dist/utils/session-gate.mjs +69 -0
- package/dist/utils/session-gate.mjs.map +1 -0
- package/dist/utils/storybook-token.d.mts +89 -0
- package/dist/utils/storybook-token.mjs +135 -0
- package/dist/utils/storybook-token.mjs.map +1 -0
- package/dist/utils/storybook-url.d.mts +13 -0
- package/dist/utils/storybook-url.mjs +20 -0
- package/dist/utils/storybook-url.mjs.map +1 -0
- package/dist/utils/timing.d.mts +0 -2
- package/dist/utils/timing.mjs +2 -3
- package/dist/utils/timing.mjs.map +1 -1
- package/dist/utils/ulid.d.mts +0 -2
- package/dist/utils/ulid.mjs +1 -2
- package/dist/utils/zip-read.mjs +128 -0
- package/dist/utils/zip-read.mjs.map +1 -0
- package/dist/utils/zip-write.d.mts +16 -0
- package/dist/utils/zip-write.mjs +187 -0
- package/dist/utils/zip-write.mjs.map +1 -0
- package/dist/utils.d.mts +17 -3
- package/dist/utils.mjs +18 -4
- package/package.json +35 -26
- package/dist/adapter/capture-runner.mjs.map +0 -1
- package/dist/adapter/git-host/comments.d.mts +0 -41
- package/dist/adapter/git-host/comments.mjs +0 -54
- package/dist/adapter/git-host/comments.mjs.map +0 -1
- package/dist/adapter/git-host/helpers.d.mts +0 -13
- package/dist/adapter/git-host/helpers.mjs +0 -30
- package/dist/adapter/git-host/helpers.mjs.map +0 -1
- package/dist/adapter/git-host.d.mts +0 -42
- package/dist/capture/queue.d.mts +0 -38
- package/dist/capture/queue.mjs +0 -98
- package/dist/capture/queue.mjs.map +0 -1
- package/dist/capture/recovery.d.mts +0 -21
- package/dist/capture/recovery.mjs +0 -83
- package/dist/capture/recovery.mjs.map +0 -1
- package/dist/capture/status-fanout.mjs +0 -72
- package/dist/capture/status-fanout.mjs.map +0 -1
- package/dist/diff/engine.d.mts +0 -16
- package/dist/diff/engine.mjs +0 -87
- package/dist/diff/engine.mjs.map +0 -1
- package/dist/diff/options.d.mts +0 -42
- package/dist/diff/options.mjs +0 -15
- package/dist/diff/options.mjs.map +0 -1
- package/dist/models/status-config.d.mts +0 -38
- package/dist/models/status-config.mjs +0 -63
- package/dist/models/status-config.mjs.map +0 -1
- package/dist/schema/status-config.d.mts +0 -16
- package/dist/test-helpers/git-contract.d.mts +0 -11
- package/dist/test-helpers/git-contract.mjs +0 -34
- package/dist/test-helpers/git-contract.mjs.map +0 -1
- /package/dist/adapter/{git-host.mjs → oauth.mjs} +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* Capture targets (ADR 0007, decision 3): what a project names to render on. A target is a rendering
|
|
5
|
+
* engine (`chromium`) or a remote one, `<engine>@<name>` (`chromium@grid`), which has its own
|
|
6
|
+
* baselines and fingerprint.
|
|
7
|
+
*/
|
|
8
|
+
/** A rendering engine. */
|
|
9
|
+
type BrowserName = "chromium" | "firefox" | "webkit" | "chrome";
|
|
10
|
+
/** Engine names accepted for capture rendering (Chromium default). */
|
|
11
|
+
declare const BROWSER_NAMES: readonly ["chromium", "firefox", "webkit", "chrome"];
|
|
12
|
+
/** Engine that legacy rows and single-browser projects belong to. */
|
|
13
|
+
declare const DEFAULT_BROWSER: BrowserName;
|
|
14
|
+
/** What a project's `browsers` setting, a snapshot's `browser` and a baseline key hold. */
|
|
15
|
+
type CaptureTarget = BrowserName | `${BrowserName}@${string}`;
|
|
16
|
+
/** Remote target names: they become part of a storage key and a unique index. */
|
|
17
|
+
declare const TARGET_NAME_PATTERN: RegExp;
|
|
18
|
+
/** How a runner's browser reaches the Storybook (ADR 0007, decision 5). */
|
|
19
|
+
type TargetReach = "loopback" | "url";
|
|
20
|
+
/** Whether a target can render now; `unavailable` carries the reason shown to operators. */
|
|
21
|
+
type TargetStatus = "ready" | {
|
|
22
|
+
readonly unavailable: string;
|
|
23
|
+
};
|
|
24
|
+
/** One target a runner offers, in its metadata. */
|
|
25
|
+
interface RunnerTarget {
|
|
26
|
+
target: CaptureTarget;
|
|
27
|
+
reach: TargetReach;
|
|
28
|
+
status: TargetStatus;
|
|
29
|
+
}
|
|
30
|
+
/** A target split into its engine and, for a remote one, its name. */
|
|
31
|
+
interface ParsedTarget {
|
|
32
|
+
engine: BrowserName;
|
|
33
|
+
/** Set for `<engine>@<name>`; absent for a local engine. */
|
|
34
|
+
name?: string;
|
|
35
|
+
}
|
|
36
|
+
/** Whether `value` is an engine name. */
|
|
37
|
+
declare function isBrowserName(value: unknown): value is BrowserName;
|
|
38
|
+
/** Split a target into engine and name; `null` when it is not a valid target. */
|
|
39
|
+
declare function tryParseTarget(value: unknown): ParsedTarget | null;
|
|
40
|
+
/** Split a target into engine and name; throws on anything that is not a target. */
|
|
41
|
+
declare function parseTarget(value: string): ParsedTarget;
|
|
42
|
+
/** Whether `value` is a capture target. */
|
|
43
|
+
declare function isCaptureTarget(value: unknown): value is CaptureTarget;
|
|
44
|
+
/** The engine half of a target. */
|
|
45
|
+
declare function engineOf(target: CaptureTarget): BrowserName;
|
|
46
|
+
/** The reason a status is unavailable, or `null` when it is ready. */
|
|
47
|
+
declare function unavailableReason(status: TargetStatus): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* A launch or connect failure: the browser never started, so the job fails at once with this
|
|
50
|
+
* reason. Crash isolation (`capture/isolate.ts`) must not see it, since no story is at fault
|
|
51
|
+
* (ADR 0007, decision 7).
|
|
52
|
+
*/
|
|
53
|
+
declare class TargetLaunchError extends Error {
|
|
54
|
+
readonly name = "TargetLaunchError";
|
|
55
|
+
readonly target: CaptureTarget;
|
|
56
|
+
/** Why it did not start, without the target's name. */
|
|
57
|
+
readonly reason: string;
|
|
58
|
+
/**
|
|
59
|
+
* The failure may pass (a remote browser service that is down or full): the target is not marked
|
|
60
|
+
* unavailable for it, though the job still fails at once. A wrong version or credentials do not.
|
|
61
|
+
*/
|
|
62
|
+
readonly transient: boolean;
|
|
63
|
+
constructor(target: CaptureTarget, reason: string, options?: {
|
|
64
|
+
cause?: unknown;
|
|
65
|
+
transient?: boolean;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
export { BROWSER_NAMES, BrowserName, CaptureTarget, DEFAULT_BROWSER, ParsedTarget, RunnerTarget, TARGET_NAME_PATTERN, TargetLaunchError, TargetReach, TargetStatus, engineOf, isBrowserName, isCaptureTarget, parseTarget, tryParseTarget, unavailableReason };
|
|
69
|
+
//# sourceMappingURL=capture-target.d.mts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/adapters/capture-target.ts
|
|
5
|
+
/** Engine names accepted for capture rendering (Chromium default). */
|
|
6
|
+
const BROWSER_NAMES = [
|
|
7
|
+
"chromium",
|
|
8
|
+
"firefox",
|
|
9
|
+
"webkit",
|
|
10
|
+
"chrome"
|
|
11
|
+
];
|
|
12
|
+
/** Engine that legacy rows and single-browser projects belong to. */
|
|
13
|
+
const DEFAULT_BROWSER = "chromium";
|
|
14
|
+
/** Remote target names: they become part of a storage key and a unique index. */
|
|
15
|
+
const TARGET_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/u;
|
|
16
|
+
/** Whether `value` is an engine name. */
|
|
17
|
+
function isBrowserName(value) {
|
|
18
|
+
return typeof value === "string" && BROWSER_NAMES.includes(value);
|
|
19
|
+
}
|
|
20
|
+
/** Split a target into engine and name; `null` when it is not a valid target. */
|
|
21
|
+
function tryParseTarget(value) {
|
|
22
|
+
if (typeof value !== "string") return null;
|
|
23
|
+
const at = value.indexOf("@");
|
|
24
|
+
const engine = at === -1 ? value : value.slice(0, at);
|
|
25
|
+
if (!isBrowserName(engine)) return null;
|
|
26
|
+
if (at === -1) return { engine };
|
|
27
|
+
const name = value.slice(at + 1);
|
|
28
|
+
return TARGET_NAME_PATTERN.test(name) ? {
|
|
29
|
+
engine,
|
|
30
|
+
name
|
|
31
|
+
} : null;
|
|
32
|
+
}
|
|
33
|
+
/** Split a target into engine and name; throws on anything that is not a target. */
|
|
34
|
+
function parseTarget(value) {
|
|
35
|
+
const parsed = tryParseTarget(value);
|
|
36
|
+
if (parsed === null) throw new Error(`Invalid capture target "${value}": expected one of ${BROWSER_NAMES.join(", ")}, or <engine>@<name> with a lowercase name of at most 32 letters, digits and hyphens`);
|
|
37
|
+
return parsed;
|
|
38
|
+
}
|
|
39
|
+
/** Whether `value` is a capture target. */
|
|
40
|
+
function isCaptureTarget(value) {
|
|
41
|
+
return tryParseTarget(value) !== null;
|
|
42
|
+
}
|
|
43
|
+
/** The engine half of a target. */
|
|
44
|
+
function engineOf(target) {
|
|
45
|
+
return parseTarget(target).engine;
|
|
46
|
+
}
|
|
47
|
+
/** The reason a status is unavailable, or `null` when it is ready. */
|
|
48
|
+
function unavailableReason(status) {
|
|
49
|
+
return status === "ready" ? null : status.unavailable;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A launch or connect failure: the browser never started, so the job fails at once with this
|
|
53
|
+
* reason. Crash isolation (`capture/isolate.ts`) must not see it, since no story is at fault
|
|
54
|
+
* (ADR 0007, decision 7).
|
|
55
|
+
*/
|
|
56
|
+
var TargetLaunchError = class extends Error {
|
|
57
|
+
name = "TargetLaunchError";
|
|
58
|
+
target;
|
|
59
|
+
/** Why it did not start, without the target's name. */
|
|
60
|
+
reason;
|
|
61
|
+
/**
|
|
62
|
+
* The failure may pass (a remote browser service that is down or full): the target is not marked
|
|
63
|
+
* unavailable for it, though the job still fails at once. A wrong version or credentials do not.
|
|
64
|
+
*/
|
|
65
|
+
transient;
|
|
66
|
+
constructor(target, reason, options) {
|
|
67
|
+
super(`Cannot launch ${target}: ${reason}`, options);
|
|
68
|
+
this.target = target;
|
|
69
|
+
this.reason = reason;
|
|
70
|
+
this.transient = options?.transient ?? false;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
export { BROWSER_NAMES, DEFAULT_BROWSER, TARGET_NAME_PATTERN, TargetLaunchError, engineOf, isBrowserName, isCaptureTarget, parseTarget, tryParseTarget, unavailableReason };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=capture-target.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture-target.mjs","names":[],"sources":["../../src/adapters/capture-target.ts"],"sourcesContent":["/**\n * Capture targets (ADR 0007, decision 3): what a project names to render on. A target is a rendering\n * engine (`chromium`) or a remote one, `<engine>@<name>` (`chromium@grid`), which has its own\n * baselines and fingerprint.\n */\n\n/** A rendering engine. */\nexport type BrowserName = \"chromium\" | \"firefox\" | \"webkit\" | \"chrome\";\n\n/** Engine names accepted for capture rendering (Chromium default). */\nexport const BROWSER_NAMES = [\"chromium\", \"firefox\", \"webkit\", \"chrome\"] as const;\n\n/** Engine that legacy rows and single-browser projects belong to. */\nexport const DEFAULT_BROWSER: BrowserName = \"chromium\";\n\n/** What a project's `browsers` setting, a snapshot's `browser` and a baseline key hold. */\nexport type CaptureTarget = BrowserName | `${BrowserName}@${string}`;\n\n/** Remote target names: they become part of a storage key and a unique index. */\nexport const TARGET_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/u;\n\n/** How a runner's browser reaches the Storybook (ADR 0007, decision 5). */\nexport type TargetReach = \"loopback\" | \"url\";\n\n/** Whether a target can render now; `unavailable` carries the reason shown to operators. */\nexport type TargetStatus = \"ready\" | { readonly unavailable: string };\n\n/** One target a runner offers, in its metadata. */\nexport interface RunnerTarget {\n target: CaptureTarget;\n reach: TargetReach;\n status: TargetStatus;\n}\n\n/** A target split into its engine and, for a remote one, its name. */\nexport interface ParsedTarget {\n engine: BrowserName;\n /** Set for `<engine>@<name>`; absent for a local engine. */\n name?: string;\n}\n\n/** Whether `value` is an engine name. */\nexport function isBrowserName(value: unknown): value is BrowserName {\n return typeof value === \"string\" && (BROWSER_NAMES as readonly string[]).includes(value);\n}\n\n/** Split a target into engine and name; `null` when it is not a valid target. */\nexport function tryParseTarget(value: unknown): ParsedTarget | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const at = value.indexOf(\"@\");\n const engine = at === -1 ? value : value.slice(0, at);\n if (!isBrowserName(engine)) {\n return null;\n }\n if (at === -1) {\n return { engine };\n }\n const name = value.slice(at + 1);\n return TARGET_NAME_PATTERN.test(name) ? { engine, name } : null;\n}\n\n/** Split a target into engine and name; throws on anything that is not a target. */\nexport function parseTarget(value: string): ParsedTarget {\n const parsed = tryParseTarget(value);\n if (parsed === null) {\n throw new Error(\n `Invalid capture target \"${value}\": expected one of ${BROWSER_NAMES.join(\", \")}, or <engine>@<name> with a lowercase name of at most 32 letters, digits and hyphens`,\n );\n }\n return parsed;\n}\n\n/** Whether `value` is a capture target. */\nexport function isCaptureTarget(value: unknown): value is CaptureTarget {\n return tryParseTarget(value) !== null;\n}\n\n/** The engine half of a target. */\nexport function engineOf(target: CaptureTarget): BrowserName {\n return parseTarget(target).engine;\n}\n\n/** The reason a status is unavailable, or `null` when it is ready. */\nexport function unavailableReason(status: TargetStatus): string | null {\n return status === \"ready\" ? null : status.unavailable;\n}\n\n/**\n * A launch or connect failure: the browser never started, so the job fails at once with this\n * reason. Crash isolation (`capture/isolate.ts`) must not see it, since no story is at fault\n * (ADR 0007, decision 7).\n */\nexport class TargetLaunchError extends Error {\n override readonly name = \"TargetLaunchError\";\n readonly target: CaptureTarget;\n /** Why it did not start, without the target's name. */\n readonly reason: string;\n /**\n * The failure may pass (a remote browser service that is down or full): the target is not marked\n * unavailable for it, though the job still fails at once. A wrong version or credentials do not.\n */\n readonly transient: boolean;\n\n constructor(\n target: CaptureTarget,\n reason: string,\n options?: { cause?: unknown; transient?: boolean },\n ) {\n super(`Cannot launch ${target}: ${reason}`, options);\n this.target = target;\n this.reason = reason;\n this.transient = options?.transient ?? false;\n }\n}\n"],"mappings":";;;;;AAUA,MAAa,gBAAgB;CAAC;CAAY;CAAW;CAAU;AAAQ;;AAGvE,MAAa,kBAA+B;;AAM5C,MAAa,sBAAsB;;AAuBnC,SAAgB,cAAc,OAAsC;CAClE,OAAO,OAAO,UAAU,YAAa,cAAoC,SAAS,KAAK;AACzF;;AAGA,SAAgB,eAAe,OAAqC;CAClE,IAAI,OAAO,UAAU,UACnB,OAAO;CAET,MAAM,KAAK,MAAM,QAAQ,GAAG;CAC5B,MAAM,SAAS,OAAO,KAAK,QAAQ,MAAM,MAAM,GAAG,EAAE;CACpD,IAAI,CAAC,cAAc,MAAM,GACvB,OAAO;CAET,IAAI,OAAO,IACT,OAAO,EAAE,OAAO;CAElB,MAAM,OAAO,MAAM,MAAM,KAAK,CAAC;CAC/B,OAAO,oBAAoB,KAAK,IAAI,IAAI;EAAE;EAAQ;CAAK,IAAI;AAC7D;;AAGA,SAAgB,YAAY,OAA6B;CACvD,MAAM,SAAS,eAAe,KAAK;CACnC,IAAI,WAAW,MACb,MAAM,IAAI,MACR,2BAA2B,MAAM,qBAAqB,cAAc,KAAK,IAAI,EAAE,qFACjF;CAEF,OAAO;AACT;;AAGA,SAAgB,gBAAgB,OAAwC;CACtE,OAAO,eAAe,KAAK,MAAM;AACnC;;AAGA,SAAgB,SAAS,QAAoC;CAC3D,OAAO,YAAY,MAAM,CAAC,CAAC;AAC7B;;AAGA,SAAgB,kBAAkB,QAAqC;CACrE,OAAO,WAAW,UAAU,OAAO,OAAO;AAC5C;;;;;;AAOA,IAAa,oBAAb,cAAuC,MAAM;CAC3C,OAAyB;CACzB;;CAEA;;;;;CAKA;CAEA,YACE,QACA,QACA,SACA;EACA,MAAM,iBAAiB,OAAO,IAAI,UAAU,OAAO;EACnD,KAAK,SAAS;EACd,KAAK,SAAS;EACd,KAAK,YAAY,SAAS,aAAa;CACzC;AACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DesiredStatus } from "./build-state.mjs";
|
|
4
|
+
/** Inputs of {@link buildCommentMarkdown}. */
|
|
5
|
+
interface BuildCommentInput {
|
|
6
|
+
buildUrl: string;
|
|
7
|
+
/** Present once the Storybook is published. */
|
|
8
|
+
storybookUrl?: string | undefined;
|
|
9
|
+
/** The gating statuses (`testing` or `review`), in display order. */
|
|
10
|
+
gates: readonly DesiredStatus[];
|
|
11
|
+
/** Present when `testing` or review is on: the snapshot totals to summarize. */
|
|
12
|
+
counts?: {
|
|
13
|
+
snapshotCount: number;
|
|
14
|
+
changedCount: number;
|
|
15
|
+
approvedCount: number;
|
|
16
|
+
rejectedCount: number;
|
|
17
|
+
} | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** Comment body (below the idempotency marker): links to the build, the Storybook and a summary. */
|
|
20
|
+
declare function buildCommentMarkdown(input: BuildCommentInput): string;
|
|
21
|
+
export { BuildCommentInput, buildCommentMarkdown };
|
|
22
|
+
//# sourceMappingURL=build-comment.d.mts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/adapters/notifier/build-comment.ts
|
|
5
|
+
const LABEL = {
|
|
6
|
+
testing: "Visual tests",
|
|
7
|
+
review: "Review",
|
|
8
|
+
storybook: "Storybook"
|
|
9
|
+
};
|
|
10
|
+
/** Comment body (below the idempotency marker): links to the build, the Storybook and a summary. */
|
|
11
|
+
function buildCommentMarkdown(input) {
|
|
12
|
+
const lines = [`**StoryShelf** — [View build](${input.buildUrl})`];
|
|
13
|
+
for (const gate of input.gates) lines.push(`- ${LABEL[gate.name]}: ${gate.description}`);
|
|
14
|
+
if (input.counts !== void 0 && input.counts.snapshotCount > 0) {
|
|
15
|
+
const { snapshotCount, changedCount, approvedCount, rejectedCount } = input.counts;
|
|
16
|
+
lines.push(`- Snapshots: ${String(snapshotCount)} total, ${String(changedCount)} changed, ${String(approvedCount)} approved, ${String(rejectedCount)} rejected`);
|
|
17
|
+
}
|
|
18
|
+
if (input.storybookUrl !== void 0) lines.push(`- Storybook: [Open the published Storybook](${input.storybookUrl})`);
|
|
19
|
+
return lines.join("\n");
|
|
20
|
+
}
|
|
21
|
+
export { buildCommentMarkdown };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=build-comment.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-comment.mjs","names":[],"sources":["../../../src/adapters/notifier/build-comment.ts"],"sourcesContent":["/** Markdown of the pull-request comment, derived from the same inputs as the statuses (ADR 0014, decision 6). */\nimport type { DesiredStatus } from \"./build-state.ts\";\n\n/** Inputs of {@link buildCommentMarkdown}. */\nexport interface BuildCommentInput {\n buildUrl: string;\n /** Present once the Storybook is published. */\n storybookUrl?: string | undefined;\n /** The gating statuses (`testing` or `review`), in display order. */\n gates: readonly DesiredStatus[];\n /** Present when `testing` or review is on: the snapshot totals to summarize. */\n counts?:\n | {\n snapshotCount: number;\n changedCount: number;\n approvedCount: number;\n rejectedCount: number;\n }\n | undefined;\n}\n\nconst LABEL: Record<DesiredStatus[\"name\"], string> = {\n testing: \"Visual tests\",\n review: \"Review\",\n storybook: \"Storybook\",\n};\n\n/** Comment body (below the idempotency marker): links to the build, the Storybook and a summary. */\nexport function buildCommentMarkdown(input: BuildCommentInput): string {\n const lines = [`**StoryShelf** — [View build](${input.buildUrl})`];\n for (const gate of input.gates) {\n lines.push(`- ${LABEL[gate.name]}: ${gate.description}`);\n }\n if (input.counts !== undefined && input.counts.snapshotCount > 0) {\n const { snapshotCount, changedCount, approvedCount, rejectedCount } = input.counts;\n lines.push(\n `- Snapshots: ${String(snapshotCount)} total, ${String(changedCount)} changed, ${String(approvedCount)} approved, ${String(rejectedCount)} rejected`,\n );\n }\n if (input.storybookUrl !== undefined) {\n lines.push(`- Storybook: [Open the published Storybook](${input.storybookUrl})`);\n }\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;AAqBA,MAAM,QAA+C;CACnD,SAAS;CACT,QAAQ;CACR,WAAW;AACb;;AAGA,SAAgB,qBAAqB,OAAkC;CACrE,MAAM,QAAQ,CAAC,iCAAiC,MAAM,SAAS,EAAE;CACjE,KAAK,MAAM,QAAQ,MAAM,OACvB,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,aAAa;CAEzD,IAAI,MAAM,WAAW,KAAA,KAAa,MAAM,OAAO,gBAAgB,GAAG;EAChE,MAAM,EAAE,eAAe,cAAc,eAAe,kBAAkB,MAAM;EAC5E,MAAM,KACJ,gBAAgB,OAAO,aAAa,EAAE,UAAU,OAAO,YAAY,EAAE,YAAY,OAAO,aAAa,EAAE,aAAa,OAAO,aAAa,EAAE,UAC5I;CACF;CACA,IAAI,MAAM,iBAAiB,KAAA,GACzB,MAAM,KAAK,+CAA+C,MAAM,aAAa,EAAE;CAEjF,OAAO,MAAM,KAAK,IAAI;AACxB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { NotifierState, StateAnnotation } from "./types.mjs";
|
|
4
|
+
import { UrlBuilder } from "../../urls.mjs";
|
|
5
|
+
/** Most per-snapshot annotations a build state carries; the rest are counted (`omitted`). */
|
|
6
|
+
declare const MAX_ANNOTATIONS = 200;
|
|
7
|
+
/** Names of the statuses below a channel's prefix. */
|
|
8
|
+
type StatusName = "testing" | "review" | "storybook";
|
|
9
|
+
/** How publishing the build's Storybook stands. */
|
|
10
|
+
type PublishingState = "pending" | "success" | "failure";
|
|
11
|
+
/** What decides which statuses exist (ADR 0014, decision 5). */
|
|
12
|
+
interface BuildStateFlags {
|
|
13
|
+
/** `testing` is on: `<prefix>/testing` is the merge gate. */
|
|
14
|
+
testing: boolean;
|
|
15
|
+
/** Review is on for the project: with `testing` off, `<prefix>/review` is the gate. */
|
|
16
|
+
review: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** The part of a build row the function reads. */
|
|
19
|
+
interface BuildStateBuild {
|
|
20
|
+
id: string;
|
|
21
|
+
gitSha: string;
|
|
22
|
+
/** Build status: `pending`, `capturing`, `comparing`, `reviewing`, `approved`, `rejected`, `failed`, `cancelled`. */
|
|
23
|
+
status: string;
|
|
24
|
+
snapshotCount: number;
|
|
25
|
+
changedCount: number;
|
|
26
|
+
approvedCount: number;
|
|
27
|
+
rejectedCount: number;
|
|
28
|
+
}
|
|
29
|
+
/** The part of a snapshot row the annotations read. */
|
|
30
|
+
interface BuildStateChange {
|
|
31
|
+
id: string;
|
|
32
|
+
/** `changed` or `new`; anything else is not a change to review. */
|
|
33
|
+
status: string;
|
|
34
|
+
storyTitle: string;
|
|
35
|
+
storyName: string;
|
|
36
|
+
storyImportPath: string | null;
|
|
37
|
+
viewportName: string;
|
|
38
|
+
browser?: string | undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Inputs of {@link statusesForBuild}. */
|
|
41
|
+
interface BuildStateInput {
|
|
42
|
+
build: BuildStateBuild;
|
|
43
|
+
projectSlug: string;
|
|
44
|
+
/** The channel's status-name prefix, without a trailing slash. */
|
|
45
|
+
prefix: string;
|
|
46
|
+
/**
|
|
47
|
+
* Absolute links (`createUrlBuilder(publicOrigin)`). A build's state is only ever shown once a
|
|
48
|
+
* public origin is resolved (ADR 0014, decision 11), so every status links and the comment exists.
|
|
49
|
+
*/
|
|
50
|
+
urls: Pick<UrlBuilder, "build" | "storybookBuild" | "snapshot">;
|
|
51
|
+
flags: BuildStateFlags;
|
|
52
|
+
publishing: PublishingState;
|
|
53
|
+
/**
|
|
54
|
+
* Approval progress of the build-level review: the approvals among each reviewer's latest
|
|
55
|
+
* verdict and the approvals the project requires. Shown on `<prefix>/review` while it waits.
|
|
56
|
+
*/
|
|
57
|
+
approvals?: {
|
|
58
|
+
given: number;
|
|
59
|
+
required: number;
|
|
60
|
+
} | undefined;
|
|
61
|
+
/** The build's snapshots; the `changed` and `new` ones become annotations of `<prefix>/testing`. */
|
|
62
|
+
changes?: readonly BuildStateChange[] | undefined;
|
|
63
|
+
}
|
|
64
|
+
/** One commit status to show. */
|
|
65
|
+
interface DesiredStatus {
|
|
66
|
+
name: StatusName;
|
|
67
|
+
/** Full name on the host, `<prefix>/<name>`. */
|
|
68
|
+
context: string;
|
|
69
|
+
state: NotifierState;
|
|
70
|
+
description: string;
|
|
71
|
+
/** What the status links to: the build page, or the published Storybook for `storybook`. */
|
|
72
|
+
url: string;
|
|
73
|
+
/** True for the Storybook status, which is never a gate. */
|
|
74
|
+
informational?: boolean;
|
|
75
|
+
/** Set on a `pending` status: `queued` before capture starts, else `running`. */
|
|
76
|
+
progress?: "queued" | "running";
|
|
77
|
+
/** Per-snapshot findings (only `testing`), at most {@link MAX_ANNOTATIONS}. */
|
|
78
|
+
annotations?: StateAnnotation[];
|
|
79
|
+
/** Changes beyond the cap. */
|
|
80
|
+
omitted?: number;
|
|
81
|
+
}
|
|
82
|
+
/** The pull-request comment to show. */
|
|
83
|
+
interface DesiredComment {
|
|
84
|
+
/** The build page; it keys the comment, one per build. */
|
|
85
|
+
url: string;
|
|
86
|
+
markdown: string;
|
|
87
|
+
state: NotifierState;
|
|
88
|
+
}
|
|
89
|
+
/** Everything a channel should show for a build. */
|
|
90
|
+
interface BuildStateSet {
|
|
91
|
+
statuses: DesiredStatus[];
|
|
92
|
+
comment: DesiredComment | null;
|
|
93
|
+
}
|
|
94
|
+
/** Statuses and comment for a build; empty without a real commit (no SHA or a local identity). */
|
|
95
|
+
declare function statusesForBuild(input: BuildStateInput): BuildStateSet;
|
|
96
|
+
export { BuildStateBuild, BuildStateChange, BuildStateFlags, BuildStateInput, BuildStateSet, DesiredComment, DesiredStatus, MAX_ANNOTATIONS, PublishingState, StatusName, statusesForBuild };
|
|
97
|
+
//# sourceMappingURL=build-state.d.mts.map
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { buildCommentMarkdown } from "./build-comment.mjs";
|
|
5
|
+
import { LOCAL_SHA_PREFIX } from "@storyshelf/affected";
|
|
6
|
+
// src/adapters/notifier/build-state.ts
|
|
7
|
+
/**
|
|
8
|
+
* The states a build's git channels show, as one pure function of the build (ADR 0014, decision 5).
|
|
9
|
+
* It reads no clock, database or provider: callers hand it the build, the channel's prefix and the
|
|
10
|
+
* flags, and write the result to the host. Every transition and the end of publishing call it
|
|
11
|
+
* again, so a build that was never captured still gets its statuses and a repeated call changes
|
|
12
|
+
* nothing.
|
|
13
|
+
*/
|
|
14
|
+
/** Most per-snapshot annotations a build state carries; the rest are counted (`omitted`). */
|
|
15
|
+
const MAX_ANNOTATIONS = 200;
|
|
16
|
+
/** Statuses and comment for a build; empty without a real commit (no SHA or a local identity). */
|
|
17
|
+
function statusesForBuild(input) {
|
|
18
|
+
const { build } = input;
|
|
19
|
+
if (build.gitSha.length === 0 || build.gitSha.startsWith(LOCAL_SHA_PREFIX)) return {
|
|
20
|
+
statuses: [],
|
|
21
|
+
comment: null
|
|
22
|
+
};
|
|
23
|
+
const links = linksOf(input);
|
|
24
|
+
const statuses = [...withAnnotations(gateStatus(input, links.build), input), storybookStatus(input.publishing, input.prefix, links)].map((status) => withProgress(status, input.build));
|
|
25
|
+
return {
|
|
26
|
+
statuses,
|
|
27
|
+
comment: commentOf(input, statuses, links)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** `pending` is `queued` while the build waits to be captured, `running` after. */
|
|
31
|
+
function withProgress(status, build) {
|
|
32
|
+
if (status.state !== "pending") return status;
|
|
33
|
+
const queued = status.name !== "storybook" && build.status === "pending";
|
|
34
|
+
return {
|
|
35
|
+
...status,
|
|
36
|
+
progress: queued ? "queued" : "running"
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** One annotation per changed snapshot, on the `testing` gate. */
|
|
40
|
+
function withAnnotations(gates, input) {
|
|
41
|
+
const changed = (input.changes ?? []).filter((c) => c.status === "changed" || c.status === "new");
|
|
42
|
+
if (changed.length === 0) return gates;
|
|
43
|
+
const annotations = changed.slice(0, 200).map((change) => annotationOf(change, input));
|
|
44
|
+
const omitted = changed.length - annotations.length;
|
|
45
|
+
return gates.map((gate) => gate.name === "testing" ? {
|
|
46
|
+
...gate,
|
|
47
|
+
annotations,
|
|
48
|
+
...omitted > 0 ? { omitted } : {}
|
|
49
|
+
} : gate);
|
|
50
|
+
}
|
|
51
|
+
function annotationOf(change, input) {
|
|
52
|
+
const where = [change.viewportName, change.browser].filter(Boolean).join(", ");
|
|
53
|
+
const isNew = change.status === "new";
|
|
54
|
+
const name = `${change.storyTitle} / ${change.storyName}`;
|
|
55
|
+
return {
|
|
56
|
+
path: change.storyImportPath?.replace(/^(?:\.\/)+/u, "") ?? ".storybook",
|
|
57
|
+
title: where === "" ? name : `${name} (${where})`,
|
|
58
|
+
message: `${isNew ? "New snapshot" : "Visual change"}: review it at ${input.urls.snapshot(input.projectSlug, input.build.id, change.id)}`,
|
|
59
|
+
url: input.urls.snapshot(input.projectSlug, input.build.id, change.id),
|
|
60
|
+
level: isNew ? "notice" : "warning"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function commentOf(input, statuses, links) {
|
|
64
|
+
const gates = statuses.filter((status) => status.name !== "storybook");
|
|
65
|
+
return {
|
|
66
|
+
url: links.build,
|
|
67
|
+
state: gates[0]?.state ?? "success",
|
|
68
|
+
markdown: buildCommentMarkdown({
|
|
69
|
+
buildUrl: links.build,
|
|
70
|
+
storybookUrl: input.publishing === "success" ? links.storybook : void 0,
|
|
71
|
+
gates,
|
|
72
|
+
counts: input.flags.testing || input.flags.review ? input.build : void 0
|
|
73
|
+
})
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** The links to show. */
|
|
77
|
+
function linksOf(input) {
|
|
78
|
+
const { urls, projectSlug, build } = input;
|
|
79
|
+
return {
|
|
80
|
+
build: urls.build(projectSlug, build.id),
|
|
81
|
+
storybook: `${urls.storybookBuild(projectSlug, build.id).replace(/\/+$/u, "")}/`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** `testing` when it is on; `review` when only review is on; none for a hosting-only build. */
|
|
85
|
+
function gateStatus(input, url) {
|
|
86
|
+
const { flags, build, prefix } = input;
|
|
87
|
+
if (flags.testing) return [{
|
|
88
|
+
name: "testing",
|
|
89
|
+
context: `${prefix}/testing`,
|
|
90
|
+
url,
|
|
91
|
+
...testingOutcome(build)
|
|
92
|
+
}];
|
|
93
|
+
if (flags.review) return [{
|
|
94
|
+
name: "review",
|
|
95
|
+
context: `${prefix}/review`,
|
|
96
|
+
url,
|
|
97
|
+
...reviewOutcome(build, input.approvals)
|
|
98
|
+
}];
|
|
99
|
+
return reviewClosed(input, url);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Review is off and the build is accepted: a final `success`, so a `<prefix>/review` status left
|
|
103
|
+
* `pending` by the time review was on (the switch-off pass accepts such builds) does not stay on
|
|
104
|
+
* the pull request. The function sees no history, so every accepted build of a project with review
|
|
105
|
+
* off shows it, and a host that requires the status never waits for one that will not come.
|
|
106
|
+
*/
|
|
107
|
+
function reviewClosed(input, url) {
|
|
108
|
+
if (input.build.status !== "approved") return [];
|
|
109
|
+
const { prefix } = input;
|
|
110
|
+
return [{
|
|
111
|
+
name: "review",
|
|
112
|
+
context: `${prefix}/review`,
|
|
113
|
+
url,
|
|
114
|
+
state: "success",
|
|
115
|
+
description: "Review is off"
|
|
116
|
+
}];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A user cancelled the build (ADR 0006). It closes both gates the same way: the host shows
|
|
120
|
+
* `cancelled` where it has the state (GitLab `canceled`, GitHub `error`), so a required status does
|
|
121
|
+
* not wait for a result that will never come, and nothing says the build failed or was reviewed.
|
|
122
|
+
*/
|
|
123
|
+
const CANCELLED = {
|
|
124
|
+
state: "cancelled",
|
|
125
|
+
description: "Cancelled"
|
|
126
|
+
};
|
|
127
|
+
/** `pending` until captured, `pending` while review is open, then the review's result. */
|
|
128
|
+
function testingOutcome(build) {
|
|
129
|
+
switch (build.status) {
|
|
130
|
+
case "reviewing": return {
|
|
131
|
+
state: "pending",
|
|
132
|
+
description: `Review open: ${plural(openCount(build), "change")} to review`
|
|
133
|
+
};
|
|
134
|
+
case "approved": return {
|
|
135
|
+
state: "success",
|
|
136
|
+
description: approvedText(build)
|
|
137
|
+
};
|
|
138
|
+
case "rejected": return {
|
|
139
|
+
state: "failure",
|
|
140
|
+
description: `Review closed: ${plural(build.rejectedCount, "change")} rejected`
|
|
141
|
+
};
|
|
142
|
+
case "failed": return {
|
|
143
|
+
state: "failure",
|
|
144
|
+
description: "Capture failed"
|
|
145
|
+
};
|
|
146
|
+
case "cancelled": return CANCELLED;
|
|
147
|
+
default: return {
|
|
148
|
+
state: "pending",
|
|
149
|
+
description: "Capturing and comparing screenshots"
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** The build-level verdict: `pending` until given, then `success` or `failure`. */
|
|
154
|
+
function reviewOutcome(build, approvals) {
|
|
155
|
+
switch (build.status) {
|
|
156
|
+
case "approved": return {
|
|
157
|
+
state: "success",
|
|
158
|
+
description: "Build approved"
|
|
159
|
+
};
|
|
160
|
+
case "rejected": return {
|
|
161
|
+
state: "failure",
|
|
162
|
+
description: "Build rejected"
|
|
163
|
+
};
|
|
164
|
+
case "failed": return {
|
|
165
|
+
state: "failure",
|
|
166
|
+
description: "Build failed"
|
|
167
|
+
};
|
|
168
|
+
case "cancelled": return CANCELLED;
|
|
169
|
+
default: return {
|
|
170
|
+
state: "pending",
|
|
171
|
+
description: waitingText(approvals)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/** Informational: never a gate, linking to the published Storybook once there is one. */
|
|
176
|
+
function storybookStatus(publishing, prefix, links) {
|
|
177
|
+
const base = {
|
|
178
|
+
name: "storybook",
|
|
179
|
+
context: `${prefix}/storybook`,
|
|
180
|
+
informational: true
|
|
181
|
+
};
|
|
182
|
+
if (publishing === "success") return {
|
|
183
|
+
...base,
|
|
184
|
+
state: "success",
|
|
185
|
+
description: "Storybook published",
|
|
186
|
+
url: links.storybook
|
|
187
|
+
};
|
|
188
|
+
if (publishing === "failure") return {
|
|
189
|
+
...base,
|
|
190
|
+
state: "failure",
|
|
191
|
+
description: "Storybook could not be published",
|
|
192
|
+
url: links.build
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
...base,
|
|
196
|
+
state: "pending",
|
|
197
|
+
description: "Publishing Storybook",
|
|
198
|
+
url: links.build
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/** `1 of 2 approvals` when the project needs several; a single approval just waits for a verdict. */
|
|
202
|
+
function waitingText(approvals) {
|
|
203
|
+
if (approvals === void 0 || approvals.required <= 1) return "Waiting for a review verdict";
|
|
204
|
+
return `Waiting for approvals: ${String(approvals.given)} of ${String(approvals.required)}`;
|
|
205
|
+
}
|
|
206
|
+
function openCount(build) {
|
|
207
|
+
return Math.max(0, build.changedCount - build.approvedCount - build.rejectedCount);
|
|
208
|
+
}
|
|
209
|
+
function approvedText(build) {
|
|
210
|
+
return build.changedCount === 0 ? "Review closed: no visual changes" : `Review closed: ${plural(build.approvedCount, "change")} approved`;
|
|
211
|
+
}
|
|
212
|
+
function plural(count, noun) {
|
|
213
|
+
return `${String(count)} ${noun}${count === 1 ? "" : "s"}`;
|
|
214
|
+
}
|
|
215
|
+
export { MAX_ANNOTATIONS, statusesForBuild };
|
|
216
|
+
|
|
217
|
+
//# sourceMappingURL=build-state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-state.mjs","names":[],"sources":["../../../src/adapters/notifier/build-state.ts"],"sourcesContent":["/**\n * The states a build's git channels show, as one pure function of the build (ADR 0014, decision 5).\n * It reads no clock, database or provider: callers hand it the build, the channel's prefix and the\n * flags, and write the result to the host. Every transition and the end of publishing call it\n * again, so a build that was never captured still gets its statuses and a repeated call changes\n * nothing.\n */\nimport { LOCAL_SHA_PREFIX } from \"@storyshelf/affected\";\nimport type { UrlBuilder } from \"../../urls.ts\";\nimport { buildCommentMarkdown } from \"./build-comment.ts\";\nimport type { NotifierState, StateAnnotation } from \"./types.ts\";\n\n/** Most per-snapshot annotations a build state carries; the rest are counted (`omitted`). */\nexport const MAX_ANNOTATIONS = 200;\n\n/** Names of the statuses below a channel's prefix. */\nexport type StatusName = \"testing\" | \"review\" | \"storybook\";\n\n/** How publishing the build's Storybook stands. */\nexport type PublishingState = \"pending\" | \"success\" | \"failure\";\n\n/** What decides which statuses exist (ADR 0014, decision 5). */\nexport interface BuildStateFlags {\n /** `testing` is on: `<prefix>/testing` is the merge gate. */\n testing: boolean;\n /** Review is on for the project: with `testing` off, `<prefix>/review` is the gate. */\n review: boolean;\n}\n\n/** The part of a build row the function reads. */\nexport interface BuildStateBuild {\n id: string;\n gitSha: string;\n /** Build status: `pending`, `capturing`, `comparing`, `reviewing`, `approved`, `rejected`, `failed`, `cancelled`. */\n status: string;\n snapshotCount: number;\n changedCount: number;\n approvedCount: number;\n rejectedCount: number;\n}\n\n/** The part of a snapshot row the annotations read. */\nexport interface BuildStateChange {\n id: string;\n /** `changed` or `new`; anything else is not a change to review. */\n status: string;\n storyTitle: string;\n storyName: string;\n storyImportPath: string | null;\n viewportName: string;\n browser?: string | undefined;\n}\n\n/** Inputs of {@link statusesForBuild}. */\nexport interface BuildStateInput {\n build: BuildStateBuild;\n projectSlug: string;\n /** The channel's status-name prefix, without a trailing slash. */\n prefix: string;\n /**\n * Absolute links (`createUrlBuilder(publicOrigin)`). A build's state is only ever shown once a\n * public origin is resolved (ADR 0014, decision 11), so every status links and the comment exists.\n */\n urls: Pick<UrlBuilder, \"build\" | \"storybookBuild\" | \"snapshot\">;\n flags: BuildStateFlags;\n publishing: PublishingState;\n /**\n * Approval progress of the build-level review: the approvals among each reviewer's latest\n * verdict and the approvals the project requires. Shown on `<prefix>/review` while it waits.\n */\n approvals?: { given: number; required: number } | undefined;\n /** The build's snapshots; the `changed` and `new` ones become annotations of `<prefix>/testing`. */\n changes?: readonly BuildStateChange[] | undefined;\n}\n\n/** One commit status to show. */\nexport interface DesiredStatus {\n name: StatusName;\n /** Full name on the host, `<prefix>/<name>`. */\n context: string;\n state: NotifierState;\n description: string;\n /** What the status links to: the build page, or the published Storybook for `storybook`. */\n url: string;\n /** True for the Storybook status, which is never a gate. */\n informational?: boolean;\n /** Set on a `pending` status: `queued` before capture starts, else `running`. */\n progress?: \"queued\" | \"running\";\n /** Per-snapshot findings (only `testing`), at most {@link MAX_ANNOTATIONS}. */\n annotations?: StateAnnotation[];\n /** Changes beyond the cap. */\n omitted?: number;\n}\n\n/** The pull-request comment to show. */\nexport interface DesiredComment {\n /** The build page; it keys the comment, one per build. */\n url: string;\n markdown: string;\n state: NotifierState;\n}\n\n/** Everything a channel should show for a build. */\nexport interface BuildStateSet {\n statuses: DesiredStatus[];\n comment: DesiredComment | null;\n}\n\n/** Statuses and comment for a build; empty without a real commit (no SHA or a local identity). */\nexport function statusesForBuild(input: BuildStateInput): BuildStateSet {\n const { build } = input;\n if (build.gitSha.length === 0 || build.gitSha.startsWith(LOCAL_SHA_PREFIX)) {\n return { statuses: [], comment: null };\n }\n const links = linksOf(input);\n const statuses = [\n ...withAnnotations(gateStatus(input, links.build), input),\n storybookStatus(input.publishing, input.prefix, links),\n ].map((status) => withProgress(status, input.build));\n return { statuses, comment: commentOf(input, statuses, links) };\n}\n\n/** `pending` is `queued` while the build waits to be captured, `running` after. */\nfunction withProgress(status: DesiredStatus, build: BuildStateBuild): DesiredStatus {\n if (status.state !== \"pending\") {\n return status;\n }\n const queued = status.name !== \"storybook\" && build.status === \"pending\";\n return { ...status, progress: queued ? \"queued\" : \"running\" };\n}\n\n/** One annotation per changed snapshot, on the `testing` gate. */\nfunction withAnnotations(gates: DesiredStatus[], input: BuildStateInput): DesiredStatus[] {\n const changed = (input.changes ?? []).filter((c) => c.status === \"changed\" || c.status === \"new\");\n if (changed.length === 0) {\n return gates;\n }\n const annotations = changed\n .slice(0, MAX_ANNOTATIONS)\n .map((change) => annotationOf(change, input));\n const omitted = changed.length - annotations.length;\n return gates.map((gate) =>\n gate.name === \"testing\" ? { ...gate, annotations, ...(omitted > 0 ? { omitted } : {}) } : gate,\n );\n}\n\nfunction annotationOf(change: BuildStateChange, input: BuildStateInput): StateAnnotation {\n const where = [change.viewportName, change.browser].filter(Boolean).join(\", \");\n const isNew = change.status === \"new\";\n const name = `${change.storyTitle} / ${change.storyName}`;\n return {\n path: change.storyImportPath?.replace(/^(?:\\.\\/)+/u, \"\") ?? \".storybook\",\n title: where === \"\" ? name : `${name} (${where})`,\n message: `${isNew ? \"New snapshot\" : \"Visual change\"}: review it at ${input.urls.snapshot(input.projectSlug, input.build.id, change.id)}`,\n url: input.urls.snapshot(input.projectSlug, input.build.id, change.id),\n level: isNew ? \"notice\" : \"warning\",\n };\n}\n\nfunction commentOf(\n input: BuildStateInput,\n statuses: DesiredStatus[],\n links: Links,\n): DesiredComment {\n const gates = statuses.filter((status) => status.name !== \"storybook\");\n return {\n url: links.build,\n state: gates[0]?.state ?? \"success\",\n markdown: buildCommentMarkdown({\n buildUrl: links.build,\n storybookUrl: input.publishing === \"success\" ? links.storybook : undefined,\n gates,\n counts: input.flags.testing || input.flags.review ? input.build : undefined,\n }),\n };\n}\n\ninterface Links {\n build: string;\n storybook: string;\n}\n\n/** The links to show. */\nfunction linksOf(input: BuildStateInput): Links {\n const { urls, projectSlug, build } = input;\n return {\n build: urls.build(projectSlug, build.id),\n storybook: `${urls.storybookBuild(projectSlug, build.id).replace(/\\/+$/u, \"\")}/`,\n };\n}\n\n/** `testing` when it is on; `review` when only review is on; none for a hosting-only build. */\nfunction gateStatus(input: BuildStateInput, url: string): DesiredStatus[] {\n const { flags, build, prefix } = input;\n if (flags.testing) {\n return [{ name: \"testing\", context: `${prefix}/testing`, url, ...testingOutcome(build) }];\n }\n if (flags.review) {\n return [\n {\n name: \"review\",\n context: `${prefix}/review`,\n url,\n ...reviewOutcome(build, input.approvals),\n },\n ];\n }\n return reviewClosed(input, url);\n}\n\n/**\n * Review is off and the build is accepted: a final `success`, so a `<prefix>/review` status left\n * `pending` by the time review was on (the switch-off pass accepts such builds) does not stay on\n * the pull request. The function sees no history, so every accepted build of a project with review\n * off shows it, and a host that requires the status never waits for one that will not come.\n */\nfunction reviewClosed(input: BuildStateInput, url: string): DesiredStatus[] {\n if (input.build.status !== \"approved\") {\n return [];\n }\n const { prefix } = input;\n return [\n {\n name: \"review\",\n context: `${prefix}/review`,\n url,\n state: \"success\",\n description: \"Review is off\",\n },\n ];\n}\n\ntype Outcome = Pick<DesiredStatus, \"state\" | \"description\">;\n\n/**\n * A user cancelled the build (ADR 0006). It closes both gates the same way: the host shows\n * `cancelled` where it has the state (GitLab `canceled`, GitHub `error`), so a required status does\n * not wait for a result that will never come, and nothing says the build failed or was reviewed.\n */\nconst CANCELLED: Outcome = { state: \"cancelled\", description: \"Cancelled\" };\n\n/** `pending` until captured, `pending` while review is open, then the review's result. */\nfunction testingOutcome(build: BuildStateBuild): Outcome {\n switch (build.status) {\n case \"reviewing\": {\n return {\n state: \"pending\",\n description: `Review open: ${plural(openCount(build), \"change\")} to review`,\n };\n }\n case \"approved\": {\n return { state: \"success\", description: approvedText(build) };\n }\n case \"rejected\": {\n return {\n state: \"failure\",\n description: `Review closed: ${plural(build.rejectedCount, \"change\")} rejected`,\n };\n }\n case \"failed\": {\n return { state: \"failure\", description: \"Capture failed\" };\n }\n case \"cancelled\": {\n return CANCELLED;\n }\n default: {\n return { state: \"pending\", description: \"Capturing and comparing screenshots\" };\n }\n }\n}\n\n/** The build-level verdict: `pending` until given, then `success` or `failure`. */\nfunction reviewOutcome(build: BuildStateBuild, approvals: BuildStateInput[\"approvals\"]): Outcome {\n switch (build.status) {\n case \"approved\": {\n return { state: \"success\", description: \"Build approved\" };\n }\n case \"rejected\": {\n return { state: \"failure\", description: \"Build rejected\" };\n }\n case \"failed\": {\n return { state: \"failure\", description: \"Build failed\" };\n }\n case \"cancelled\": {\n return CANCELLED;\n }\n default: {\n return { state: \"pending\", description: waitingText(approvals) };\n }\n }\n}\n\n/** Informational: never a gate, linking to the published Storybook once there is one. */\nfunction storybookStatus(publishing: PublishingState, prefix: string, links: Links): DesiredStatus {\n const base = { name: \"storybook\", context: `${prefix}/storybook`, informational: true } as const;\n if (publishing === \"success\") {\n return {\n ...base,\n state: \"success\",\n description: \"Storybook published\",\n url: links.storybook,\n };\n }\n if (publishing === \"failure\") {\n return {\n ...base,\n state: \"failure\",\n description: \"Storybook could not be published\",\n url: links.build,\n };\n }\n return { ...base, state: \"pending\", description: \"Publishing Storybook\", url: links.build };\n}\n\n/** `1 of 2 approvals` when the project needs several; a single approval just waits for a verdict. */\nfunction waitingText(approvals: BuildStateInput[\"approvals\"]): string {\n if (approvals === undefined || approvals.required <= 1) {\n return \"Waiting for a review verdict\";\n }\n return `Waiting for approvals: ${String(approvals.given)} of ${String(approvals.required)}`;\n}\n\nfunction openCount(build: BuildStateBuild): number {\n return Math.max(0, build.changedCount - build.approvedCount - build.rejectedCount);\n}\n\nfunction approvedText(build: BuildStateBuild): string {\n return build.changedCount === 0\n ? \"Review closed: no visual changes\"\n : `Review closed: ${plural(build.approvedCount, \"change\")} approved`;\n}\n\nfunction plural(count: number, noun: string): string {\n return `${String(count)} ${noun}${count === 1 ? \"\" : \"s\"}`;\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
import { NotificationBrand, NotificationChannel, NotificationEvent, SystemNotification } from "./types.mjs";
|
|
4
|
-
import { NotifierProvider } from "./provider.mjs";
|
|
5
3
|
import { Logger } from "../../logger.mjs";
|
|
6
|
-
|
|
4
|
+
import { ChannelOutcome, NotificationBrand, NotificationChannel, NotificationEvent, SystemNotification } from "./types.mjs";
|
|
5
|
+
import { NotifierProvider } from "./provider.mjs";
|
|
7
6
|
/** Options for project-event fan-out (inline best-effort, non-fatal). */
|
|
8
7
|
interface EmitNotificationsOptions {
|
|
9
8
|
notifiers?: NotifierProvider[];
|
|
10
9
|
channels?: NotificationChannel[];
|
|
11
10
|
brand?: NotificationBrand;
|
|
12
11
|
logger?: Logger;
|
|
12
|
+
/** Called once per attempted channel so the host can record or clear its last error. */
|
|
13
|
+
onOutcome?: (outcome: ChannelOutcome) => Promise<void> | void;
|
|
13
14
|
}
|
|
14
15
|
/**
|
|
15
16
|
* Deliver a project event to every subscribed channel.
|
|
@@ -21,6 +22,5 @@ declare function emitNotifications(event: NotificationEvent, options?: EmitNotif
|
|
|
21
22
|
* (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).
|
|
22
23
|
*/
|
|
23
24
|
declare function emitSystemNotification(event: SystemNotification, options?: EmitNotificationsOptions): Promise<void>;
|
|
24
|
-
//#endregion
|
|
25
25
|
export { EmitNotificationsOptions, emitNotifications, emitSystemNotification };
|
|
26
26
|
//# sourceMappingURL=events.d.mts.map
|