@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,68 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { isTerminalJob, parseAttemptRowId } from "../../models/capture-job.mjs";
|
|
5
|
+
import { isoAt } from "./clock.mjs";
|
|
6
|
+
import { claimNext } from "./claim.mjs";
|
|
7
|
+
// src/capture/db-queue/poll.ts
|
|
8
|
+
/** Longest a nack may delay a retry; larger delays are clamped. */
|
|
9
|
+
const MAX_NACK_DELAY_MS = 36e5;
|
|
10
|
+
/**
|
|
11
|
+
* Claim one job. Probes once; with `waitMs`, an empty probe waits for a local enqueue (or the
|
|
12
|
+
* timeout) and probes once more only when woken, so an idle wait costs a single probe.
|
|
13
|
+
*/
|
|
14
|
+
async function pollJob(rt, options) {
|
|
15
|
+
const since = rt.wake.version();
|
|
16
|
+
rt.pollVersion = since;
|
|
17
|
+
const job = await claimNext(rt);
|
|
18
|
+
const waitMs = options?.waitMs ?? 0;
|
|
19
|
+
if (job !== null || waitMs <= 0) return job;
|
|
20
|
+
return await rt.wake.wait(waitMs, since) ? await claimNext(rt) : null;
|
|
21
|
+
}
|
|
22
|
+
/** The attempt succeeded: its row and the job row become `done` (a cancelled job stays cancelled). */
|
|
23
|
+
async function ackJob(rt, job) {
|
|
24
|
+
const ref = attemptRef(job);
|
|
25
|
+
const now = isoAt(rt);
|
|
26
|
+
await rt.model.finishAttempt(ref.receipt, "done", now);
|
|
27
|
+
if ((await rt.model.get(ref.jobId))?.status !== "cancelled") await rt.model.finishJob(ref.jobId, "done", now);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The attempt failed. Only the current holder settles the job: a holder whose attempt was taken
|
|
31
|
+
* over (its row is no longer `running`, or the job moved on to a later attempt) writes nothing, so a
|
|
32
|
+
* stale holder can never requeue or fail a job another instance is running.
|
|
33
|
+
*/
|
|
34
|
+
async function nackJob(rt, job, options = {}) {
|
|
35
|
+
const ref = attemptRef(job);
|
|
36
|
+
if ((await rt.model.get(ref.receipt))?.status !== "running") return;
|
|
37
|
+
await rt.model.finishAttempt(ref.receipt, "failed", isoAt(rt), options.error ?? null);
|
|
38
|
+
const row = await rt.model.get(ref.jobId);
|
|
39
|
+
if (row === null || isTerminalJob(row) || row.attempt !== ref.attempt) return;
|
|
40
|
+
await settleFailure(rt, row, options);
|
|
41
|
+
}
|
|
42
|
+
/** Cancelled, final, or retried after `delayMs` (clamped to `[0, MAX_NACK_DELAY_MS]`). */
|
|
43
|
+
async function settleFailure(rt, row, options) {
|
|
44
|
+
const now = isoAt(rt);
|
|
45
|
+
const error = options.error ?? null;
|
|
46
|
+
if (row.cancelRequestedAt !== null) {
|
|
47
|
+
await rt.model.finishJob(row.jobId, "cancelled", now, error);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (options.requeue === false || row.attempt >= row.maxAttempts) {
|
|
51
|
+
await rt.model.finishJob(row.jobId, "failed", now, error ?? "failed");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const delayMs = Math.min(Math.max(options.delayMs ?? 0, 0), MAX_NACK_DELAY_MS);
|
|
55
|
+
await rt.model.requeue(row.jobId, isoAt(rt, delayMs), error, now);
|
|
56
|
+
}
|
|
57
|
+
/** The attempt a polled job refers to, from its receipt (`<jobId>:<attempt>`). */
|
|
58
|
+
function attemptRef(job) {
|
|
59
|
+
const parsed = job.receipt === void 0 ? null : parseAttemptRowId(job.receipt);
|
|
60
|
+
if (parsed === null || job.receipt === void 0) throw new Error("not a database queue job: missing or malformed receipt");
|
|
61
|
+
return {
|
|
62
|
+
receipt: job.receipt,
|
|
63
|
+
...parsed
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export { MAX_NACK_DELAY_MS, ackJob, attemptRef, nackJob, pollJob };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=poll.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll.mjs","names":[],"sources":["../../../src/capture/db-queue/poll.ts"],"sourcesContent":["/** `poll` / `ack` / `nack` of the database queue: claim, finish and retry-with-backoff of attempts. */\nimport type { PollableJob } from \"../../adapters/capture-queue.ts\";\nimport { isTerminalJob, parseAttemptRowId } from \"../../models/capture-job.ts\";\nimport type { CaptureJobRow } from \"../../schema/capture-job.ts\";\nimport { claimNext } from \"./claim.ts\";\nimport { isoAt } from \"./clock.ts\";\nimport type { DatabaseJob, QueueRuntime } from \"./types.ts\";\n\n/** Longest a nack may delay a retry; larger delays are clamped. */\nexport const MAX_NACK_DELAY_MS = 60 * 60_000;\n\n/** Options of `nack`, as `PollableCaptureQueue` defines them. */\nexport interface NackOptions {\n requeue?: boolean;\n delayMs?: number;\n error?: string;\n}\n\n/**\n * Claim one job. Probes once; with `waitMs`, an empty probe waits for a local enqueue (or the\n * timeout) and probes once more only when woken, so an idle wait costs a single probe.\n */\nexport async function pollJob(\n rt: QueueRuntime,\n options?: { waitMs?: number },\n): Promise<DatabaseJob | null> {\n const since = rt.wake.version();\n rt.pollVersion = since;\n const job = await claimNext(rt);\n const waitMs = options?.waitMs ?? 0;\n if (job !== null || waitMs <= 0) {\n return job;\n }\n return (await rt.wake.wait(waitMs, since)) ? await claimNext(rt) : null;\n}\n\n/** The attempt succeeded: its row and the job row become `done` (a cancelled job stays cancelled). */\nexport async function ackJob(rt: QueueRuntime, job: PollableJob): Promise<void> {\n const ref = attemptRef(job);\n const now = isoAt(rt);\n await rt.model.finishAttempt(ref.receipt, \"done\", now);\n if ((await rt.model.get(ref.jobId))?.status !== \"cancelled\") {\n await rt.model.finishJob(ref.jobId, \"done\", now);\n }\n}\n\n/**\n * The attempt failed. Only the current holder settles the job: a holder whose attempt was taken\n * over (its row is no longer `running`, or the job moved on to a later attempt) writes nothing, so a\n * stale holder can never requeue or fail a job another instance is running.\n */\nexport async function nackJob(\n rt: QueueRuntime,\n job: PollableJob,\n options: NackOptions = {},\n): Promise<void> {\n const ref = attemptRef(job);\n if ((await rt.model.get(ref.receipt))?.status !== \"running\") {\n return;\n }\n await rt.model.finishAttempt(ref.receipt, \"failed\", isoAt(rt), options.error ?? null);\n const row = await rt.model.get(ref.jobId);\n if (row === null || isTerminalJob(row) || row.attempt !== ref.attempt) {\n return;\n }\n await settleFailure(rt, row, options);\n}\n\n/** Cancelled, final, or retried after `delayMs` (clamped to `[0, MAX_NACK_DELAY_MS]`). */\nasync function settleFailure(\n rt: QueueRuntime,\n row: CaptureJobRow,\n options: NackOptions,\n): Promise<void> {\n const now = isoAt(rt);\n const error = options.error ?? null;\n if (row.cancelRequestedAt !== null) {\n await rt.model.finishJob(row.jobId, \"cancelled\", now, error);\n return;\n }\n if (options.requeue === false || row.attempt >= row.maxAttempts) {\n await rt.model.finishJob(row.jobId, \"failed\", now, error ?? \"failed\");\n return;\n }\n const delayMs = Math.min(Math.max(options.delayMs ?? 0, 0), MAX_NACK_DELAY_MS);\n await rt.model.requeue(row.jobId, isoAt(rt, delayMs), error, now);\n}\n\n/** The attempt a polled job refers to, from its receipt (`<jobId>:<attempt>`). */\nexport function attemptRef(job: PollableJob): { receipt: string; jobId: string; attempt: number } {\n const parsed = job.receipt === undefined ? null : parseAttemptRowId(job.receipt);\n if (parsed === null || job.receipt === undefined) {\n throw new Error(\"not a database queue job: missing or malformed receipt\");\n }\n return { receipt: job.receipt, ...parsed };\n}\n"],"mappings":";;;;;;;;AASA,MAAa,oBAAoB;;;;;AAajC,eAAsB,QACpB,IACA,SAC6B;CAC7B,MAAM,QAAQ,GAAG,KAAK,QAAQ;CAC9B,GAAG,cAAc;CACjB,MAAM,MAAM,MAAM,UAAU,EAAE;CAC9B,MAAM,SAAS,SAAS,UAAU;CAClC,IAAI,QAAQ,QAAQ,UAAU,GAC5B,OAAO;CAET,OAAQ,MAAM,GAAG,KAAK,KAAK,QAAQ,KAAK,IAAK,MAAM,UAAU,EAAE,IAAI;AACrE;;AAGA,eAAsB,OAAO,IAAkB,KAAiC;CAC9E,MAAM,MAAM,WAAW,GAAG;CAC1B,MAAM,MAAM,MAAM,EAAE;CACpB,MAAM,GAAG,MAAM,cAAc,IAAI,SAAS,QAAQ,GAAG;CACrD,KAAK,MAAM,GAAG,MAAM,IAAI,IAAI,KAAK,EAAA,EAAI,WAAW,aAC9C,MAAM,GAAG,MAAM,UAAU,IAAI,OAAO,QAAQ,GAAG;AAEnD;;;;;;AAOA,eAAsB,QACpB,IACA,KACA,UAAuB,CAAC,GACT;CACf,MAAM,MAAM,WAAW,GAAG;CAC1B,KAAK,MAAM,GAAG,MAAM,IAAI,IAAI,OAAO,EAAA,EAAI,WAAW,WAChD;CAEF,MAAM,GAAG,MAAM,cAAc,IAAI,SAAS,UAAU,MAAM,EAAE,GAAG,QAAQ,SAAS,IAAI;CACpF,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,IAAI,KAAK;CACxC,IAAI,QAAQ,QAAQ,cAAc,GAAG,KAAK,IAAI,YAAY,IAAI,SAC5D;CAEF,MAAM,cAAc,IAAI,KAAK,OAAO;AACtC;;AAGA,eAAe,cACb,IACA,KACA,SACe;CACf,MAAM,MAAM,MAAM,EAAE;CACpB,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI,IAAI,sBAAsB,MAAM;EAClC,MAAM,GAAG,MAAM,UAAU,IAAI,OAAO,aAAa,KAAK,KAAK;EAC3D;CACF;CACA,IAAI,QAAQ,YAAY,SAAS,IAAI,WAAW,IAAI,aAAa;EAC/D,MAAM,GAAG,MAAM,UAAU,IAAI,OAAO,UAAU,KAAK,SAAS,QAAQ;EACpE;CACF;CACA,MAAM,UAAU,KAAK,IAAI,KAAK,IAAI,QAAQ,WAAW,GAAG,CAAC,GAAG,iBAAiB;CAC7E,MAAM,GAAG,MAAM,QAAQ,IAAI,OAAO,MAAM,IAAI,OAAO,GAAG,OAAO,GAAG;AAClE;;AAGA,SAAgB,WAAW,KAAuE;CAChG,MAAM,SAAS,IAAI,YAAY,KAAA,IAAY,OAAO,kBAAkB,IAAI,OAAO;CAC/E,IAAI,WAAW,QAAQ,IAAI,YAAY,KAAA,GACrC,MAAM,IAAI,MAAM,wDAAwD;CAE1E,OAAO;EAAE,SAAS,IAAI;EAAS,GAAG;CAAO;AAC3C"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
/** Timer seam of the database queue: production uses the global timers, tests a manual clock. */
|
|
4
|
+
/** The two timer calls the queue, its wake signal and the lease keeper make. */
|
|
5
|
+
interface QueueTimers {
|
|
6
|
+
setTimeout(callback: () => void, ms: number): unknown;
|
|
7
|
+
clearTimeout(handle: unknown): void;
|
|
8
|
+
}
|
|
9
|
+
export { QueueTimers };
|
|
10
|
+
//# sourceMappingURL=timers.d.mts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/capture/db-queue/timers.ts
|
|
5
|
+
/** Global timers, unref'd so a waiting poll or a lease check never holds the process open. */
|
|
6
|
+
const REAL_TIMERS = {
|
|
7
|
+
setTimeout: (callback, ms) => {
|
|
8
|
+
const handle = setTimeout(callback, Math.max(0, ms));
|
|
9
|
+
handle.unref?.();
|
|
10
|
+
return handle;
|
|
11
|
+
},
|
|
12
|
+
clearTimeout: (handle) => {
|
|
13
|
+
clearTimeout(handle);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/** Call `callback` every `ms` until the returned stop function runs; built on `setTimeout`. */
|
|
17
|
+
function repeatEvery(timers, ms, callback) {
|
|
18
|
+
let handle;
|
|
19
|
+
let stopped = false;
|
|
20
|
+
const arm = () => {
|
|
21
|
+
handle = timers.setTimeout(() => {
|
|
22
|
+
if (!stopped) {
|
|
23
|
+
callback();
|
|
24
|
+
arm();
|
|
25
|
+
}
|
|
26
|
+
}, ms);
|
|
27
|
+
};
|
|
28
|
+
arm();
|
|
29
|
+
return () => {
|
|
30
|
+
stopped = true;
|
|
31
|
+
timers.clearTimeout(handle);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export { REAL_TIMERS, repeatEvery };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=timers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timers.mjs","names":[],"sources":["../../../src/capture/db-queue/timers.ts"],"sourcesContent":["/** Timer seam of the database queue: production uses the global timers, tests a manual clock. */\n\n/** The two timer calls the queue, its wake signal and the lease keeper make. */\nexport interface QueueTimers {\n setTimeout(callback: () => void, ms: number): unknown;\n clearTimeout(handle: unknown): void;\n}\n\n/** Global timers, unref'd so a waiting poll or a lease check never holds the process open. */\nexport const REAL_TIMERS: QueueTimers = {\n setTimeout: (callback, ms) => {\n const handle = setTimeout(callback, Math.max(0, ms));\n handle.unref?.();\n return handle;\n },\n clearTimeout: (handle) => {\n clearTimeout(handle as ReturnType<typeof setTimeout>);\n },\n};\n\n/** Call `callback` every `ms` until the returned stop function runs; built on `setTimeout`. */\nexport function repeatEvery(timers: QueueTimers, ms: number, callback: () => void): () => void {\n let handle: unknown;\n let stopped = false;\n const arm = (): void => {\n handle = timers.setTimeout(() => {\n if (!stopped) {\n callback();\n arm();\n }\n }, ms);\n };\n arm();\n return () => {\n stopped = true;\n timers.clearTimeout(handle);\n };\n}\n"],"mappings":";;;;;AASA,MAAa,cAA2B;CACtC,aAAa,UAAU,OAAO;EAC5B,MAAM,SAAS,WAAW,UAAU,KAAK,IAAI,GAAG,EAAE,CAAC;EACnD,OAAO,QAAQ;EACf,OAAO;CACT;CACA,eAAe,WAAW;EACxB,aAAa,MAAuC;CACtD;AACF;;AAGA,SAAgB,YAAY,QAAqB,IAAY,UAAkC;CAC7F,IAAI;CACJ,IAAI,UAAU;CACd,MAAM,YAAkB;EACtB,SAAS,OAAO,iBAAiB;GAC/B,IAAI,CAAC,SAAS;IACZ,SAAS;IACT,IAAI;GACN;EACF,GAAG,EAAE;CACP;CACA,IAAI;CACJ,aAAa;EACX,UAAU;EACV,OAAO,aAAa,MAAM;CAC5B;AACF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { Logger } from "../../logger.mjs";
|
|
4
|
+
import { AdapterLifecycle } from "../../adapter/metadata.mjs";
|
|
5
|
+
import { CaptureJob, LeaseRenewal, PollableCaptureQueue, PollableJob } from "../../adapter/capture-queue.mjs";
|
|
6
|
+
import { CaptureJobKind } from "../../schema/capture-job.mjs";
|
|
7
|
+
import { QueueTimers } from "./timers.mjs";
|
|
8
|
+
import "../../models/capture-job.mjs";
|
|
9
|
+
/** Options of {@link createDatabaseCaptureQueue}. */
|
|
10
|
+
interface DatabaseCaptureQueueOptions {
|
|
11
|
+
/** Job kinds this instance polls (default `["capture"]`); enqueue accepts every kind. */
|
|
12
|
+
kinds?: readonly CaptureJobKind[];
|
|
13
|
+
/** Lease granted per attempt, renewed by a heartbeat and by progress (default {@link DEFAULT_LEASE_MS}, 5 min; `testing.leaseSeconds`). */
|
|
14
|
+
leaseMs?: number;
|
|
15
|
+
/** Retries after the first attempt (`testing.retries`, default 2: three attempts in total). */
|
|
16
|
+
retries?: number;
|
|
17
|
+
/** Identity written on the attempt rows this instance holds (default host, pid and a random tag). */
|
|
18
|
+
owner?: string;
|
|
19
|
+
/** Clock in epoch ms (default `Date.now`); tests inject one to drive leases and visibility. */
|
|
20
|
+
now?: () => number;
|
|
21
|
+
/** Timers of the local wake wait (default the global timers); tests inject a manual clock. */
|
|
22
|
+
timers?: QueueTimers;
|
|
23
|
+
/** Explicit logger override; the host normally binds one through `setLogger`. */
|
|
24
|
+
logger?: Logger;
|
|
25
|
+
/**
|
|
26
|
+
* Called after a job failed because its last attempt lost its lease: nothing was running to
|
|
27
|
+
* record the failure, so the host writes it (a build left `capturing`). May run on every
|
|
28
|
+
* instance that finds the job, so it must be idempotent; a throw is logged and ignored.
|
|
29
|
+
*/
|
|
30
|
+
onExhausted?: (job: DatabaseJob, error: string) => Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/** Default lease per attempt: long enough for a slow stage, short enough to recover a crash. */
|
|
33
|
+
declare const DEFAULT_LEASE_MS: number;
|
|
34
|
+
/** Default `testing.retries` (ADR 0006, decision 11). */
|
|
35
|
+
declare const DEFAULT_RETRIES = 2;
|
|
36
|
+
/** A job of any kind, as `enqueueJob` takes it. */
|
|
37
|
+
interface QueueJobInput {
|
|
38
|
+
kind: CaptureJobKind;
|
|
39
|
+
/** Build the job works on; notify jobs may have none. */
|
|
40
|
+
buildId?: string | null;
|
|
41
|
+
/** `capture_shards` row, for a shard capture job. */
|
|
42
|
+
shard?: string;
|
|
43
|
+
reqId?: string;
|
|
44
|
+
traceparent?: string;
|
|
45
|
+
/** Kind-specific fields (channel id, zip key, …), stored as JSON. */
|
|
46
|
+
data?: Record<string, unknown>;
|
|
47
|
+
/** Attempts allowed in total for this job; defaults to the queue's (`retries` + 1). */
|
|
48
|
+
maxAttempts?: number;
|
|
49
|
+
}
|
|
50
|
+
/** A job claimed from the database queue. */
|
|
51
|
+
interface DatabaseJob extends PollableJob {
|
|
52
|
+
/** Id of the job row (`receipt` is the attempt row, `<jobId>:<attempt>`). */
|
|
53
|
+
jobId: string;
|
|
54
|
+
kind: CaptureJobKind;
|
|
55
|
+
/** Attempt number, from 1 (`attempts` is the number made before this one). */
|
|
56
|
+
attempt: number;
|
|
57
|
+
maxAttempts: number;
|
|
58
|
+
/** Kind-specific fields given at enqueue. */
|
|
59
|
+
data: Record<string, unknown>;
|
|
60
|
+
}
|
|
61
|
+
/** The database queue: a {@link PollableCaptureQueue} plus multi-kind enqueue and a local wake. */
|
|
62
|
+
interface DatabaseCaptureQueue extends PollableCaptureQueue {
|
|
63
|
+
readonly lifecycle: AdapterLifecycle;
|
|
64
|
+
poll(options?: {
|
|
65
|
+
waitMs?: number;
|
|
66
|
+
}): Promise<DatabaseJob | null>;
|
|
67
|
+
extend(job: PollableJob): Promise<LeaseRenewal>;
|
|
68
|
+
/** Put a job of any kind on the queue; resolves to its job id. */
|
|
69
|
+
enqueueJob(job: QueueJobInput): Promise<string>;
|
|
70
|
+
/** Cancel a job by job id, or every unfinished job of a build (every kind) by build id. */
|
|
71
|
+
cancel(id: string): Promise<boolean>;
|
|
72
|
+
/** Read the job's state without renewing its lease (the 5 s cancel check). */
|
|
73
|
+
inspect(job: PollableJob): Promise<LeaseRenewal>;
|
|
74
|
+
/**
|
|
75
|
+
* Resolve true when this instance enqueues a job (including one enqueued since the last `poll`
|
|
76
|
+
* began, so no wake-up is lost), false after `ms`.
|
|
77
|
+
*/
|
|
78
|
+
waitForWork(ms: number): Promise<boolean>;
|
|
79
|
+
}
|
|
80
|
+
export { DEFAULT_LEASE_MS, DEFAULT_RETRIES, DatabaseCaptureQueue, DatabaseCaptureQueueOptions, DatabaseJob, QueueJobInput };
|
|
81
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/capture/db-queue/types.ts
|
|
5
|
+
/** Default lease per attempt: long enough for a slow stage, short enough to recover a crash. */
|
|
6
|
+
const DEFAULT_LEASE_MS = 3e5;
|
|
7
|
+
/** Default `testing.retries` (ADR 0006, decision 11). */
|
|
8
|
+
const DEFAULT_RETRIES = 2;
|
|
9
|
+
export { DEFAULT_LEASE_MS, DEFAULT_RETRIES };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../../src/capture/db-queue/types.ts"],"sourcesContent":["/** Option, job and runtime types of the database capture queue. */\nimport type {\n CaptureJob,\n LeaseRenewal,\n PollableCaptureQueue,\n PollableJob,\n} from \"../../adapters/capture-queue.ts\";\nimport type { AdapterLifecycle } from \"../../adapters/metadata.ts\";\nimport type { Logger } from \"../../logger.ts\";\nimport type { CaptureJobModel } from \"../../models/capture-job.ts\";\nimport type { CaptureJobKind } from \"../../schema/capture-job.ts\";\nimport type { QueueTimers } from \"./timers.ts\";\nimport type { WakeSignal } from \"./wake.ts\";\n\n/** Options of {@link createDatabaseCaptureQueue}. */\nexport interface DatabaseCaptureQueueOptions {\n /** Job kinds this instance polls (default `[\"capture\"]`); enqueue accepts every kind. */\n kinds?: readonly CaptureJobKind[];\n /** Lease granted per attempt, renewed by a heartbeat and by progress (default {@link DEFAULT_LEASE_MS}, 5 min; `testing.leaseSeconds`). */\n leaseMs?: number;\n /** Retries after the first attempt (`testing.retries`, default 2: three attempts in total). */\n retries?: number;\n /** Identity written on the attempt rows this instance holds (default host, pid and a random tag). */\n owner?: string;\n /** Clock in epoch ms (default `Date.now`); tests inject one to drive leases and visibility. */\n now?: () => number;\n /** Timers of the local wake wait (default the global timers); tests inject a manual clock. */\n timers?: QueueTimers;\n /** Explicit logger override; the host normally binds one through `setLogger`. */\n logger?: Logger;\n /**\n * Called after a job failed because its last attempt lost its lease: nothing was running to\n * record the failure, so the host writes it (a build left `capturing`). May run on every\n * instance that finds the job, so it must be idempotent; a throw is logged and ignored.\n */\n onExhausted?: (job: DatabaseJob, error: string) => Promise<void>;\n}\n\n/** Default lease per attempt: long enough for a slow stage, short enough to recover a crash. */\nexport const DEFAULT_LEASE_MS = 5 * 60_000;\n\n/** Default `testing.retries` (ADR 0006, decision 11). */\nexport const DEFAULT_RETRIES = 2;\n\n/** A job of any kind, as `enqueueJob` takes it. */\nexport interface QueueJobInput {\n kind: CaptureJobKind;\n /** Build the job works on; notify jobs may have none. */\n buildId?: string | null;\n /** `capture_shards` row, for a shard capture job. */\n shard?: string;\n reqId?: string;\n traceparent?: string;\n /** Kind-specific fields (channel id, zip key, …), stored as JSON. */\n data?: Record<string, unknown>;\n /** Attempts allowed in total for this job; defaults to the queue's (`retries` + 1). */\n maxAttempts?: number;\n}\n\n/** A job claimed from the database queue. */\nexport interface DatabaseJob extends PollableJob {\n /** Id of the job row (`receipt` is the attempt row, `<jobId>:<attempt>`). */\n jobId: string;\n kind: CaptureJobKind;\n /** Attempt number, from 1 (`attempts` is the number made before this one). */\n attempt: number;\n maxAttempts: number;\n /** Kind-specific fields given at enqueue. */\n data: Record<string, unknown>;\n}\n\n/** The database queue: a {@link PollableCaptureQueue} plus multi-kind enqueue and a local wake. */\nexport interface DatabaseCaptureQueue extends PollableCaptureQueue {\n readonly lifecycle: AdapterLifecycle;\n poll(options?: { waitMs?: number }): Promise<DatabaseJob | null>;\n extend(job: PollableJob): Promise<LeaseRenewal>;\n /** Put a job of any kind on the queue; resolves to its job id. */\n enqueueJob(job: QueueJobInput): Promise<string>;\n /** Cancel a job by job id, or every unfinished job of a build (every kind) by build id. */\n cancel(id: string): Promise<boolean>;\n /** Read the job's state without renewing its lease (the 5 s cancel check). */\n inspect(job: PollableJob): Promise<LeaseRenewal>;\n /**\n * Resolve true when this instance enqueues a job (including one enqueued since the last `poll`\n * began, so no wake-up is lost), false after `ms`.\n */\n waitForWork(ms: number): Promise<boolean>;\n}\n\n/** State shared by the queue's modules. */\nexport interface QueueRuntime {\n model: CaptureJobModel;\n kinds: readonly CaptureJobKind[];\n leaseMs: number;\n maxAttempts: number;\n owner: string;\n now: () => number;\n timers?: QueueTimers;\n wake: WakeSignal;\n /** Wake version read when the latest poll began. */\n pollVersion: number;\n logger?: Logger;\n onExhausted?: DatabaseCaptureQueueOptions[\"onExhausted\"];\n}\n\n/** The capture-shaped job `enqueue` takes, re-exported for the modules. */\nexport type { CaptureJob };\n"],"mappings":";;;;;AAuCA,MAAa,mBAAmB;;AAGhC,MAAa,kBAAkB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { REAL_TIMERS } from "./timers.mjs";
|
|
5
|
+
// src/capture/db-queue/wake.ts
|
|
6
|
+
/** In-process wake signal: an enqueue on this instance wakes its waiting poller at once. */
|
|
7
|
+
/** Create a wake signal over `timers` (unref'd globals by default). */
|
|
8
|
+
function createWakeSignal(timers = REAL_TIMERS) {
|
|
9
|
+
const waiters = /* @__PURE__ */ new Set();
|
|
10
|
+
let closed = false;
|
|
11
|
+
let notifies = 0;
|
|
12
|
+
const settleAll = (woken) => {
|
|
13
|
+
for (const settle of waiters) settle(woken);
|
|
14
|
+
waiters.clear();
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
notify: () => {
|
|
18
|
+
notifies += 1;
|
|
19
|
+
settleAll(true);
|
|
20
|
+
},
|
|
21
|
+
version: () => notifies,
|
|
22
|
+
wait: async (ms, since) => {
|
|
23
|
+
if (closed || since !== void 0 && since !== notifies) return !closed;
|
|
24
|
+
return await waitFor(timers, waiters, ms);
|
|
25
|
+
},
|
|
26
|
+
close: () => {
|
|
27
|
+
closed = true;
|
|
28
|
+
settleAll(false);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function waitFor(timers, waiters, ms) {
|
|
33
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
34
|
+
const timer = timers.setTimeout(() => {
|
|
35
|
+
waiters.delete(settle);
|
|
36
|
+
resolve(false);
|
|
37
|
+
}, ms);
|
|
38
|
+
const settle = (woken) => {
|
|
39
|
+
timers.clearTimeout(timer);
|
|
40
|
+
resolve(woken);
|
|
41
|
+
};
|
|
42
|
+
waiters.add(settle);
|
|
43
|
+
return await promise;
|
|
44
|
+
}
|
|
45
|
+
export { createWakeSignal };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=wake.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake.mjs","names":[],"sources":["../../../src/capture/db-queue/wake.ts"],"sourcesContent":["/** In-process wake signal: an enqueue on this instance wakes its waiting poller at once. */\nimport { REAL_TIMERS, type QueueTimers } from \"./timers.ts\";\n\n/** Wakes waiters on local enqueue; other instances find the job on their next poll. */\nexport interface WakeSignal {\n /** Wake every current waiter. */\n notify(): void;\n /** Count of notifies so far; pass it to `wait` to catch a notify that came before the wait. */\n version(): number;\n /**\n * Resolve true when notified, false after `ms` or once closed. With `since`, resolve true at once\n * if a notify came after that version was read (no lost wake-up between a probe and its wait).\n */\n wait(ms: number, since?: number): Promise<boolean>;\n /** Release every waiter (false) and make later waits resolve at once; idempotent. */\n close(): void;\n}\n\n/** Create a wake signal over `timers` (unref'd globals by default). */\nexport function createWakeSignal(timers: QueueTimers = REAL_TIMERS): WakeSignal {\n const waiters = new Set<(woken: boolean) => void>();\n let closed = false;\n let notifies = 0;\n const settleAll = (woken: boolean): void => {\n for (const settle of waiters) {\n settle(woken);\n }\n waiters.clear();\n };\n return {\n notify: () => {\n notifies += 1;\n settleAll(true);\n },\n version: () => notifies,\n wait: async (ms, since) => {\n if (closed || (since !== undefined && since !== notifies)) {\n return !closed;\n }\n return await waitFor(timers, waiters, ms);\n },\n close: () => {\n closed = true;\n settleAll(false);\n },\n };\n}\n\nasync function waitFor(\n timers: QueueTimers,\n waiters: Set<(woken: boolean) => void>,\n ms: number,\n): Promise<boolean> {\n const { promise, resolve } = Promise.withResolvers<boolean>();\n const timer = timers.setTimeout(() => {\n waiters.delete(settle);\n resolve(false);\n }, ms);\n const settle = (woken: boolean): void => {\n timers.clearTimeout(timer);\n resolve(woken);\n };\n waiters.add(settle);\n return await promise;\n}\n"],"mappings":";;;;;;;AAmBA,SAAgB,iBAAiB,SAAsB,aAAyB;CAC9E,MAAM,0BAAU,IAAI,IAA8B;CAClD,IAAI,SAAS;CACb,IAAI,WAAW;CACf,MAAM,aAAa,UAAyB;EAC1C,KAAK,MAAM,UAAU,SACnB,OAAO,KAAK;EAEd,QAAQ,MAAM;CAChB;CACA,OAAO;EACL,cAAc;GACZ,YAAY;GACZ,UAAU,IAAI;EAChB;EACA,eAAe;EACf,MAAM,OAAO,IAAI,UAAU;GACzB,IAAI,UAAW,UAAU,KAAA,KAAa,UAAU,UAC9C,OAAO,CAAC;GAEV,OAAO,MAAM,QAAQ,QAAQ,SAAS,EAAE;EAC1C;EACA,aAAa;GACX,SAAS;GACT,UAAU,KAAK;EACjB;CACF;AACF;AAEA,eAAe,QACb,QACA,SACA,IACkB;CAClB,MAAM,EAAE,SAAS,YAAY,QAAQ,cAAuB;CAC5D,MAAM,QAAQ,OAAO,iBAAiB;EACpC,QAAQ,OAAO,MAAM;EACrB,QAAQ,KAAK;CACf,GAAG,EAAE;CACL,MAAM,UAAU,UAAyB;EACvC,OAAO,aAAa,KAAK;EACzB,QAAQ,KAAK;CACf;CACA,QAAQ,IAAI,MAAM;CAClB,OAAO,MAAM;AACf"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/capture/design.ts
|
|
5
|
+
/**
|
|
6
|
+
* Resolve a story's design URL. `storyshelf.figma` (plain string) wins over the
|
|
7
|
+
* `design` addon shape (`string | {url} | {type,url} | {type,url}[]`, first URL wins).
|
|
8
|
+
*/
|
|
9
|
+
function extractDesignUrl(parameters, parse) {
|
|
10
|
+
const explicit = parameters?.storyshelf?.figma;
|
|
11
|
+
const raw = typeof explicit === "string" && explicit.trim() !== "" ? explicit : firstDesignUrl(parameters?.design);
|
|
12
|
+
if (raw === void 0 || raw.trim() === "") return {};
|
|
13
|
+
const parsed = parse(raw);
|
|
14
|
+
return parsed ? { url: parsed.url } : { invalid: raw };
|
|
15
|
+
}
|
|
16
|
+
/** First URL of the `design` addon value, whatever shape it takes. */
|
|
17
|
+
function firstDesignUrl(value) {
|
|
18
|
+
if (typeof value === "string") return value;
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
for (const item of value) {
|
|
21
|
+
const url = firstDesignUrl(item);
|
|
22
|
+
if (url !== void 0) return url;
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const url = value?.url;
|
|
27
|
+
return typeof url === "string" ? url : void 0;
|
|
28
|
+
}
|
|
29
|
+
/** Log (once per story) design values that were declared but are not usable Figma URLs. */
|
|
30
|
+
function logInvalidDesigns(logger, stories) {
|
|
31
|
+
for (const story of stories) if (story.designInvalid !== void 0) logger?.warn({
|
|
32
|
+
storyId: story.id,
|
|
33
|
+
design: story.designInvalid
|
|
34
|
+
}, "ignored invalid design url");
|
|
35
|
+
}
|
|
36
|
+
export { extractDesignUrl, logInvalidDesigns };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=design.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design.mjs","names":[],"sources":["../../src/capture/design.ts"],"sourcesContent":["/** Design-source extraction from Storybook story parameters (`design` addon + `storyshelf.figma`). */\n\n/** Story parameters relevant to design linking, as serialized in the Storybook index. */\nexport interface DesignParameters {\n design?: unknown;\n storyshelf?: { figma?: unknown };\n}\n\n/** Parses a declared link into its canonical URL; null when no design provider accepts it. */\nexport type DesignUrlParser = (raw: string) => { url: string } | null;\n\n/** Outcome of extraction: a valid design URL, a rejected raw value, or nothing declared. */\nexport interface DesignExtraction {\n url?: string;\n /** Raw value that was declared but is not a usable design URL (logged by the caller). */\n invalid?: string;\n}\n\n/**\n * Resolve a story's design URL. `storyshelf.figma` (plain string) wins over the\n * `design` addon shape (`string | {url} | {type,url} | {type,url}[]`, first URL wins).\n */\nexport function extractDesignUrl(\n parameters: DesignParameters | undefined,\n parse: DesignUrlParser,\n): DesignExtraction {\n const explicit = parameters?.storyshelf?.figma;\n const raw =\n typeof explicit === \"string\" && explicit.trim() !== \"\"\n ? explicit\n : firstDesignUrl(parameters?.design);\n if (raw === undefined || raw.trim() === \"\") return {};\n const parsed = parse(raw);\n return parsed ? { url: parsed.url } : { invalid: raw };\n}\n\n/** First URL of the `design` addon value, whatever shape it takes. */\nfunction firstDesignUrl(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) {\n for (const item of value as unknown[]) {\n const url = firstDesignUrl(item);\n if (url !== undefined) return url;\n }\n return undefined;\n }\n const url = (value as { url?: unknown } | null | undefined)?.url;\n return typeof url === \"string\" ? url : undefined;\n}\n\n/** Log (once per story) design values that were declared but are not usable Figma URLs. */\nexport function logInvalidDesigns(\n logger: { warn(obj: object, msg: string): void } | undefined,\n stories: readonly { id: string; designInvalid?: string }[],\n): void {\n for (const story of stories) {\n if (story.designInvalid !== undefined) {\n logger?.warn(\n { storyId: story.id, design: story.designInvalid },\n \"ignored invalid design url\",\n );\n }\n }\n}\n"],"mappings":";;;;;;;;AAsBA,SAAgB,iBACd,YACA,OACkB;CAClB,MAAM,WAAW,YAAY,YAAY;CACzC,MAAM,MACJ,OAAO,aAAa,YAAY,SAAS,KAAK,MAAM,KAChD,WACA,eAAe,YAAY,MAAM;CACvC,IAAI,QAAQ,KAAA,KAAa,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC;CACpD,MAAM,SAAS,MAAM,GAAG;CACxB,OAAO,SAAS,EAAE,KAAK,OAAO,IAAI,IAAI,EAAE,SAAS,IAAI;AACvD;;AAGA,SAAS,eAAe,OAAoC;CAC1D,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,MAAM,QAAQ,OAAoB;GACrC,MAAM,MAAM,eAAe,IAAI;GAC/B,IAAI,QAAQ,KAAA,GAAW,OAAO;EAChC;EACA;CACF;CACA,MAAM,MAAO,OAAgD;CAC7D,OAAO,OAAO,QAAQ,WAAW,MAAM,KAAA;AACzC;;AAGA,SAAgB,kBACd,QACA,SACM;CACN,KAAK,MAAM,SAAS,SAClB,IAAI,MAAM,kBAAkB,KAAA,GAC1B,QAAQ,KACN;EAAE,SAAS,MAAM;EAAI,QAAQ,MAAM;CAAc,GACjD,4BACF;AAGN"}
|
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { DEFAULT_DIFF_OPTIONS, diffImagesAsync } from "@storyshelf/image";
|
|
5
|
+
// src/capture/diff-record.ts
|
|
6
|
+
/** Diff a stored screenshot against a baseline and persist the overlay; shared by capture and re-diff. */
|
|
7
7
|
/** Per-story `diffThreshold` when it is a finite number in 0..1; otherwise the project threshold. */
|
|
8
8
|
function resolvePixelThreshold(projectThreshold, override) {
|
|
9
9
|
return typeof override === "number" && Number.isFinite(override) && override >= 0 && override <= 1 ? override : projectThreshold;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Content-addressed screenshots share a path exactly when their bytes are equal, so the diff is
|
|
13
|
+
* empty without reading either image. Dimensions are not known (nothing was read) and report 0.
|
|
14
|
+
*/
|
|
15
|
+
function samePathResult() {
|
|
16
|
+
const unread = {
|
|
17
|
+
width: 0,
|
|
18
|
+
height: 0
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
passed: true,
|
|
22
|
+
diffPixels: 0,
|
|
23
|
+
diffRatio: 0,
|
|
24
|
+
diffImage: null,
|
|
25
|
+
baselineDimensions: unread,
|
|
26
|
+
currentDimensions: unread,
|
|
27
|
+
sizeChanged: false
|
|
28
|
+
};
|
|
29
|
+
}
|
|
11
30
|
/** Read two stored PNGs and diff them with the project's thresholds (optionally a per-story pixel threshold). */
|
|
12
31
|
async function diffStoredScreenshots(storage, project, baselinePath, currentPath, diffThreshold) {
|
|
32
|
+
if (baselinePath === currentPath) return samePathResult();
|
|
13
33
|
const current = await storage.read(currentPath);
|
|
14
34
|
const previous = await storage.read(baselinePath);
|
|
15
|
-
return
|
|
35
|
+
return await diffImagesAsync(previous, current, {
|
|
16
36
|
...DEFAULT_DIFF_OPTIONS,
|
|
17
37
|
pixelThreshold: resolvePixelThreshold(project.pixelThreshold, diffThreshold),
|
|
18
38
|
maxDiffRatio: project.maxDiffRatio
|
|
@@ -24,7 +44,6 @@ async function writeDiffOverlay(storage, path, result, passed) {
|
|
|
24
44
|
await storage.write(path, result.diffImage);
|
|
25
45
|
return path;
|
|
26
46
|
}
|
|
27
|
-
//#endregion
|
|
28
47
|
export { diffStoredScreenshots, resolvePixelThreshold, writeDiffOverlay };
|
|
29
48
|
|
|
30
49
|
//# sourceMappingURL=diff-record.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-record.mjs","names":[],"sources":["../../src/capture/diff-record.ts"],"sourcesContent":["/** Diff a stored screenshot against a baseline and persist the overlay; shared by capture and re-diff. */\nimport
|
|
1
|
+
{"version":3,"file":"diff-record.mjs","names":[],"sources":["../../src/capture/diff-record.ts"],"sourcesContent":["/** Diff a stored screenshot against a baseline and persist the overlay; shared by capture and re-diff. */\nimport { DEFAULT_DIFF_OPTIONS, diffImagesAsync, type DiffResult } from \"@storyshelf/image\";\nimport type { StorageAdapter } from \"../adapters/storage.ts\";\n\n/** Project thresholds that drive a diff. */\nexport interface DiffThresholds {\n pixelThreshold: number;\n maxDiffRatio: number;\n}\n\n/** Per-story `diffThreshold` when it is a finite number in 0..1; otherwise the project threshold. */\nexport function resolvePixelThreshold(projectThreshold: number, override?: number): number {\n const valid = typeof override === \"number\" && Number.isFinite(override);\n return valid && override >= 0 && override <= 1 ? override : projectThreshold;\n}\n\n/**\n * Content-addressed screenshots share a path exactly when their bytes are equal, so the diff is\n * empty without reading either image. Dimensions are not known (nothing was read) and report 0.\n */\nfunction samePathResult(): DiffResult {\n const unread = { width: 0, height: 0 };\n return {\n passed: true,\n diffPixels: 0,\n diffRatio: 0,\n diffImage: null,\n baselineDimensions: unread,\n currentDimensions: unread,\n sizeChanged: false,\n };\n}\n\n/** Read two stored PNGs and diff them with the project's thresholds (optionally a per-story pixel threshold). */\nexport async function diffStoredScreenshots(\n storage: StorageAdapter,\n project: DiffThresholds,\n baselinePath: string,\n currentPath: string,\n diffThreshold?: number,\n): Promise<DiffResult> {\n if (baselinePath === currentPath) {\n return samePathResult();\n }\n const current = await storage.read(currentPath);\n const previous = await storage.read(baselinePath);\n return await diffImagesAsync(previous, current, {\n ...DEFAULT_DIFF_OPTIONS,\n pixelThreshold: resolvePixelThreshold(project.pixelThreshold, diffThreshold),\n maxDiffRatio: project.maxDiffRatio,\n });\n}\n\n/** Write the diff overlay for a failing diff; returns the stored path, or null when none applies. */\nexport async function writeDiffOverlay(\n storage: StorageAdapter,\n path: string,\n result: Pick<DiffResult, \"diffImage\">,\n passed: boolean,\n): Promise<string | null> {\n if (passed || !result.diffImage) {\n return null;\n }\n await storage.write(path, result.diffImage);\n return path;\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,sBAAsB,kBAA0B,UAA2B;CAEzF,OADc,OAAO,aAAa,YAAY,OAAO,SAAS,QAAQ,KACtD,YAAY,KAAK,YAAY,IAAI,WAAW;AAC9D;;;;;AAMA,SAAS,iBAA6B;CACpC,MAAM,SAAS;EAAE,OAAO;EAAG,QAAQ;CAAE;CACrC,OAAO;EACL,QAAQ;EACR,YAAY;EACZ,WAAW;EACX,WAAW;EACX,oBAAoB;EACpB,mBAAmB;EACnB,aAAa;CACf;AACF;;AAGA,eAAsB,sBACpB,SACA,SACA,cACA,aACA,eACqB;CACrB,IAAI,iBAAiB,aACnB,OAAO,eAAe;CAExB,MAAM,UAAU,MAAM,QAAQ,KAAK,WAAW;CAC9C,MAAM,WAAW,MAAM,QAAQ,KAAK,YAAY;CAChD,OAAO,MAAM,gBAAgB,UAAU,SAAS;EAC9C,GAAG;EACH,gBAAgB,sBAAsB,QAAQ,gBAAgB,aAAa;EAC3E,cAAc,QAAQ;CACxB,CAAC;AACH;;AAGA,eAAsB,iBACpB,SACA,MACA,QACA,QACwB;CACxB,IAAI,UAAU,CAAC,OAAO,WACpB,OAAO;CAET,MAAM,QAAQ,MAAM,MAAM,OAAO,SAAS;CAC1C,OAAO;AACT"}
|
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
-
import { GitHostProvider } from "../adapter/git-host.mjs";
|
|
5
3
|
import { Logger } from "../logger.mjs";
|
|
6
|
-
import {
|
|
4
|
+
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
7
5
|
import { BuildTables } from "../models/build.mjs";
|
|
8
6
|
import { CaptureAttemptTables } from "../models/capture-attempt.mjs";
|
|
9
7
|
import { CaptureLogTables } from "../models/capture-log.mjs";
|
|
10
8
|
import { ProjectTables } from "../models/project.mjs";
|
|
9
|
+
import { JobLease } from "./job-lease.mjs";
|
|
11
10
|
import { CaptureJobOptions } from "./orchestrator.mjs";
|
|
12
|
-
import {
|
|
13
|
-
//#region src/capture/dispatch.d.ts
|
|
11
|
+
import { BuildStatePublisher } from "./build-state/types.mjs";
|
|
14
12
|
/** Build the queue's job runner: post pending, apply skip rules, capture, report. */
|
|
15
|
-
declare function createDispatchJob(deps: DispatchDeps): (job: CaptureDispatchJob) => Promise<void>;
|
|
13
|
+
declare function createDispatchJob(deps: DispatchDeps): (job: CaptureDispatchJob, lease?: JobLease) => Promise<void>;
|
|
16
14
|
/** Table handles required by dispatch. */
|
|
17
|
-
type DispatchTables = BuildTables & ProjectTables &
|
|
15
|
+
type DispatchTables = BuildTables & ProjectTables & CaptureAttemptTables & CaptureLogTables;
|
|
18
16
|
/** Dependencies for building the capture queue's job runner. */
|
|
19
17
|
interface DispatchDeps {
|
|
20
18
|
db: DatabaseAdapter;
|
|
21
19
|
tables: DispatchTables;
|
|
22
20
|
jobOptions: CaptureJobOptions;
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
/** Shows a build's current state on its git channels; called at every transition. */
|
|
22
|
+
buildState: BuildStatePublisher;
|
|
25
23
|
logger: Logger;
|
|
24
|
+
/** Redeliveries the queue allows a failing job; a shard's last try is its final word. */
|
|
25
|
+
maxRetries?: number | undefined;
|
|
26
26
|
}
|
|
27
27
|
/** A queued capture job. */
|
|
28
28
|
interface CaptureDispatchJob {
|
|
29
29
|
buildId: string;
|
|
30
|
+
/** A `capture_shards` row to render; absent for the build's own (plan or whole-build) job. */
|
|
31
|
+
shard?: string | undefined;
|
|
32
|
+
/** Times the queue has already delivered this job and seen it fail. */
|
|
33
|
+
attempts?: number | undefined;
|
|
30
34
|
reqId?: string;
|
|
31
35
|
/** W3C `traceparent` continuing the enqueueing request's trace. */
|
|
32
36
|
traceparent?: string;
|
|
33
37
|
}
|
|
34
|
-
//#endregion
|
|
35
38
|
export { CaptureDispatchJob, DispatchDeps, DispatchTables, createDispatchJob };
|
|
36
39
|
//# sourceMappingURL=dispatch.d.mts.map
|