@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
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { sanitizeErrorText } from "../../utils/redact.mjs";
|
|
4
5
|
import { formatNotification, formatSystemNotification } from "./format.mjs";
|
|
5
|
-
|
|
6
|
+
import { isStateProvider } from "./provider.mjs";
|
|
7
|
+
// src/adapters/notifier/events.ts
|
|
6
8
|
/** Check an event against a channel's allowlist (empty = all). */
|
|
7
9
|
function subscribed(channel, event) {
|
|
8
10
|
if (!channel.enabled) return false;
|
|
9
11
|
return channel.events.length === 0 || channel.events.includes(event);
|
|
10
12
|
}
|
|
13
|
+
/** `state` channels (git hosts) follow build state, never the message fan-out. */
|
|
14
|
+
function isMessageChannel(notifiers, channel) {
|
|
15
|
+
const provider = providerFor(notifiers, channel.provider);
|
|
16
|
+
return provider === void 0 || !isStateProvider(provider);
|
|
17
|
+
}
|
|
11
18
|
/** Resolve a provider for a channel kind, or undefined when unwired. */
|
|
12
19
|
function providerFor(notifiers, kind) {
|
|
13
20
|
return notifiers?.find((candidate) => candidate.metadata.kind === kind);
|
|
@@ -16,6 +23,7 @@ function providerFor(notifiers, kind) {
|
|
|
16
23
|
async function deliver(notifiers, channel, formatted) {
|
|
17
24
|
const provider = providerFor(notifiers, channel.provider);
|
|
18
25
|
if (!provider) throw new Error(`notifier missing: ${channel.provider}`);
|
|
26
|
+
if (isStateProvider(provider)) throw new Error(`notifier ${channel.provider} delivers state, not messages`);
|
|
19
27
|
await provider.create({
|
|
20
28
|
config: channel.config,
|
|
21
29
|
secret: channel.secret
|
|
@@ -24,22 +32,33 @@ async function deliver(notifiers, channel, formatted) {
|
|
|
24
32
|
formatted
|
|
25
33
|
});
|
|
26
34
|
}
|
|
35
|
+
/** Deliver to one channel, report the outcome and swallow the failure (logged). */
|
|
36
|
+
async function deliverReported(options, channel, formatted, failure) {
|
|
37
|
+
let problem;
|
|
38
|
+
try {
|
|
39
|
+
await deliver(options.notifiers, channel, formatted);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
options.logger?.warn({
|
|
42
|
+
err: error,
|
|
43
|
+
channelId: channel.id
|
|
44
|
+
}, failure);
|
|
45
|
+
problem = sanitizeErrorText(error instanceof Error ? error.message : String(error), 500);
|
|
46
|
+
}
|
|
47
|
+
await options.onOutcome?.({
|
|
48
|
+
channelId: channel.id,
|
|
49
|
+
...problem === void 0 ? {} : { error: problem }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
27
52
|
/**
|
|
28
53
|
* Deliver a project event to every subscribed channel.
|
|
29
54
|
* Inline best-effort: `Promise.allSettled`, failures logged and swallowed.
|
|
30
55
|
*/
|
|
31
56
|
async function emitNotifications(event, options = {}) {
|
|
32
|
-
const targets = (options.channels ?? []).filter((channel) => subscribed(channel, event.event));
|
|
57
|
+
const targets = (options.channels ?? []).filter((channel) => subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel));
|
|
33
58
|
if (targets.length === 0) return;
|
|
59
|
+
const formatted = formatNotification(event, options.brand);
|
|
34
60
|
await Promise.allSettled(targets.map(async (channel) => {
|
|
35
|
-
|
|
36
|
-
await deliver(options.notifiers, channel, formatNotification(event, options.brand));
|
|
37
|
-
} catch (error) {
|
|
38
|
-
options.logger?.warn({
|
|
39
|
-
err: error,
|
|
40
|
-
channelId: channel.id
|
|
41
|
-
}, "notification failed");
|
|
42
|
-
}
|
|
61
|
+
await deliverReported(options, channel, formatted, "notification failed");
|
|
43
62
|
}));
|
|
44
63
|
}
|
|
45
64
|
/**
|
|
@@ -47,20 +66,13 @@ async function emitNotifications(event, options = {}) {
|
|
|
47
66
|
* (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).
|
|
48
67
|
*/
|
|
49
68
|
async function emitSystemNotification(event, options = {}) {
|
|
50
|
-
const targets = (options.channels ?? []).filter((channel) => channel.projectId === null && subscribed(channel, event.event));
|
|
69
|
+
const targets = (options.channels ?? []).filter((channel) => channel.projectId === null && subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel));
|
|
51
70
|
if (targets.length === 0) return;
|
|
71
|
+
const formatted = formatSystemNotification(event, options.brand);
|
|
52
72
|
await Promise.allSettled(targets.map(async (channel) => {
|
|
53
|
-
|
|
54
|
-
await deliver(options.notifiers, channel, formatSystemNotification(event, options.brand));
|
|
55
|
-
} catch (error) {
|
|
56
|
-
options.logger?.warn({
|
|
57
|
-
err: error,
|
|
58
|
-
channelId: channel.id
|
|
59
|
-
}, "system notification failed");
|
|
60
|
-
}
|
|
73
|
+
await deliverReported(options, channel, formatted, "system notification failed");
|
|
61
74
|
}));
|
|
62
75
|
}
|
|
63
|
-
//#endregion
|
|
64
76
|
export { emitNotifications, emitSystemNotification };
|
|
65
77
|
|
|
66
78
|
//# sourceMappingURL=events.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.mjs","names":[],"sources":["../../../src/adapters/notifier/events.ts"],"sourcesContent":["import type { Logger } from \"../../logger.ts\";\nimport { formatNotification, formatSystemNotification } from \"./format.ts\";\nimport type
|
|
1
|
+
{"version":3,"file":"events.mjs","names":[],"sources":["../../../src/adapters/notifier/events.ts"],"sourcesContent":["import type { Logger } from \"../../logger.ts\";\nimport { sanitizeErrorText } from \"../../utils/redact.ts\";\nimport { formatNotification, formatSystemNotification } from \"./format.ts\";\nimport { isStateProvider, type NotifierProvider } from \"./provider.ts\";\nimport type {\n ChannelOutcome,\n NotificationBrand,\n NotificationChannel,\n NotificationEvent,\n SystemNotification,\n} from \"./types.ts\";\n\n/** Options for project-event fan-out (inline best-effort, non-fatal). */\nexport interface EmitNotificationsOptions {\n notifiers?: NotifierProvider[];\n channels?: NotificationChannel[];\n brand?: NotificationBrand;\n logger?: Logger;\n /** Called once per attempted channel so the host can record or clear its last error. */\n onOutcome?: (outcome: ChannelOutcome) => Promise<void> | void;\n}\n\n/** Check an event against a channel's allowlist (empty = all). */\nfunction subscribed(channel: NotificationChannel, event: string): boolean {\n if (!channel.enabled) {\n return false;\n }\n return channel.events.length === 0 || channel.events.includes(event);\n}\n\n/** `state` channels (git hosts) follow build state, never the message fan-out. */\nfunction isMessageChannel(\n notifiers: NotifierProvider[] | undefined,\n channel: NotificationChannel,\n): boolean {\n const provider = providerFor(notifiers, channel.provider);\n return provider === undefined || !isStateProvider(provider);\n}\n\n/** Resolve a provider for a channel kind, or undefined when unwired. */\nfunction providerFor(\n notifiers: NotifierProvider[] | undefined,\n kind: string,\n): NotifierProvider | undefined {\n return notifiers?.find((candidate) => candidate.metadata.kind === kind);\n}\n\n/** Send one formatted event through a channel's provider (throws on failure). */\nasync function deliver(\n notifiers: NotifierProvider[] | undefined,\n channel: NotificationChannel,\n formatted: ReturnType<typeof formatNotification>,\n): Promise<void> {\n const provider = providerFor(notifiers, channel.provider);\n if (!provider) {\n throw new Error(`notifier missing: ${channel.provider}`);\n }\n if (isStateProvider(provider)) {\n throw new Error(`notifier ${channel.provider} delivers state, not messages`);\n }\n const sender = provider.create({ config: channel.config, secret: channel.secret });\n await sender.send({ channel, formatted });\n}\n\n/** Deliver to one channel, report the outcome and swallow the failure (logged). */\nasync function deliverReported(\n options: EmitNotificationsOptions,\n channel: NotificationChannel,\n formatted: ReturnType<typeof formatNotification>,\n failure: string,\n): Promise<void> {\n let problem: string | undefined;\n try {\n await deliver(options.notifiers, channel, formatted);\n } catch (error) {\n options.logger?.warn({ err: error, channelId: channel.id }, failure);\n problem = sanitizeErrorText(error instanceof Error ? error.message : String(error), 500);\n }\n await options.onOutcome?.({\n channelId: channel.id,\n ...(problem === undefined ? {} : { error: problem }),\n });\n}\n\n/**\n * Deliver a project event to every subscribed channel.\n * Inline best-effort: `Promise.allSettled`, failures logged and swallowed.\n */\nexport async function emitNotifications(\n event: NotificationEvent,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter(\n (channel) => subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel),\n );\n if (targets.length === 0) {\n return;\n }\n const formatted = formatNotification(event, options.brand);\n await Promise.allSettled(\n targets.map(async (channel) => {\n await deliverReported(options, channel, formatted, \"notification failed\");\n }),\n );\n}\n\n/**\n * Deliver a site-wide admin alert to project-less channels\n * (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).\n */\nexport async function emitSystemNotification(\n event: SystemNotification,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter(\n (channel) =>\n channel.projectId === null &&\n subscribed(channel, event.event) &&\n isMessageChannel(options.notifiers, channel),\n );\n if (targets.length === 0) {\n return;\n }\n const formatted = formatSystemNotification(event, options.brand);\n await Promise.allSettled(\n targets.map(async (channel) => {\n await deliverReported(options, channel, formatted, \"system notification failed\");\n }),\n );\n}\n"],"mappings":";;;;;;;;AAuBA,SAAS,WAAW,SAA8B,OAAwB;CACxE,IAAI,CAAC,QAAQ,SACX,OAAO;CAET,OAAO,QAAQ,OAAO,WAAW,KAAK,QAAQ,OAAO,SAAS,KAAK;AACrE;;AAGA,SAAS,iBACP,WACA,SACS;CACT,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ;CACxD,OAAO,aAAa,KAAA,KAAa,CAAC,gBAAgB,QAAQ;AAC5D;;AAGA,SAAS,YACP,WACA,MAC8B;CAC9B,OAAO,WAAW,MAAM,cAAc,UAAU,SAAS,SAAS,IAAI;AACxE;;AAGA,eAAe,QACb,WACA,SACA,WACe;CACf,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ;CACxD,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,qBAAqB,QAAQ,UAAU;CAEzD,IAAI,gBAAgB,QAAQ,GAC1B,MAAM,IAAI,MAAM,YAAY,QAAQ,SAAS,8BAA8B;CAG7E,MADe,SAAS,OAAO;EAAE,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;CAAO,CACrE,CAAC,CAAC,KAAK;EAAE;EAAS;CAAU,CAAC;AAC1C;;AAGA,eAAe,gBACb,SACA,SACA,WACA,SACe;CACf,IAAI;CACJ,IAAI;EACF,MAAM,QAAQ,QAAQ,WAAW,SAAS,SAAS;CACrD,SAAS,OAAO;EACd,QAAQ,QAAQ,KAAK;GAAE,KAAK;GAAO,WAAW,QAAQ;EAAG,GAAG,OAAO;EACnE,UAAU,kBAAkB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,GAAG;CACzF;CACA,MAAM,QAAQ,YAAY;EACxB,WAAW,QAAQ;EACnB,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ;CACpD,CAAC;AACH;;;;;AAMA,eAAsB,kBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QACtC,YAAY,WAAW,SAAS,MAAM,KAAK,KAAK,iBAAiB,QAAQ,WAAW,OAAO,CAC9F;CACA,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,YAAY,mBAAmB,OAAO,QAAQ,KAAK;CACzD,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,MAAM,gBAAgB,SAAS,SAAS,WAAW,qBAAqB;CAC1E,CAAC,CACH;AACF;;;;;AAMA,eAAsB,uBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QACtC,YACC,QAAQ,cAAc,QACtB,WAAW,SAAS,MAAM,KAAK,KAC/B,iBAAiB,QAAQ,WAAW,OAAO,CAC/C;CACA,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,YAAY,yBAAyB,OAAO,QAAQ,KAAK;CAC/D,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,MAAM,gBAAgB,SAAS,SAAS,WAAW,4BAA4B;CACjF,CAAC,CACH;AACF"}
|
|
@@ -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 { ChannelToggles, FormattedNotification, NotificationBrand, NotificationEvent, SystemNotification } from "./types.mjs";
|
|
4
|
-
//#region src/adapters/notifier/format.d.ts
|
|
5
4
|
/**
|
|
6
5
|
* Format a project event into subject/text/markdown/html using brand +
|
|
7
6
|
* channel toggles. Pure (no I/O) so settings preview and senders share it.
|
|
@@ -9,6 +8,5 @@ import { ChannelToggles, FormattedNotification, NotificationBrand, NotificationE
|
|
|
9
8
|
declare function formatNotification(event: NotificationEvent, brand?: NotificationBrand, toggles?: ChannelToggles): FormattedNotification;
|
|
10
9
|
/** Format a site-wide admin alert (no project scope, always verbose). */
|
|
11
10
|
declare function formatSystemNotification(event: SystemNotification, brand?: NotificationBrand): FormattedNotification;
|
|
12
|
-
//#endregion
|
|
13
11
|
export { formatNotification, formatSystemNotification };
|
|
14
12
|
//# sourceMappingURL=format.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/adapters/notifier/format.ts
|
|
5
5
|
/** Escape HTML special chars in free-form values (commit messages, names). */
|
|
6
6
|
function esc(value) {
|
|
7
7
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -90,7 +90,6 @@ function formatSystemNotification(event, brand) {
|
|
|
90
90
|
subjectPrefix: "[Shelf sys]"
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
|
-
//#endregion
|
|
94
93
|
export { formatNotification, formatSystemNotification };
|
|
95
94
|
|
|
96
95
|
//# sourceMappingURL=format.mjs.map
|
|
@@ -1,32 +1,76 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
import { FormattedNotification, NotificationChannel } from "./types.mjs";
|
|
3
|
+
import { FormattedNotification, NotificationChannel, NotifierState, NotifierStateTarget } from "./types.mjs";
|
|
4
4
|
import { Adapter, AdapterMetadata } from "../../adapter/metadata.mjs";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { Logger } from "pino";
|
|
7
|
-
|
|
7
|
+
/** How a provider delivers: `message` sends once, `state` makes a host show a named state. */
|
|
8
|
+
type NotifierDelivery = "message" | "state";
|
|
8
9
|
/** Notifier-specific metadata (adds logo + config validation schema). */
|
|
9
10
|
interface NotifierMetadata extends AdapterMetadata {
|
|
10
11
|
readonly category: "notifier";
|
|
11
12
|
readonly logo?: string;
|
|
12
13
|
readonly schema: z.ZodType;
|
|
14
|
+
/** Delivery kind; absent means `message` (chat, email). */
|
|
15
|
+
readonly delivery?: NotifierDelivery;
|
|
13
16
|
}
|
|
14
|
-
/**
|
|
15
|
-
interface
|
|
17
|
+
/** Metadata of a `message` provider (Slack, Teams, email). */
|
|
18
|
+
interface MessageNotifierMetadata extends NotifierMetadata {
|
|
19
|
+
readonly delivery?: "message";
|
|
20
|
+
}
|
|
21
|
+
/** Metadata of a `state` provider (GitHub, GitLab): `delivery` is mandatory. */
|
|
22
|
+
interface StateNotifierMetadata extends NotifierMetadata {
|
|
23
|
+
readonly delivery: "state";
|
|
24
|
+
}
|
|
25
|
+
/** Descriptor of a `message` provider, registered at startup. */
|
|
26
|
+
interface MessageNotifierProvider extends Adapter<MessageNotifierMetadata> {
|
|
16
27
|
create(opts: {
|
|
17
28
|
config: unknown;
|
|
18
29
|
secret?: string;
|
|
19
30
|
logger?: Logger;
|
|
20
|
-
}):
|
|
31
|
+
}): MessageNotifierAdapter;
|
|
21
32
|
}
|
|
22
|
-
/**
|
|
23
|
-
interface
|
|
33
|
+
/** Descriptor of a `state` provider, registered at startup. */
|
|
34
|
+
interface StateNotifierProvider extends Adapter<StateNotifierMetadata> {
|
|
35
|
+
create(opts: {
|
|
36
|
+
config: unknown;
|
|
37
|
+
secret?: string;
|
|
38
|
+
logger?: Logger;
|
|
39
|
+
}): StateNotifierAdapter;
|
|
40
|
+
}
|
|
41
|
+
/** Descriptor — registered at startup, validates per-channel config. */
|
|
42
|
+
type NotifierProvider = MessageNotifierProvider | StateNotifierProvider;
|
|
43
|
+
/** Runtime of a `message` provider — bound to one channel config + secret, sends one message. */
|
|
44
|
+
interface MessageNotifierAdapter extends Adapter<MessageNotifierMetadata> {
|
|
24
45
|
send(input: {
|
|
25
46
|
channel: NotificationChannel;
|
|
26
47
|
formatted: FormattedNotification;
|
|
27
48
|
logger?: Logger;
|
|
28
49
|
}): Promise<void>;
|
|
29
50
|
}
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
/** Input of one idempotent state write. */
|
|
52
|
+
interface SetStateInput {
|
|
53
|
+
channel: NotificationChannel;
|
|
54
|
+
/** What to make the host show: a commit status or a pull-request comment. */
|
|
55
|
+
target: NotifierStateTarget;
|
|
56
|
+
state: NotifierState;
|
|
57
|
+
/**
|
|
58
|
+
* Link back to the build page; also keys the pull-request comment. Absent while no public origin
|
|
59
|
+
* is known (ADR 0007): a status then has no link and a comment is not written.
|
|
60
|
+
*/
|
|
61
|
+
url?: string | undefined;
|
|
62
|
+
logger?: Logger;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Runtime of a `state` provider: idempotent, latest call wins. A provider that
|
|
66
|
+
* cannot show a target kind (no comment support) skips it silently.
|
|
67
|
+
*/
|
|
68
|
+
interface StateNotifierAdapter extends Adapter<StateNotifierMetadata> {
|
|
69
|
+
setState(input: SetStateInput): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
/** Runtime — bound to one channel config + decrypted secret. */
|
|
72
|
+
type NotifierAdapter = MessageNotifierAdapter | StateNotifierAdapter;
|
|
73
|
+
/** True when the provider delivers state (git hosts) rather than messages. */
|
|
74
|
+
declare function isStateProvider(provider: NotifierProvider): provider is StateNotifierProvider;
|
|
75
|
+
export { MessageNotifierAdapter, MessageNotifierMetadata, MessageNotifierProvider, NotifierAdapter, NotifierDelivery, NotifierMetadata, NotifierProvider, SetStateInput, StateNotifierAdapter, StateNotifierMetadata, StateNotifierProvider, isStateProvider };
|
|
32
76
|
//# sourceMappingURL=provider.d.mts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/adapters/notifier/provider.ts
|
|
5
|
+
/** True when the provider delivers state (git hosts) rather than messages. */
|
|
6
|
+
function isStateProvider(provider) {
|
|
7
|
+
return provider.metadata.delivery === "state";
|
|
8
|
+
}
|
|
9
|
+
export { isStateProvider };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=provider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.mjs","names":[],"sources":["../../../src/adapters/notifier/provider.ts"],"sourcesContent":["import type { Logger } from \"pino\";\nimport type { z } from \"zod\";\nimport type { Adapter, AdapterMetadata } from \"../metadata.ts\";\nimport type {\n FormattedNotification,\n NotificationChannel,\n NotifierState,\n NotifierStateTarget,\n} from \"./types.ts\";\n\n/** How a provider delivers: `message` sends once, `state` makes a host show a named state. */\nexport type NotifierDelivery = \"message\" | \"state\";\n\n/** Notifier-specific metadata (adds logo + config validation schema). */\nexport interface NotifierMetadata extends AdapterMetadata {\n readonly category: \"notifier\";\n readonly logo?: string;\n readonly schema: z.ZodType;\n /** Delivery kind; absent means `message` (chat, email). */\n readonly delivery?: NotifierDelivery;\n}\n\n/** Metadata of a `message` provider (Slack, Teams, email). */\nexport interface MessageNotifierMetadata extends NotifierMetadata {\n readonly delivery?: \"message\";\n}\n\n/** Metadata of a `state` provider (GitHub, GitLab): `delivery` is mandatory. */\nexport interface StateNotifierMetadata extends NotifierMetadata {\n readonly delivery: \"state\";\n}\n\n/** Descriptor of a `message` provider, registered at startup. */\nexport interface MessageNotifierProvider extends Adapter<MessageNotifierMetadata> {\n create(opts: { config: unknown; secret?: string; logger?: Logger }): MessageNotifierAdapter;\n}\n\n/** Descriptor of a `state` provider, registered at startup. */\nexport interface StateNotifierProvider extends Adapter<StateNotifierMetadata> {\n create(opts: { config: unknown; secret?: string; logger?: Logger }): StateNotifierAdapter;\n}\n\n/** Descriptor — registered at startup, validates per-channel config. */\nexport type NotifierProvider = MessageNotifierProvider | StateNotifierProvider;\n\n/** Runtime of a `message` provider — bound to one channel config + secret, sends one message. */\nexport interface MessageNotifierAdapter extends Adapter<MessageNotifierMetadata> {\n send(input: {\n channel: NotificationChannel;\n formatted: FormattedNotification;\n logger?: Logger;\n }): Promise<void>;\n}\n\n/** Input of one idempotent state write. */\nexport interface SetStateInput {\n channel: NotificationChannel;\n /** What to make the host show: a commit status or a pull-request comment. */\n target: NotifierStateTarget;\n state: NotifierState;\n /**\n * Link back to the build page; also keys the pull-request comment. Absent while no public origin\n * is known (ADR 0007): a status then has no link and a comment is not written.\n */\n url?: string | undefined;\n logger?: Logger;\n}\n\n/**\n * Runtime of a `state` provider: idempotent, latest call wins. A provider that\n * cannot show a target kind (no comment support) skips it silently.\n */\nexport interface StateNotifierAdapter extends Adapter<StateNotifierMetadata> {\n setState(input: SetStateInput): Promise<void>;\n}\n\n/** Runtime — bound to one channel config + decrypted secret. */\nexport type NotifierAdapter = MessageNotifierAdapter | StateNotifierAdapter;\n\n/** True when the provider delivers state (git hosts) rather than messages. */\nexport function isStateProvider(provider: NotifierProvider): provider is StateNotifierProvider {\n return provider.metadata.delivery === \"state\";\n}\n"],"mappings":";;;;;AAgFA,SAAgB,gBAAgB,UAA+D;CAC7F,OAAO,SAAS,SAAS,aAAa;AACxC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { Logger } from "../../logger.mjs";
|
|
4
|
+
import { NotificationChannel } from "./types.mjs";
|
|
5
|
+
import { StateNotifierProvider } from "./provider.mjs";
|
|
6
|
+
import { BuildStateSet } from "./build-state.mjs";
|
|
7
|
+
/** Default status-name prefix of a git channel (`<prefix>/testing`). */
|
|
8
|
+
declare const DEFAULT_STATUS_PREFIX = "storyshelf";
|
|
9
|
+
/** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */
|
|
10
|
+
declare function channelPrefix(channel: NotificationChannel): string;
|
|
11
|
+
/**
|
|
12
|
+
* Make the channel's host show `states` for the commit `sha`: every status, then the comment.
|
|
13
|
+
* Each write is idempotent (latest call wins). A failed status write throws so the caller can
|
|
14
|
+
* retry; a failed comment write is logged and never fails the statuses.
|
|
15
|
+
*/
|
|
16
|
+
declare function writeBuildState(provider: StateNotifierProvider, channel: NotificationChannel, write: {
|
|
17
|
+
sha: string;
|
|
18
|
+
states: BuildStateSet;
|
|
19
|
+
logger?: Logger | undefined;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
export { DEFAULT_STATUS_PREFIX, channelPrefix, writeBuildState };
|
|
22
|
+
//# sourceMappingURL=state.d.mts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/adapters/notifier/state.ts
|
|
5
|
+
/** Default status-name prefix of a git channel (`<prefix>/testing`). */
|
|
6
|
+
const DEFAULT_STATUS_PREFIX = "storyshelf";
|
|
7
|
+
/** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */
|
|
8
|
+
function channelPrefix(channel) {
|
|
9
|
+
const prefix = channel.config["prefix"];
|
|
10
|
+
return typeof prefix === "string" && prefix.length > 0 ? prefix : DEFAULT_STATUS_PREFIX;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Make the channel's host show `states` for the commit `sha`: every status, then the comment.
|
|
14
|
+
* Each write is idempotent (latest call wins). A failed status write throws so the caller can
|
|
15
|
+
* retry; a failed comment write is logged and never fails the statuses.
|
|
16
|
+
*/
|
|
17
|
+
async function writeBuildState(provider, channel, write) {
|
|
18
|
+
const { sha, states, logger } = write;
|
|
19
|
+
const adapter = provider.create({
|
|
20
|
+
config: channel.config,
|
|
21
|
+
secret: channel.secret,
|
|
22
|
+
logger
|
|
23
|
+
});
|
|
24
|
+
const failed = (await Promise.allSettled(states.statuses.map(async (status) => {
|
|
25
|
+
await adapter.setState({
|
|
26
|
+
channel,
|
|
27
|
+
target: {
|
|
28
|
+
kind: "status",
|
|
29
|
+
sha,
|
|
30
|
+
context: status.context,
|
|
31
|
+
description: status.description,
|
|
32
|
+
...status.informational === true ? { informational: true } : {},
|
|
33
|
+
...status.progress === void 0 ? {} : { progress: status.progress },
|
|
34
|
+
...status.annotations === void 0 ? {} : { annotations: status.annotations },
|
|
35
|
+
...status.omitted === void 0 ? {} : { omitted: status.omitted }
|
|
36
|
+
},
|
|
37
|
+
state: status.state,
|
|
38
|
+
url: status.url,
|
|
39
|
+
logger
|
|
40
|
+
});
|
|
41
|
+
}))).find((result) => result.status === "rejected");
|
|
42
|
+
if (failed?.status === "rejected") throw failed.reason;
|
|
43
|
+
if (states.comment !== null) {
|
|
44
|
+
const { comment } = states;
|
|
45
|
+
await adapter.setState({
|
|
46
|
+
channel,
|
|
47
|
+
target: {
|
|
48
|
+
kind: "comment",
|
|
49
|
+
sha,
|
|
50
|
+
markdown: comment.markdown
|
|
51
|
+
},
|
|
52
|
+
state: comment.state,
|
|
53
|
+
url: comment.url,
|
|
54
|
+
logger
|
|
55
|
+
}).catch((error) => {
|
|
56
|
+
logger?.warn({
|
|
57
|
+
err: error,
|
|
58
|
+
channelId: channel.id
|
|
59
|
+
}, "failed to upsert comment");
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export { DEFAULT_STATUS_PREFIX, channelPrefix, writeBuildState };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.mjs","names":[],"sources":["../../../src/adapters/notifier/state.ts"],"sourcesContent":["/** Writing a build's desired states to one `state` channel (git hosts); see `build-state.ts` for what they are. */\nimport type { Logger } from \"../../logger.ts\";\nimport type { BuildStateSet } from \"./build-state.ts\";\nimport type { StateNotifierProvider } from \"./provider.ts\";\nimport type { NotificationChannel } from \"./types.ts\";\n\n/** Default status-name prefix of a git channel (`<prefix>/testing`). */\nexport const DEFAULT_STATUS_PREFIX = \"storyshelf\";\n\n/** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */\nexport function channelPrefix(channel: NotificationChannel): string {\n const prefix = channel.config[\"prefix\"];\n return typeof prefix === \"string\" && prefix.length > 0 ? prefix : DEFAULT_STATUS_PREFIX;\n}\n\n/**\n * Make the channel's host show `states` for the commit `sha`: every status, then the comment.\n * Each write is idempotent (latest call wins). A failed status write throws so the caller can\n * retry; a failed comment write is logged and never fails the statuses.\n */\nexport async function writeBuildState(\n provider: StateNotifierProvider,\n channel: NotificationChannel,\n write: { sha: string; states: BuildStateSet; logger?: Logger | undefined },\n): Promise<void> {\n const { sha, states, logger } = write;\n const adapter = provider.create({ config: channel.config, secret: channel.secret, logger });\n const results = await Promise.allSettled(\n states.statuses.map(async (status) => {\n await adapter.setState({\n channel,\n target: {\n kind: \"status\",\n sha,\n context: status.context,\n description: status.description,\n ...(status.informational === true ? { informational: true } : {}),\n ...(status.progress === undefined ? {} : { progress: status.progress }),\n ...(status.annotations === undefined ? {} : { annotations: status.annotations }),\n ...(status.omitted === undefined ? {} : { omitted: status.omitted }),\n },\n state: status.state,\n url: status.url,\n logger,\n });\n }),\n );\n const failed = results.find((result) => result.status === \"rejected\");\n if (failed?.status === \"rejected\") {\n throw failed.reason;\n }\n if (states.comment !== null) {\n const { comment } = states;\n await adapter\n .setState({\n channel,\n target: { kind: \"comment\", sha, markdown: comment.markdown },\n state: comment.state,\n url: comment.url,\n logger,\n })\n .catch((error: unknown) => {\n logger?.warn({ err: error, channelId: channel.id }, \"failed to upsert comment\");\n });\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,wBAAwB;;AAGrC,SAAgB,cAAc,SAAsC;CAClE,MAAM,SAAS,QAAQ,OAAO;CAC9B,OAAO,OAAO,WAAW,YAAY,OAAO,SAAS,IAAI,SAAS;AACpE;;;;;;AAOA,eAAsB,gBACpB,UACA,SACA,OACe;CACf,MAAM,EAAE,KAAK,QAAQ,WAAW;CAChC,MAAM,UAAU,SAAS,OAAO;EAAE,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;EAAQ;CAAO,CAAC;CAqB1F,MAAM,UAAS,MApBO,QAAQ,WAC5B,OAAO,SAAS,IAAI,OAAO,WAAW;EACpC,MAAM,QAAQ,SAAS;GACrB;GACA,QAAQ;IACN,MAAM;IACN;IACA,SAAS,OAAO;IAChB,aAAa,OAAO;IACpB,GAAI,OAAO,kBAAkB,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,GAAI,OAAO,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,OAAO,SAAS;IACrE,GAAI,OAAO,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,OAAO,YAAY;IAC9E,GAAI,OAAO,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;GACpE;GACA,OAAO,OAAO;GACd,KAAK,OAAO;GACZ;EACF,CAAC;CACH,CAAC,CACH,EAAA,CACuB,MAAM,WAAW,OAAO,WAAW,UAAU;CACpE,IAAI,QAAQ,WAAW,YACrB,MAAM,OAAO;CAEf,IAAI,OAAO,YAAY,MAAM;EAC3B,MAAM,EAAE,YAAY;EACpB,MAAM,QACH,SAAS;GACR;GACA,QAAQ;IAAE,MAAM;IAAW;IAAK,UAAU,QAAQ;GAAS;GAC3D,OAAO,QAAQ;GACf,KAAK,QAAQ;GACb;EACF,CAAC,CAAC,CACD,OAAO,UAAmB;GACzB,QAAQ,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,0BAA0B;EAChF,CAAC;CACL;AACF"}
|
|
@@ -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/adapters/notifier/types.d.ts
|
|
4
3
|
/** Shared event envelope for human-facing notifications. */
|
|
5
4
|
interface NotificationEvent {
|
|
6
5
|
event: string;
|
|
@@ -42,6 +41,55 @@ interface NotificationChannel {
|
|
|
42
41
|
secret?: string;
|
|
43
42
|
events: string[];
|
|
44
43
|
enabled: boolean;
|
|
44
|
+
/** Last delivery error, cleared by the next successful delivery. */
|
|
45
|
+
lastError?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* What a `state` provider shows for a build: pending, passed, failed, or cancelled by a user
|
|
49
|
+
* (a host without a cancelled state shows it like the nearest failure-class state).
|
|
50
|
+
*/
|
|
51
|
+
type NotifierState = "pending" | "success" | "failure" | "cancelled";
|
|
52
|
+
/**
|
|
53
|
+
* One per-story finding a host that supports it (GitHub check runs) shows beside a status: a
|
|
54
|
+
* changed snapshot that deep-links to its review page.
|
|
55
|
+
*/
|
|
56
|
+
interface StateAnnotation {
|
|
57
|
+
/** The story file the snapshot belongs to (the host anchors the finding there). */
|
|
58
|
+
path: string;
|
|
59
|
+
/** Short heading, e.g. `Button / Primary (chromium)`. */
|
|
60
|
+
title: string;
|
|
61
|
+
message: string;
|
|
62
|
+
/** Absolute link to the snapshot's review page. */
|
|
63
|
+
url: string;
|
|
64
|
+
level: "notice" | "warning";
|
|
65
|
+
}
|
|
66
|
+
/** Where a `state` provider writes: a commit status or a pull-request comment. */
|
|
67
|
+
type NotifierStateTarget = {
|
|
68
|
+
kind: "status";
|
|
69
|
+
sha: string;
|
|
70
|
+
/** Full status name on the host, e.g. `storyshelf/testing` (the caller owns the prefix). */
|
|
71
|
+
context: string;
|
|
72
|
+
/** Short text beside the status; the provider supplies a default. */
|
|
73
|
+
description?: string;
|
|
74
|
+
/** For a `pending` state: not started (`queued`) or under way (`running`; the default). */
|
|
75
|
+
progress?: "queued" | "running";
|
|
76
|
+
/** Never a merge gate (the Storybook status): a failure is shown as neutral where the host has it. */
|
|
77
|
+
informational?: boolean;
|
|
78
|
+
/** Per-snapshot findings of the build; only a host with annotations shows them. */
|
|
79
|
+
annotations?: StateAnnotation[];
|
|
80
|
+
/** Changed snapshots beyond `annotations` (cut at the cap); the host says "and N more". */
|
|
81
|
+
omitted?: number;
|
|
82
|
+
} | {
|
|
83
|
+
kind: "comment";
|
|
84
|
+
sha: string;
|
|
85
|
+
/** Comment body below the idempotency marker. */
|
|
86
|
+
markdown: string;
|
|
87
|
+
};
|
|
88
|
+
/** Result of one delivery attempt to a channel, reported to the host for health display. */
|
|
89
|
+
interface ChannelOutcome {
|
|
90
|
+
channelId: string;
|
|
91
|
+
/** Sanitized error text, absent on success. */
|
|
92
|
+
error?: string;
|
|
45
93
|
}
|
|
46
94
|
/** App-level (site-wide) admin alert — no project scope. */
|
|
47
95
|
interface SystemNotification {
|
|
@@ -50,7 +98,6 @@ interface SystemNotification {
|
|
|
50
98
|
timestamp: string;
|
|
51
99
|
}
|
|
52
100
|
/** Site-wide events for admins (new users, failures, purge). */
|
|
53
|
-
type SystemEventName = "sys:user-created" | "sys:invite-issued" | "sys:auth-failed" | "sys:capture-failed" | "sys:purge-completed";
|
|
54
|
-
|
|
55
|
-
export { ChannelToggles, FormattedNotification, NotificationBrand, NotificationChannel, NotificationEvent, SystemEventName, SystemNotification };
|
|
101
|
+
type SystemEventName = "sys:user-created" | "sys:invite-issued" | "sys:auth-failed" | "sys:capture-failed" | "sys:purge-completed" | "sys:notify-failed" | "sys:ai-budget";
|
|
102
|
+
export { ChannelOutcome, ChannelToggles, FormattedNotification, NotificationBrand, NotificationChannel, NotificationEvent, NotifierState, NotifierStateTarget, StateAnnotation, SystemEventName, SystemNotification };
|
|
56
103
|
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { BrowserName, CaptureTarget, TargetReach } from "./capture-target.mjs";
|
|
4
|
+
/** How a runner talks to the service: Playwright's own protocol, or the Chrome DevTools Protocol. */
|
|
5
|
+
type RemoteProtocol = "playwright" | "cdp";
|
|
6
|
+
/** Where and how to connect. A function `connect` is called per connection, so a token can be fresh. */
|
|
7
|
+
interface RemoteConnection {
|
|
8
|
+
/** `ws(s)://…` (CDP also accepts `http(s)://…`). May carry credentials: it is never logged. */
|
|
9
|
+
endpoint: string;
|
|
10
|
+
/** Request headers for the handshake, such as `authorization`. Never logged. */
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/** A connection a function `connect` returns, with what `release` needs back. */
|
|
14
|
+
interface RemoteLeasedConnection<TLease = unknown> extends RemoteConnection {
|
|
15
|
+
/** Opaque to the runner, handed to `release` once and never logged (it may carry credentials). */
|
|
16
|
+
lease?: TLease | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** What a run is doing when it connects. */
|
|
19
|
+
type RemotePurpose = "render" | "extract" | "tests";
|
|
20
|
+
/** How a leased connection ended, handed to `release`. */
|
|
21
|
+
type RemoteLeaseOutcome = "finished" | "failed" | "cancelled";
|
|
22
|
+
/** What a function `connect` is told about the connection it is asked for. */
|
|
23
|
+
interface RemoteConnectContext {
|
|
24
|
+
engine: BrowserName;
|
|
25
|
+
/** The StoryShelf build; the same for every shard of it. */
|
|
26
|
+
buildId: string;
|
|
27
|
+
/** The shard's own id; the build id when the render is not sharded. */
|
|
28
|
+
runId: string;
|
|
29
|
+
/** The shard's 1-based position in the build's plan; `undefined` (never 0) when not sharded. */
|
|
30
|
+
shardIndex?: number | undefined;
|
|
31
|
+
/** `render` for a build or shard, `extract` for the parameter pre-pass, `tests` for `.test()` entries. */
|
|
32
|
+
purpose: RemotePurpose;
|
|
33
|
+
/** This connection's attempt, from 1; each retry connects anew. */
|
|
34
|
+
attempt: number;
|
|
35
|
+
/**
|
|
36
|
+
* Aborts while `connect` is pending: on `timeouts.acquireMs`, a cancel (user, build, render
|
|
37
|
+
* budget) and shutdown. Spent once `connect` resolves.
|
|
38
|
+
*/
|
|
39
|
+
signal: AbortSignal;
|
|
40
|
+
}
|
|
41
|
+
/** What `release` is told about how the connection's render went. */
|
|
42
|
+
interface RemoteReleaseInfo {
|
|
43
|
+
outcome: RemoteLeaseOutcome;
|
|
44
|
+
/** Why it failed, for `failed`. Carries no credentials, but may carry provider text. */
|
|
45
|
+
error?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** What {@link defineRemote} takes: what `remote()` exposes to operators. */
|
|
48
|
+
interface RemoteOptions<TLease = unknown> {
|
|
49
|
+
/** The target name half (`chromium@<name>`): lowercase letters, digits and hyphens, at most 32. */
|
|
50
|
+
name: string;
|
|
51
|
+
/** The engines to offer (a subset of what the service has). */
|
|
52
|
+
engines: readonly BrowserName[];
|
|
53
|
+
/** Parallel sessions the plan allows: the page cap of the target, per process (decision 4). A function is read live. */
|
|
54
|
+
sessions: number | (() => number);
|
|
55
|
+
/** Maximum concurrent pages on each browser connection; independent of the shared session gate. */
|
|
56
|
+
maxPagesPerConnection?: number | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Maximum connections this process holds to the service at once (default: no cap). A separate
|
|
59
|
+
* limit from `sessions` (pages) and `maxPagesPerConnection`: a connection counts from the moment
|
|
60
|
+
* it is requested until its render has ended, a shared one once. Renders over the cap wait, and a
|
|
61
|
+
* cancel or shutdown ends the wait. Per process; the deployment-wide cap is another issue.
|
|
62
|
+
*/
|
|
63
|
+
maxConnections?: number | undefined;
|
|
64
|
+
/** Declared, never inferred: how the runner talks to the service. */
|
|
65
|
+
protocol: RemoteProtocol;
|
|
66
|
+
/**
|
|
67
|
+
* Declared, never inferred: `loopback` when the remote browser can route back to this host
|
|
68
|
+
* (Playwright's `exposeNetwork: "<loopback>"`), else `url` (it needs a signed Storybook URL).
|
|
69
|
+
*/
|
|
70
|
+
reach: TargetReach;
|
|
71
|
+
/**
|
|
72
|
+
* The connection: an object for a fixed service (validated at creation), or a function called
|
|
73
|
+
* for every connection (sync or async) to wake or start something, pick a server per shard, or
|
|
74
|
+
* mint a token. A throw is retried and ends as a `TargetLaunchError`.
|
|
75
|
+
*/
|
|
76
|
+
connect: RemoteConnection | ((context: RemoteConnectContext) => RemoteLeasedConnection<TLease> | Promise<RemoteLeasedConnection<TLease>>);
|
|
77
|
+
/**
|
|
78
|
+
* Called once for every connection `connect` returned a `lease` for, after the render that used
|
|
79
|
+
* it finished, failed or was cancelled (and for leases still held at shutdown, `cancelled`).
|
|
80
|
+
* Only valid with a function `connect`. A throw or a timeout (`timeouts.releaseMs`) is logged and
|
|
81
|
+
* never fails the render.
|
|
82
|
+
*/
|
|
83
|
+
release?: ((lease: TLease, info: RemoteReleaseInfo) => Promise<void> | void) | undefined;
|
|
84
|
+
/** OS the service renders on, reported when the page cannot tell (`linux-x64`, `windows`, …). */
|
|
85
|
+
platform?: string | undefined;
|
|
86
|
+
/** Connect retries: `attempts` after the first (default 3), `backoffMs` doubling (default 500). */
|
|
87
|
+
retry?: {
|
|
88
|
+
attempts?: number | undefined;
|
|
89
|
+
backoffMs?: number | undefined;
|
|
90
|
+
} | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* `acquireMs` bounds the `connect` function, `connectMs` the handshake after it (a farm with a
|
|
93
|
+
* client cap queues extra connections, so a busy farm shows up as this timeout), `releaseMs`
|
|
94
|
+
* the `release` hook. All default to 30 000. `probeMs` bounds measuring the browser's
|
|
95
|
+
* environment once connected (default 15 000): a probe that overruns leaves the environment
|
|
96
|
+
* unknown with a warning, and a cancel stops it at once.
|
|
97
|
+
*/
|
|
98
|
+
timeouts?: {
|
|
99
|
+
acquireMs?: number | undefined;
|
|
100
|
+
connectMs?: number | undefined;
|
|
101
|
+
releaseMs?: number | undefined;
|
|
102
|
+
probeMs?: number | undefined;
|
|
103
|
+
} | undefined;
|
|
104
|
+
}
|
|
105
|
+
/** One remote service, validated: an entry of a runner's `browsers`. */
|
|
106
|
+
interface RemoteBrowser {
|
|
107
|
+
readonly kind: "remote";
|
|
108
|
+
readonly name: string;
|
|
109
|
+
readonly engines: readonly BrowserName[];
|
|
110
|
+
readonly sessions: number | (() => number);
|
|
111
|
+
readonly maxPagesPerConnection?: number | undefined;
|
|
112
|
+
readonly maxConnections?: number | undefined;
|
|
113
|
+
readonly protocol: RemoteProtocol;
|
|
114
|
+
readonly reach: TargetReach;
|
|
115
|
+
readonly connect: RemoteOptions["connect"];
|
|
116
|
+
readonly release: ((lease: never, info: RemoteReleaseInfo) => Promise<void> | void) | undefined;
|
|
117
|
+
readonly platform: string | undefined;
|
|
118
|
+
readonly retry: {
|
|
119
|
+
readonly attempts: number;
|
|
120
|
+
readonly backoffMs: number;
|
|
121
|
+
};
|
|
122
|
+
readonly timeouts: {
|
|
123
|
+
readonly acquireMs: number;
|
|
124
|
+
readonly connectMs: number;
|
|
125
|
+
readonly releaseMs: number;
|
|
126
|
+
readonly probeMs: number;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** What a runner supports, which {@link defineRemote} checks the service against. */
|
|
130
|
+
interface RemoteSupport {
|
|
131
|
+
/** Engines the runner can drive. */
|
|
132
|
+
engines: readonly BrowserName[];
|
|
133
|
+
/** Protocols the runner can speak. */
|
|
134
|
+
protocols: readonly RemoteProtocol[];
|
|
135
|
+
/** Shown in errors, for example `remote()`. */
|
|
136
|
+
label: string;
|
|
137
|
+
}
|
|
138
|
+
/** One target a remote service offers. */
|
|
139
|
+
interface RemoteTarget {
|
|
140
|
+
kind: "remote";
|
|
141
|
+
target: CaptureTarget;
|
|
142
|
+
engine: BrowserName;
|
|
143
|
+
remote: RemoteBrowser;
|
|
144
|
+
/** How the browser reaches the Storybook. */
|
|
145
|
+
reach: TargetReach;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Validate a remote service eagerly, so a mistake fails when the runner is created and not when the
|
|
149
|
+
* first build runs: unknown or moved options, the name, the sessions, the engines against what the
|
|
150
|
+
* runner drives, the protocol, the reach, and a fixed connection (endpoint scheme).
|
|
151
|
+
*/
|
|
152
|
+
declare function defineRemote<TLease = unknown>(options: RemoteOptions<TLease>, support: RemoteSupport): RemoteBrowser;
|
|
153
|
+
/** The targets a service offers, in the order of its `engines`. */
|
|
154
|
+
declare function remoteTargetsOf(remote: RemoteBrowser): RemoteTarget[];
|
|
155
|
+
/** Whether a value is a remote service entry. */
|
|
156
|
+
declare function isRemoteBrowser(value: unknown): value is RemoteBrowser;
|
|
157
|
+
/** Whether `endpoint` has a scheme `protocol` can open. */
|
|
158
|
+
declare function hasSchemeFor(protocol: RemoteProtocol, endpoint: string): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Remove what identifies the connection from text surfaced to operators: the endpoint (it can carry
|
|
161
|
+
* a key in its path or query), its host and path, its query values, every header value and every
|
|
162
|
+
* value inside the lease (non-strings are stringified).
|
|
163
|
+
*/
|
|
164
|
+
declare function scrubConnection(text: string, connection: RemoteConnection & {
|
|
165
|
+
lease?: unknown;
|
|
166
|
+
}): string;
|
|
167
|
+
export { RemoteBrowser, RemoteConnectContext, RemoteConnection, RemoteLeaseOutcome, RemoteLeasedConnection, RemoteOptions, RemoteProtocol, RemotePurpose, RemoteReleaseInfo, RemoteSupport, RemoteTarget, defineRemote, hasSchemeFor, isRemoteBrowser, remoteTargetsOf, scrubConnection };
|
|
168
|
+
//# sourceMappingURL=remote-browser.d.mts.map
|