@storyshelf/core 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/capture-queue.d.mts +0 -2
- package/dist/adapter/capture-runner.d.mts +9 -4
- package/dist/adapter/capture-runner.mjs +6 -2
- package/dist/adapter/database.d.mts +63 -3
- package/dist/adapter/database.mjs +4 -3
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/design.d.mts +0 -2
- package/dist/adapter/design.mjs +1 -2
- package/dist/adapter/email-sender.d.mts +0 -2
- package/dist/adapter/metadata.d.mts +0 -2
- package/dist/adapter/oauth.d.mts +0 -2
- package/dist/adapter/setup.d.mts +0 -2
- package/dist/adapter/setup.mjs +1 -2
- package/dist/adapter/storage.d.mts +1 -3
- package/dist/adapter/webhook-events.d.mts +0 -2
- package/dist/adapter/webhook-events.mjs +12 -13
- package/dist/adapter/webhook-events.mjs.map +1 -1
- package/dist/adapters/capture-target-offers.d.mts +0 -2
- package/dist/adapters/capture-target-offers.mjs +1 -2
- package/dist/adapters/capture-target.d.mts +0 -2
- package/dist/adapters/capture-target.mjs +1 -2
- package/dist/adapters/notifier/build-comment.d.mts +0 -2
- package/dist/adapters/notifier/build-comment.mjs +1 -2
- package/dist/adapters/notifier/build-state.d.mts +0 -2
- package/dist/adapters/notifier/build-state.mjs +1 -2
- package/dist/adapters/notifier/events.d.mts +0 -2
- package/dist/adapters/notifier/events.mjs +1 -2
- package/dist/adapters/notifier/format.d.mts +0 -2
- package/dist/adapters/notifier/format.mjs +1 -2
- package/dist/adapters/notifier/provider.d.mts +0 -2
- package/dist/adapters/notifier/provider.mjs +1 -2
- package/dist/adapters/notifier/state.d.mts +0 -2
- package/dist/adapters/notifier/state.mjs +1 -2
- package/dist/adapters/notifier/types.d.mts +0 -2
- package/dist/adapters/remote-browser.d.mts +112 -31
- package/dist/adapters/remote-browser.mjs +132 -34
- package/dist/adapters/remote-browser.mjs.map +1 -1
- package/dist/adapters/remote-lease-attempt.mjs +39 -0
- package/dist/adapters/remote-lease-attempt.mjs.map +1 -0
- package/dist/adapters/remote-lease-error.d.mts +25 -0
- package/dist/adapters/remote-lease-error.mjs +54 -0
- package/dist/adapters/remote-lease-error.mjs.map +1 -0
- package/dist/adapters/remote-lease-held.d.mts +15 -0
- package/dist/adapters/remote-lease-held.mjs +86 -0
- package/dist/adapters/remote-lease-held.mjs.map +1 -0
- package/dist/adapters/remote-lease-shutdown.d.mts +12 -0
- package/dist/adapters/remote-lease-shutdown.mjs +32 -0
- package/dist/adapters/remote-lease-shutdown.mjs.map +1 -0
- package/dist/adapters/remote-lease.d.mts +39 -0
- package/dist/adapters/remote-lease.mjs +175 -0
- package/dist/adapters/remote-lease.mjs.map +1 -0
- package/dist/adapters/remote-limiter.mjs +121 -0
- package/dist/adapters/remote-limiter.mjs.map +1 -0
- package/dist/adapters/remote-pool.d.mts +56 -0
- package/dist/adapters/remote-pool.mjs +195 -0
- package/dist/adapters/remote-pool.mjs.map +1 -0
- package/dist/adapters/render-runs.d.mts +0 -2
- package/dist/adapters/render-runs.mjs +1 -2
- package/dist/adapters/setup-runner.d.mts +0 -2
- package/dist/adapters/setup-runner.mjs +1 -2
- package/dist/adapters/sources.d.mts +0 -2
- package/dist/adapters/sources.mjs +1 -2
- package/dist/adapters/validate.d.mts +0 -2
- package/dist/adapters/validate.mjs +2 -2
- package/dist/adapters/validate.mjs.map +1 -1
- package/dist/ai.d.mts +0 -2
- package/dist/ai.mjs +1 -2
- package/dist/auth.d.mts +0 -2
- package/dist/auth.mjs +1 -2
- package/dist/brand-packs.d.mts +0 -2
- package/dist/brand-packs.mjs +0 -1
- package/dist/capture/a11y/axe-source.d.mts +0 -2
- package/dist/capture/a11y/axe-source.mjs +1 -2
- package/dist/capture/a11y/in-page.d.mts +1 -3
- package/dist/capture/a11y/in-page.mjs +3 -4
- package/dist/capture/a11y/in-page.mjs.map +1 -1
- package/dist/capture/a11y/map.d.mts +0 -2
- package/dist/capture/a11y/map.mjs +1 -2
- package/dist/capture/a11y/options.d.mts +0 -2
- package/dist/capture/a11y/options.mjs +1 -2
- package/dist/capture/adapter.d.mts +5 -2
- package/dist/capture/adapter.mjs +1 -2
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +0 -2
- package/dist/capture/affected.mjs +1 -2
- package/dist/capture/attempt-logger.mjs +1 -2
- package/dist/capture/browsers.d.mts +0 -2
- package/dist/capture/browsers.mjs +1 -2
- package/dist/capture/build-state/deliver.d.mts +0 -2
- package/dist/capture/build-state/deliver.mjs +1 -2
- package/dist/capture/build-state/notify-job.d.mts +0 -2
- package/dist/capture/build-state/notify-job.mjs +1 -2
- package/dist/capture/build-state/publisher.d.mts +0 -2
- package/dist/capture/build-state/publisher.mjs +1 -2
- package/dist/capture/build-state/resume.d.mts +0 -2
- package/dist/capture/build-state/resume.mjs +1 -2
- package/dist/capture/build-state/types.d.mts +1 -3
- package/dist/capture/catalog/catalogue.d.mts +0 -2
- package/dist/capture/catalog/catalogue.mjs +1 -2
- package/dist/capture/catalog/components.d.mts +0 -2
- package/dist/capture/catalog/components.mjs +1 -2
- package/dist/capture/catalog/history.d.mts +0 -2
- package/dist/capture/catalog/history.mjs +1 -2
- package/dist/capture/catalog/hook.d.mts +0 -2
- package/dist/capture/catalog/hook.mjs +1 -2
- package/dist/capture/catalog/index.d.mts +2 -2
- package/dist/capture/catalog/load.d.mts +0 -2
- package/dist/capture/catalog/load.mjs +1 -2
- package/dist/capture/catalog/parse.d.mts +0 -2
- package/dist/capture/catalog/parse.mjs +1 -2
- package/dist/capture/catalog/read.d.mts +6 -3
- package/dist/capture/catalog/read.mjs +14 -8
- package/dist/capture/catalog/read.mjs.map +1 -1
- package/dist/capture/catalog/types.d.mts +0 -2
- package/dist/capture/comparison-reference.d.mts +27 -0
- package/dist/capture/comparison-reference.mjs +75 -0
- package/dist/capture/comparison-reference.mjs.map +1 -0
- package/dist/capture/consumer/capture-handler.d.mts +1 -3
- package/dist/capture/consumer/capture-handler.mjs +1 -2
- package/dist/capture/consumer/idle.d.mts +0 -2
- package/dist/capture/consumer/idle.mjs +1 -2
- package/dist/capture/consumer/index.d.mts +0 -2
- package/dist/capture/consumer/index.mjs +1 -2
- package/dist/capture/consumer/loop.mjs +1 -2
- package/dist/capture/consumer/metrics.d.mts +0 -2
- package/dist/capture/consumer/metrics.mjs +1 -2
- package/dist/capture/consumer/retry.d.mts +0 -2
- package/dist/capture/consumer/retry.mjs +1 -2
- package/dist/capture/consumer/run-job.mjs +1 -2
- package/dist/capture/consumer/startup.mjs +1 -2
- package/dist/capture/consumer/types.d.mts +0 -2
- package/dist/capture/crash-failure.d.mts +0 -2
- package/dist/capture/crash-failure.mjs +1 -2
- package/dist/capture/db-queue/cadence.d.mts +0 -2
- package/dist/capture/db-queue/cadence.mjs +1 -2
- package/dist/capture/db-queue/claim.d.mts +0 -2
- package/dist/capture/db-queue/claim.mjs +20 -4
- package/dist/capture/db-queue/claim.mjs.map +1 -1
- package/dist/capture/db-queue/clock.mjs +1 -2
- package/dist/capture/db-queue/codec.mjs +1 -2
- package/dist/capture/db-queue/index.d.mts +0 -2
- package/dist/capture/db-queue/index.mjs +3 -3
- package/dist/capture/db-queue/index.mjs.map +1 -1
- package/dist/capture/db-queue/keeper.d.mts +0 -2
- package/dist/capture/db-queue/keeper.mjs +1 -2
- package/dist/capture/db-queue/lease.mjs +1 -2
- package/dist/capture/db-queue/lifecycle.mjs +1 -2
- package/dist/capture/db-queue/operations.mjs +1 -2
- package/dist/capture/db-queue/poll-loop.d.mts +0 -2
- package/dist/capture/db-queue/poll-loop.mjs +1 -2
- package/dist/capture/db-queue/poll.d.mts +0 -2
- package/dist/capture/db-queue/poll.mjs +1 -2
- package/dist/capture/db-queue/timers.d.mts +0 -2
- package/dist/capture/db-queue/timers.mjs +1 -2
- package/dist/capture/db-queue/types.d.mts +0 -2
- package/dist/capture/db-queue/types.mjs +1 -2
- package/dist/capture/db-queue/types.mjs.map +1 -1
- package/dist/capture/db-queue/wake.mjs +1 -2
- package/dist/capture/design.mjs +1 -2
- package/dist/capture/diff-record.mjs +1 -2
- package/dist/capture/dispatch.d.mts +1 -3
- package/dist/capture/dispatch.mjs +17 -5
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/enrich.mjs +1 -2
- package/dist/capture/failure-sets.mjs +1 -2
- package/dist/capture/fingerprint.d.mts +0 -2
- package/dist/capture/fingerprint.mjs +1 -2
- package/dist/capture/forked/channel.d.mts +0 -2
- package/dist/capture/forked/child.d.mts +0 -2
- package/dist/capture/forked/child.mjs +1 -2
- package/dist/capture/forked/crash-tracker.mjs +1 -2
- package/dist/capture/forked/decision.d.mts +0 -2
- package/dist/capture/forked/decision.mjs +1 -2
- package/dist/capture/forked/exit.mjs +1 -2
- package/dist/capture/forked/fork.d.mts +0 -2
- package/dist/capture/forked/fork.mjs +1 -2
- package/dist/capture/forked/forked-capture.d.mts +0 -2
- package/dist/capture/forked/forked-capture.mjs +1 -2
- package/dist/capture/forked/lease-book.mjs +1 -2
- package/dist/capture/forked/protocol.d.mts +0 -2
- package/dist/capture/forked/protocol.mjs +1 -2
- package/dist/capture/forked/runs.mjs +1 -2
- package/dist/capture/guards.mjs +1 -2
- package/dist/capture/ignore-regions.d.mts +36 -0
- package/dist/capture/ignore-regions.mjs +65 -0
- package/dist/capture/ignore-regions.mjs.map +1 -0
- package/dist/capture/isolate.mjs +1 -2
- package/dist/capture/job-lease.d.mts +0 -2
- package/dist/capture/job-lease.mjs +1 -2
- package/dist/capture/matrix.mjs +4 -4
- package/dist/capture/matrix.mjs.map +1 -1
- package/dist/capture/modes.d.mts +0 -2
- package/dist/capture/modes.mjs +2 -3
- package/dist/capture/modes.mjs.map +1 -1
- package/dist/capture/orchestrator.d.mts +0 -2
- package/dist/capture/orchestrator.mjs +2 -3
- package/dist/capture/pipeline.d.mts +0 -2
- package/dist/capture/pipeline.mjs +37 -6
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/progress.d.mts +0 -2
- package/dist/capture/progress.mjs +1 -2
- package/dist/capture/publish/accept.d.mts +0 -2
- package/dist/capture/publish/accept.mjs +1 -2
- package/dist/capture/publish/complete.d.mts +1 -3
- package/dist/capture/publish/complete.mjs +1 -2
- package/dist/capture/publish/extract.d.mts +0 -2
- package/dist/capture/publish/extract.mjs +6 -5
- package/dist/capture/publish/extract.mjs.map +1 -1
- package/dist/capture/publish/handler.d.mts +1 -3
- package/dist/capture/publish/handler.mjs +1 -2
- package/dist/capture/publish/index.d.mts +2 -1
- package/dist/capture/publish/invalid-zip.d.mts +8 -0
- package/dist/capture/publish/invalid-zip.mjs +11 -0
- package/dist/capture/publish/invalid-zip.mjs.map +1 -0
- package/dist/capture/publish/limits.d.mts +0 -2
- package/dist/capture/publish/limits.mjs +1 -2
- package/dist/capture/publish/published.d.mts +0 -2
- package/dist/capture/publish/published.mjs +1 -2
- package/dist/capture/publish/run.d.mts +1 -3
- package/dist/capture/publish/run.mjs +1 -2
- package/dist/capture/rediff.d.mts +1 -3
- package/dist/capture/rediff.mjs +19 -6
- package/dist/capture/rediff.mjs.map +1 -1
- package/dist/capture/render.mjs +1 -2
- package/dist/capture/render.mjs.map +1 -1
- package/dist/capture/scratch.d.mts +0 -2
- package/dist/capture/scratch.mjs +2 -4
- package/dist/capture/scratch.mjs.map +1 -1
- package/dist/capture/shard-plan.mjs +1 -2
- package/dist/capture/shards/context.mjs +3 -3
- package/dist/capture/shards/context.mjs.map +1 -1
- package/dist/capture/shards/execute.mjs +4 -3
- package/dist/capture/shards/execute.mjs.map +1 -1
- package/dist/capture/shards/fan-out.mjs +1 -2
- package/dist/capture/shards/history.mjs +1 -2
- package/dist/capture/shards/reduce.mjs +1 -2
- package/dist/capture/sizing.d.mts +0 -2
- package/dist/capture/sizing.mjs +1 -2
- package/dist/capture/skip-checks.mjs +1 -2
- package/dist/capture/statics.d.mts +0 -2
- package/dist/capture/statics.mjs +2 -4
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/storybook-urls.d.mts +0 -2
- package/dist/capture/storybook-urls.mjs +3 -3
- package/dist/capture/storybook-urls.mjs.map +1 -1
- package/dist/capture/storybook.d.mts +0 -2
- package/dist/capture/storybook.mjs +8 -4
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture/target.mjs +1 -2
- package/dist/capture/targets.d.mts +0 -2
- package/dist/capture/targets.mjs +1 -2
- package/dist/capture/tests.d.mts +0 -2
- package/dist/capture/tests.mjs +13 -3
- package/dist/capture/tests.mjs.map +1 -1
- package/dist/capture/token-chunks.mjs +24 -7
- package/dist/capture/token-chunks.mjs.map +1 -1
- package/dist/capture.d.mts +5 -2
- package/dist/capture.mjs +5 -2
- package/dist/config.d.mts +16 -3
- package/dist/config.mjs +6 -3
- package/dist/config.mjs.map +1 -1
- package/dist/diff.d.mts +0 -2
- package/dist/diff.mjs +1 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/insights/budget.d.mts +0 -2
- package/dist/insights/budget.mjs +1 -2
- package/dist/insights/envelope.d.mts +0 -2
- package/dist/insights/envelope.mjs +1 -2
- package/dist/insights/evidence-health.d.mts +0 -2
- package/dist/insights/evidence-health.mjs +1 -2
- package/dist/insights/evidence.d.mts +0 -2
- package/dist/insights/evidence.mjs +1 -2
- package/dist/insights/hash.d.mts +0 -2
- package/dist/insights/hash.mjs +1 -2
- package/dist/insights/limits.d.mts +0 -2
- package/dist/insights/limits.mjs +1 -2
- package/dist/insights/prompts/v1.d.mts +0 -2
- package/dist/insights/prompts/v1.mjs +1 -2
- package/dist/insights/redact.d.mts +0 -2
- package/dist/insights/redact.mjs +1 -2
- package/dist/insights/text.mjs +1 -2
- package/dist/logger.d.mts +0 -2
- package/dist/logger.mjs +1 -2
- package/dist/models/ai-budget-alert.d.mts +0 -2
- package/dist/models/ai-budget-alert.mjs +1 -2
- package/dist/models/ai-usage.d.mts +0 -2
- package/dist/models/ai-usage.mjs +1 -2
- package/dist/models/baseline-approval.d.mts +18 -0
- package/dist/models/baseline-approval.mjs +41 -0
- package/dist/models/baseline-approval.mjs.map +1 -0
- package/dist/models/baseline-archive.d.mts +0 -2
- package/dist/models/baseline-archive.mjs +1 -2
- package/dist/models/baseline-atomic.mjs +66 -0
- package/dist/models/baseline-atomic.mjs.map +1 -0
- package/dist/models/baseline-conflict.d.mts +6 -0
- package/dist/models/baseline-conflict.mjs +9 -0
- package/dist/models/baseline-conflict.mjs.map +1 -0
- package/dist/models/baseline-export.d.mts +0 -2
- package/dist/models/baseline-export.mjs +1 -2
- package/dist/models/baseline-import.mjs +1 -2
- package/dist/models/baseline-origin.d.mts +16 -0
- package/dist/models/baseline-origin.mjs +35 -0
- package/dist/models/baseline-origin.mjs.map +1 -0
- package/dist/models/baseline-status.d.mts +0 -2
- package/dist/models/baseline-status.mjs +1 -2
- package/dist/models/baseline-transfer.d.mts +1 -2
- package/dist/models/baseline-transfer.mjs +30 -2
- package/dist/models/baseline-transfer.mjs.map +1 -1
- package/dist/models/baseline.d.mts +5 -2
- package/dist/models/baseline.mjs +91 -12
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build-component.d.mts +0 -2
- package/dist/models/build-component.mjs +1 -2
- package/dist/models/build-review-status.d.mts +0 -2
- package/dist/models/build-review-status.mjs +1 -2
- package/dist/models/build-review.d.mts +0 -2
- package/dist/models/build-review.mjs +1 -2
- package/dist/models/build.d.mts +1 -3
- package/dist/models/build.mjs +14 -15
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +0 -2
- package/dist/models/capture-attempt.mjs +1 -2
- package/dist/models/capture-job.d.mts +0 -2
- package/dist/models/capture-job.mjs +1 -2
- package/dist/models/capture-log.d.mts +0 -2
- package/dist/models/capture-log.mjs +1 -2
- package/dist/models/capture-shard.d.mts +0 -2
- package/dist/models/capture-shard.mjs +1 -2
- package/dist/models/changeset.d.mts +0 -2
- package/dist/models/changeset.mjs +1 -2
- package/dist/models/columns.mjs +1 -2
- package/dist/models/comment.d.mts +0 -2
- package/dist/models/comment.mjs +1 -2
- package/dist/models/component.d.mts +0 -2
- package/dist/models/component.mjs +1 -2
- package/dist/models/connections.d.mts +0 -2
- package/dist/models/connections.mjs +1 -2
- package/dist/models/content-ref.d.mts +0 -2
- package/dist/models/content-ref.mjs +1 -2
- package/dist/models/credentials.d.mts +0 -2
- package/dist/models/credentials.mjs +1 -2
- package/dist/models/design-credentials.d.mts +0 -2
- package/dist/models/design-credentials.mjs +1 -2
- package/dist/models/design-health.d.mts +0 -2
- package/dist/models/design-health.mjs +1 -2
- package/dist/models/design-nodes.d.mts +2 -4
- package/dist/models/design-nodes.mjs +1 -2
- package/dist/models/design-renders.mjs +1 -2
- package/dist/models/design-resolve.d.mts +0 -2
- package/dist/models/design-resolve.mjs +1 -2
- package/dist/models/design.d.mts +0 -2
- package/dist/models/design.mjs +1 -2
- package/dist/models/inherited-ratio.d.mts +0 -2
- package/dist/models/inherited-ratio.mjs +1 -2
- package/dist/models/insight.d.mts +0 -2
- package/dist/models/insight.mjs +1 -2
- package/dist/models/label.d.mts +0 -2
- package/dist/models/label.mjs +1 -2
- package/dist/models/member.d.mts +0 -2
- package/dist/models/member.mjs +1 -2
- package/dist/models/notification-channel.d.mts +0 -2
- package/dist/models/notification-channel.mjs +1 -2
- package/dist/models/notification-subscription.d.mts +0 -2
- package/dist/models/notification-subscription.mjs +1 -2
- package/dist/models/project-group-mapping.d.mts +0 -2
- package/dist/models/project-group-mapping.mjs +1 -2
- package/dist/models/project.d.mts +0 -2
- package/dist/models/project.mjs +1 -2
- package/dist/models/public-origin.d.mts +0 -2
- package/dist/models/public-origin.mjs +1 -2
- package/dist/models/review-switch-off.d.mts +0 -2
- package/dist/models/review-switch-off.mjs +1 -2
- package/dist/models/site-settings.d.mts +0 -2
- package/dist/models/site-settings.mjs +1 -2
- package/dist/models/snapshot.d.mts +3 -2
- package/dist/models/snapshot.mjs +4 -2
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/token.d.mts +0 -2
- package/dist/models/token.mjs +1 -2
- package/dist/models/usage.d.mts +0 -2
- package/dist/models/usage.mjs +1 -2
- package/dist/models/user.d.mts +0 -2
- package/dist/models/user.mjs +1 -2
- package/dist/models/webhook.d.mts +0 -2
- package/dist/models/webhook.mjs +1 -2
- package/dist/models.d.mts +5 -2
- package/dist/models.mjs +5 -2
- package/dist/options.d.mts +0 -2
- package/dist/options.mjs +2 -4
- package/dist/options.mjs.map +1 -1
- package/dist/paths.d.mts +3 -3
- package/dist/paths.mjs +7 -3
- package/dist/paths.mjs.map +1 -1
- package/dist/retention/ai.d.mts +1 -3
- package/dist/retention/ai.mjs +0 -1
- package/dist/retention/pending.mjs +1 -2
- package/dist/retention/published-gzip-sweep.mjs +28 -0
- package/dist/retention/published-gzip-sweep.mjs.map +1 -0
- package/dist/retention/screenshot-sweep.d.mts +0 -2
- package/dist/retention/screenshot-sweep.mjs +1 -2
- package/dist/retention.d.mts +0 -2
- package/dist/retention.mjs +5 -2
- package/dist/retention.mjs.map +1 -1
- package/dist/schema/baseline.d.mts +2 -2
- package/dist/schema/build-component.d.mts +0 -2
- package/dist/schema/build-review.d.mts +0 -2
- package/dist/schema/build.d.mts +0 -2
- package/dist/schema/capture-attempt.d.mts +0 -2
- package/dist/schema/capture-job.d.mts +0 -2
- package/dist/schema/capture-shard.d.mts +0 -2
- package/dist/schema/comment.d.mts +0 -2
- package/dist/schema/connection.d.mts +0 -2
- package/dist/schema/content-ref.d.mts +0 -2
- package/dist/schema/design.d.mts +0 -2
- package/dist/schema/insight.d.mts +0 -2
- package/dist/schema/label.d.mts +0 -2
- package/dist/schema/member.d.mts +0 -2
- package/dist/schema/notification.d.mts +0 -2
- package/dist/schema/project-group-mapping.d.mts +0 -2
- package/dist/schema/project.d.mts +0 -2
- package/dist/schema/site-setting.d.mts +0 -2
- package/dist/schema/snapshot.d.mts +5 -2
- package/dist/schema/token.d.mts +0 -2
- package/dist/schema/usage.d.mts +0 -2
- package/dist/schema/user.d.mts +0 -2
- package/dist/schema/webhook.d.mts +0 -2
- package/dist/schema.d.mts +4 -6
- package/dist/serverless.d.mts +0 -2
- package/dist/serverless.mjs +1 -2
- package/dist/test-helpers/build-reference-contract.d.mts +14 -0
- package/dist/test-helpers/build-reference-contract.mjs +66 -0
- package/dist/test-helpers/build-reference-contract.mjs.map +1 -0
- package/dist/test-helpers/create-project.d.mts +0 -2
- package/dist/test-helpers/create-project.mjs +1 -2
- package/dist/test-helpers/database-contract.d.mts +0 -2
- package/dist/test-helpers/database-contract.mjs +37 -2
- package/dist/test-helpers/database-contract.mjs.map +1 -1
- package/dist/test-helpers/deferred.d.mts +0 -2
- package/dist/test-helpers/deferred.mjs +1 -2
- package/dist/test-helpers/design-contract.d.mts +0 -2
- package/dist/test-helpers/design-contract.mjs +1 -2
- package/dist/test-helpers/fake-adapters.d.mts +0 -2
- package/dist/test-helpers/fake-adapters.mjs +1 -2
- package/dist/test-helpers/fake-database.d.mts +0 -2
- package/dist/test-helpers/fake-database.mjs +7 -2
- package/dist/test-helpers/fake-database.mjs.map +1 -1
- package/dist/test-helpers/fake-design.d.mts +0 -2
- package/dist/test-helpers/fake-design.mjs +1 -2
- package/dist/test-helpers/fake-notifier.d.mts +0 -2
- package/dist/test-helpers/fake-notifier.mjs +1 -2
- package/dist/test-helpers/fake-storage.d.mts +0 -2
- package/dist/test-helpers/fake-storage.mjs +1 -2
- package/dist/test-helpers/fake-tables.mjs +5 -2
- package/dist/test-helpers/fake-tables.mjs.map +1 -1
- package/dist/test-helpers/manual-clock.d.mts +0 -2
- package/dist/test-helpers/manual-clock.mjs +1 -2
- package/dist/test-helpers/notifier-contract.d.mts +0 -2
- package/dist/test-helpers/notifier-contract.mjs +1 -2
- package/dist/test-helpers/queue-contract.d.mts +0 -2
- package/dist/test-helpers/queue-contract.mjs +1 -2
- package/dist/test-helpers/queue-multi-instance.d.mts +0 -2
- package/dist/test-helpers/queue-multi-instance.mjs +1 -2
- package/dist/test-helpers/runner-contract.d.mts +0 -2
- package/dist/test-helpers/runner-contract.mjs +1 -2
- package/dist/test-helpers/sql-chunks.mjs +2 -2
- package/dist/test-helpers/sql-chunks.mjs.map +1 -1
- package/dist/test-helpers/storage-contract.d.mts +0 -2
- package/dist/test-helpers/storage-contract.mjs +1 -2
- package/dist/test-helpers.d.mts +2 -1
- package/dist/test-helpers.mjs +2 -1
- package/dist/tracing.mjs +36 -6
- package/dist/tracing.mjs.map +1 -1
- package/dist/types.d.mts +0 -2
- package/dist/types.mjs +1 -2
- package/dist/urls.d.mts +0 -2
- package/dist/urls.mjs +1 -2
- package/dist/utils/adaptive-concurrency.d.mts +0 -2
- package/dist/utils/adaptive-concurrency.mjs +1 -2
- package/dist/utils/connect-retry.d.mts +2 -2
- package/dist/utils/connect-retry.mjs +2 -3
- package/dist/utils/connect-retry.mjs.map +1 -1
- package/dist/utils/encrypt.d.mts +0 -2
- package/dist/utils/encrypt.mjs +1 -2
- package/dist/utils/environment.d.mts +0 -2
- package/dist/utils/environment.mjs +1 -2
- package/dist/utils/hash.d.mts +0 -2
- package/dist/utils/hash.mjs +1 -2
- package/dist/utils/http.d.mts +13 -3
- package/dist/utils/http.mjs +79 -17
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/map-adaptive.d.mts +0 -2
- package/dist/utils/map-adaptive.mjs +1 -2
- package/dist/utils/map-limit.d.mts +0 -2
- package/dist/utils/map-limit.mjs +1 -2
- package/dist/utils/mime.d.mts +0 -2
- package/dist/utils/mime.mjs +1 -2
- package/dist/utils/page-limiter.d.mts +0 -2
- package/dist/utils/page-limiter.mjs +1 -2
- package/dist/utils/path-security.d.mts +0 -2
- package/dist/utils/path-security.mjs +2 -4
- package/dist/utils/path-security.mjs.map +1 -1
- package/dist/utils/public-origin.d.mts +0 -2
- package/dist/utils/public-origin.mjs +1 -2
- package/dist/utils/redact.d.mts +0 -2
- package/dist/utils/redact.mjs +1 -2
- package/dist/utils/remote-environment.d.mts +40 -3
- package/dist/utils/remote-environment.mjs +52 -3
- package/dist/utils/remote-environment.mjs.map +1 -1
- package/dist/utils/resources.d.mts +0 -2
- package/dist/utils/resources.mjs +1 -2
- package/dist/utils/screenshot-store.d.mts +0 -2
- package/dist/utils/screenshot-store.mjs +1 -2
- package/dist/utils/session-gate.d.mts +7 -6
- package/dist/utils/session-gate.mjs +28 -12
- package/dist/utils/session-gate.mjs.map +1 -1
- package/dist/utils/storybook-token.d.mts +11 -3
- package/dist/utils/storybook-token.mjs +10 -9
- package/dist/utils/storybook-token.mjs.map +1 -1
- package/dist/utils/storybook-url.d.mts +0 -2
- package/dist/utils/storybook-url.mjs +1 -2
- package/dist/utils/timing.d.mts +0 -2
- package/dist/utils/timing.mjs +1 -2
- package/dist/utils/ulid.d.mts +0 -2
- package/dist/utils/ulid.mjs +1 -2
- package/dist/utils/zip-read.mjs +1 -2
- package/dist/utils/zip-write.d.mts +0 -2
- package/dist/utils/zip-write.mjs +1 -2
- package/dist/utils.d.mts +5 -5
- package/dist/utils.mjs +5 -5
- package/package.json +6 -6
package/dist/retention.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retention.mjs","names":[],"sources":["../src/retention/purge.ts"],"sourcesContent":["import { and, desc, eq, inArray, lt } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { Logger } from \"pino\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { StorageAdapter } from \"../adapters/storage.ts\";\nimport { BaselineModel } from \"../models/baseline.ts\";\nimport { BuildComponentModel } from \"../models/build-component.ts\";\nimport { BuildModel, type BuildTables } from \"../models/build.ts\";\nimport { CaptureJobModel } from \"../models/capture-job.ts\";\nimport { InsightModel } from \"../models/insight.ts\";\nimport { LabelModel, type LabelTables } from \"../models/label.ts\";\nimport { PackageUsageModel } from \"../models/usage.ts\";\nimport type { Project } from \"../schema/project.ts\";\nimport { TERMINAL_BUILD_STATUSES } from \"../types.ts\";\nimport { pendingCandidates } from \"./pending.ts\";\nimport { sweepScreenshotContent } from \"./screenshot-sweep.ts\";\n\nexport {\n sweepScreenshotContent,\n SWEEP_GRACE_MS,\n type SweepDeps,\n type SweepResult,\n type SweepTables,\n} from \"./screenshot-sweep.ts\";\nimport { col } from \"../models/columns.ts\";\nexport { purgeAiData, STALE_RUN_MS, type AiPurgeResult } from \"./ai.ts\";\n\n/** Table handles for retention queries. */\nexport interface RetentionTables {\n builds: Table;\n buildLabels: Table;\n baselines: Table;\n}\n\n/** Removes expired transient builds while keeping baselines and persistent builds. */\nexport class Retention {\n private readonly db: DatabaseAdapter;\n private readonly storage: StorageAdapter;\n private readonly tables: RetentionTables;\n private readonly logger?: Logger;\n\n constructor(\n db: DatabaseAdapter,\n storage: StorageAdapter,\n tables: RetentionTables,\n logger?: Logger,\n ) {\n this.db = db;\n this.storage = storage;\n this.tables = tables;\n this.logger = logger;\n }\n\n async purge(project: Project, options: PurgeOptions): Promise<PurgeResult> {\n const cutoff = new Date(Date.now() - options.ttlDays * 86_400_000).toISOString();\n const { buildIds, pending } = await this.selectBuilds(project, options, cutoff);\n const results = await Promise.all(\n buildIds.map(async (buildId) => ({\n files: await this.deleteBuildFiles(project.id, buildId),\n removed: await this.removeBuild(buildId),\n })),\n );\n const removedBuilds = results.filter((r: { removed: boolean }) => r.removed).length;\n const removedFiles = results.reduce((sum: number, r: { files: number }) => sum + r.files, 0);\n await this.sweepScreenshots(project);\n const removedJobs = await this.purgeFinishedJobs(cutoff);\n this.logger?.info(\n { projectId: project.id, removedBuilds, removedFiles, removedJobs, removedPending: pending },\n \"build retention purge complete\",\n );\n return { removedBuilds, removedFiles };\n }\n\n /**\n * The builds a purge removes: terminal builds past the window (minus the latest per branch when\n * asked), and pending builds idle past it (ADR 0013, decision 9). Persistent builds stay.\n */\n private async selectBuilds(\n project: Project,\n options: PurgeOptions,\n cutoff: string,\n ): Promise<{ buildIds: string[]; pending: number }> {\n const candidates = await this.db.list(this.tables.builds, {\n where: and(\n eq(col(this.tables.builds, \"projectId\"), project.id),\n inArray(col(this.tables.builds, \"status\"), [...TERMINAL_BUILD_STATUSES]),\n lt(col(this.tables.builds, \"updatedAt\"), cutoff),\n ),\n });\n const keep = options.keepLatestPerBranch\n ? await this.latestPerBranch(project.id)\n : new Set<string>();\n const persistent = await new LabelModel(\n this.db,\n this.tables as unknown as LabelTables,\n ).persistentBuildIds(project.id);\n const terminal = candidates\n .map((build) => (build as { id: string }).id)\n .filter((buildId) => !keep.has(buildId));\n // Pending builds leave on their own clock; \"the latest on a branch\" does not shield them.\n const pending = (await pendingCandidates(this.db, project.id, cutoff)).map(\n (candidate) => candidate.buildId,\n );\n return {\n buildIds: [...terminal, ...pending].filter((buildId) => !persistent.has(buildId)),\n pending: pending.length,\n };\n }\n\n /** Reclaim screenshots no snapshot or baseline references any more; never blocks the purge. */\n private async sweepScreenshots(project: Project): Promise<void> {\n try {\n await sweepScreenshotContent(\n {\n db: this.db,\n storage: this.storage,\n tables: {\n snapshots: this.db.tables.snapshots,\n baselines: this.tables.baselines,\n builds: this.tables.builds,\n },\n logger: this.logger,\n },\n project.id,\n );\n } catch (error) {\n this.logger?.warn({ err: error, projectId: project.id }, \"screenshot sweep failed\");\n }\n }\n\n /**\n * Drop finished queue jobs older than the build cutoff (they have no foreign key to a build, and\n * a finished job is only history); never blocks the purge. Queued and running jobs are kept.\n */\n private async purgeFinishedJobs(cutoff: string): Promise<number> {\n try {\n return await new CaptureJobModel(this.db).purgeFinished(cutoff);\n } catch (error) {\n this.logger?.warn({ err: error }, \"capture job purge failed\");\n return 0;\n }\n }\n\n private async removeBuild(buildId: string): Promise<boolean> {\n await new InsightModel(this.db).removeForBuild(buildId);\n await new CaptureJobModel(this.db).removeForBuild(buildId);\n await new BuildComponentModel(this.db).removeForBuild(buildId);\n await new PackageUsageModel(this.db).removeForBuild(buildId);\n await new BuildModel(this.db, this.tables as unknown as BuildTables).remove(buildId);\n return true;\n }\n\n private async latestPerBranch(projectId: string): Promise<Set<string>> {\n const rows = (await this.db.list(this.tables.builds, {\n where: eq(col(this.tables.builds, \"projectId\"), projectId),\n orderBy: desc(col(this.tables.builds, \"updatedAt\")),\n })) as unknown as { gitBranch: string; id: string }[];\n const latest = new Map<string, string>();\n for (const row of rows) {\n const branch = row.gitBranch;\n const current = latest.get(branch);\n if (!current) {\n latest.set(branch, row.id);\n }\n }\n return new Set(latest.values());\n }\n\n private async deleteBuildFiles(projectId: string, buildId: string): Promise<number> {\n const prefix = `${projectId}/builds/${buildId}/`;\n const manifestPath = `${prefix}storybook/manifest.json`;\n let manifestFiles: string[] = [];\n try {\n if (await this.storage.exists(manifestPath)) {\n const raw = await this.storage.read(manifestPath);\n const manifest = JSON.parse(raw.toString(\"utf8\")) as Record<string, string>;\n manifestFiles = Object.values(manifest);\n }\n } catch {\n // ignore — manifest may not exist for old builds\n }\n const files = await this.storage.list(prefix);\n await Promise.all(\n files.map(async (file) => {\n await this.storage.delete(file);\n }),\n );\n // Decrement content refs for this build's manifest\n for (const hash of manifestFiles) {\n try {\n const contentRefs = this.db.tables.contentRefs;\n const existing = (await this.db.get(contentRefs, hash)) as unknown as {\n refCount: number;\n } | null;\n // oxlint-disable-next-line unicorn/prefer-ternary -- refCount check is clearer as if/else\n if (existing) {\n const refCount = existing.refCount;\n // oxlint-disable-next-line unicorn/prefer-ternary -- grace logic is clearer as if/else\n if (refCount <= 1) {\n // Keep for 7-day grace: set refCount 0 and update lastSeenAt, don't delete yet\n await this.db.update(contentRefs, hash, {\n refCount: 0,\n lastSeenAt: new Date().toISOString(),\n });\n } else {\n await this.db.update(contentRefs, hash, {\n refCount: refCount - 1,\n lastSeenAt: new Date().toISOString(),\n });\n }\n }\n } catch {\n // ignore — content_refs may not exist\n }\n }\n // GC stale content_refs with 7-day grace\n try {\n const contentRefs = this.db.tables.contentRefs;\n const cutoff = new Date(Date.now() - 7 * 86_400_000).toISOString();\n const all = (await this.db.list(contentRefs)) as unknown as {\n hash: string;\n refCount: number;\n lastSeenAt: string;\n }[];\n for (const row of all) {\n if (row.refCount === 0 && row.lastSeenAt < cutoff) {\n await this.storage.delete(`content/${row.hash}`).catch(() => {\n // ignore storage delete failure\n });\n await this.db.remove(contentRefs, row.hash);\n }\n }\n } catch {\n // ignore — content_refs may not exist\n }\n return files.length;\n }\n\n async purgeStaleBranches(project: Project, ttlDays: number): Promise<BranchGcResult> {\n if (ttlDays <= 0) {\n return { removedBranches: 0, removedBaselines: 0 };\n }\n const cutoff = new Date(Date.now() - ttlDays * 86_400_000).toISOString();\n const rows = (await this.db.list(this.tables.builds, {\n where: eq(col(this.tables.builds, \"projectId\"), project.id),\n })) as unknown as { gitBranch: string; updatedAt: string }[];\n const stale = collectStaleBranches(rows, project.gitDefaultBranch, cutoff);\n if (stale.size === 0) {\n return { removedBranches: 0, removedBaselines: 0 };\n }\n const baselines = new BaselineModel(this.db, this.tables, this.storage);\n const removedBaselines = await baselines.removeStaleBranches(project.id, stale);\n await this.sweepScreenshots(project);\n this.logger?.info(\n { projectId: project.id, removedBranches: stale.size, removedBaselines },\n \"branch GC complete\",\n );\n return { removedBranches: stale.size, removedBaselines };\n }\n}\n\n/** Options controlling which builds a retention purge removes. */\nexport interface PurgeOptions {\n ttlDays: number;\n keepLatestPerBranch: boolean;\n}\n\n/** Counts of builds and files removed by a retention purge. */\nexport interface PurgeResult {\n removedBuilds: number;\n removedFiles: number;\n}\n\n/** Counts of stale branches and baselines removed. */\nexport interface BranchGcResult {\n removedBranches: number;\n removedBaselines: number;\n}\n\nfunction collectStaleBranches(\n rows: { gitBranch: string; updatedAt: string }[],\n defaultBranch: string,\n cutoff: string,\n): Set<string> {\n const latestAt = branchLatestAt(rows);\n const stale = new Set<string>();\n for (const [branch, updatedAt] of latestAt) {\n if (branch !== defaultBranch && updatedAt < cutoff) {\n stale.add(branch);\n }\n }\n return stale;\n}\n\nfunction branchLatestAt(rows: { gitBranch: string; updatedAt: string }[]): Map<string, string> {\n const latestAt = new Map<string, string>();\n for (const row of rows) {\n const current = latestAt.get(row.gitBranch);\n if (!current || row.updatedAt > current) {\n latestAt.set(row.gitBranch, row.updatedAt);\n }\n }\n return latestAt;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmCA,IAAa,YAAb,MAAuB;CACrB;CACA;CACA;CACA;CAEA,YACE,IACA,SACA,QACA,QACA;EACA,KAAK,KAAK;EACV,KAAK,UAAU;EACf,KAAK,SAAS;EACd,KAAK,SAAS;CAChB;CAEA,MAAM,MAAM,SAAkB,SAA6C;EACzE,MAAM,0BAAS,IAAI,KAAK,KAAK,IAAI,IAAI,QAAQ,UAAU,KAAU,EAAA,CAAE,YAAY;EAC/E,MAAM,EAAE,UAAU,YAAY,MAAM,KAAK,aAAa,SAAS,SAAS,MAAM;EAC9E,MAAM,UAAU,MAAM,QAAQ,IAC5B,SAAS,IAAI,OAAO,aAAa;GAC/B,OAAO,MAAM,KAAK,iBAAiB,QAAQ,IAAI,OAAO;GACtD,SAAS,MAAM,KAAK,YAAY,OAAO;EACzC,EAAE,CACJ;EACA,MAAM,gBAAgB,QAAQ,QAAQ,MAA4B,EAAE,OAAO,CAAC,CAAC;EAC7E,MAAM,eAAe,QAAQ,QAAQ,KAAa,MAAyB,MAAM,EAAE,OAAO,CAAC;EAC3F,MAAM,KAAK,iBAAiB,OAAO;EACnC,MAAM,cAAc,MAAM,KAAK,kBAAkB,MAAM;EACvD,KAAK,QAAQ,KACX;GAAE,WAAW,QAAQ;GAAI;GAAe;GAAc;GAAa,gBAAgB;EAAQ,GAC3F,gCACF;EACA,OAAO;GAAE;GAAe;EAAa;CACvC;;;;;CAMA,MAAc,aACZ,SACA,SACA,QACkD;EAClD,MAAM,aAAa,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,EACxD,OAAO,IACL,GAAG,IAAI,KAAK,OAAO,QAAQ,WAAW,GAAG,QAAQ,EAAE,GACnD,QAAQ,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG,CAAC,GAAG,uBAAuB,CAAC,GACvE,GAAG,IAAI,KAAK,OAAO,QAAQ,WAAW,GAAG,MAAM,CACjD,EACF,CAAC;EACD,MAAM,OAAO,QAAQ,sBACjB,MAAM,KAAK,gBAAgB,QAAQ,EAAE,oBACrC,IAAI,IAAY;EACpB,MAAM,aAAa,MAAM,IAAI,WAC3B,KAAK,IACL,KAAK,MACP,CAAC,CAAC,mBAAmB,QAAQ,EAAE;EAC/B,MAAM,WAAW,WACd,KAAK,UAAW,MAAyB,EAAE,CAAC,CAC5C,QAAQ,YAAY,CAAC,KAAK,IAAI,OAAO,CAAC;EAEzC,MAAM,WAAW,MAAM,kBAAkB,KAAK,IAAI,QAAQ,IAAI,MAAM,EAAA,CAAG,KACpE,cAAc,UAAU,OAC3B;EACA,OAAO;GACL,UAAU,CAAC,GAAG,UAAU,GAAG,OAAO,CAAC,CAAC,QAAQ,YAAY,CAAC,WAAW,IAAI,OAAO,CAAC;GAChF,SAAS,QAAQ;EACnB;CACF;;CAGA,MAAc,iBAAiB,SAAiC;EAC9D,IAAI;GACF,MAAM,uBACJ;IACE,IAAI,KAAK;IACT,SAAS,KAAK;IACd,QAAQ;KACN,WAAW,KAAK,GAAG,OAAO;KAC1B,WAAW,KAAK,OAAO;KACvB,QAAQ,KAAK,OAAO;IACtB;IACA,QAAQ,KAAK;GACf,GACA,QAAQ,EACV;EACF,SAAS,OAAO;GACd,KAAK,QAAQ,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,yBAAyB;EACpF;CACF;;;;;CAMA,MAAc,kBAAkB,QAAiC;EAC/D,IAAI;GACF,OAAO,MAAM,IAAI,gBAAgB,KAAK,EAAE,CAAC,CAAC,cAAc,MAAM;EAChE,SAAS,OAAO;GACd,KAAK,QAAQ,KAAK,EAAE,KAAK,MAAM,GAAG,0BAA0B;GAC5D,OAAO;EACT;CACF;CAEA,MAAc,YAAY,SAAmC;EAC3D,MAAM,IAAI,aAAa,KAAK,EAAE,CAAC,CAAC,eAAe,OAAO;EACtD,MAAM,IAAI,gBAAgB,KAAK,EAAE,CAAC,CAAC,eAAe,OAAO;EACzD,MAAM,IAAI,oBAAoB,KAAK,EAAE,CAAC,CAAC,eAAe,OAAO;EAC7D,MAAM,IAAI,kBAAkB,KAAK,EAAE,CAAC,CAAC,eAAe,OAAO;EAC3D,MAAM,IAAI,WAAW,KAAK,IAAI,KAAK,MAAgC,CAAC,CAAC,OAAO,OAAO;EACnF,OAAO;CACT;CAEA,MAAc,gBAAgB,WAAyC;EACrE,MAAM,OAAQ,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ;GACnD,OAAO,GAAG,IAAI,KAAK,OAAO,QAAQ,WAAW,GAAG,SAAS;GACzD,SAAS,KAAK,IAAI,KAAK,OAAO,QAAQ,WAAW,CAAC;EACpD,CAAC;EACD,MAAM,yBAAS,IAAI,IAAoB;EACvC,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,SAAS,IAAI;GAEnB,IAAI,CADY,OAAO,IAAI,MAChB,GACT,OAAO,IAAI,QAAQ,IAAI,EAAE;EAE7B;EACA,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC;CAChC;CAEA,MAAc,iBAAiB,WAAmB,SAAkC;EAClF,MAAM,SAAS,GAAG,UAAU,UAAU,QAAQ;EAC9C,MAAM,eAAe,GAAG,OAAO;EAC/B,IAAI,gBAA0B,CAAC;EAC/B,IAAI;GACF,IAAI,MAAM,KAAK,QAAQ,OAAO,YAAY,GAAG;IAC3C,MAAM,MAAM,MAAM,KAAK,QAAQ,KAAK,YAAY;IAChD,MAAM,WAAW,KAAK,MAAM,IAAI,SAAS,MAAM,CAAC;IAChD,gBAAgB,OAAO,OAAO,QAAQ;GACxC;EACF,QAAQ,CAER;EACA,MAAM,QAAQ,MAAM,KAAK,QAAQ,KAAK,MAAM;EAC5C,MAAM,QAAQ,IACZ,MAAM,IAAI,OAAO,SAAS;GACxB,MAAM,KAAK,QAAQ,OAAO,IAAI;EAChC,CAAC,CACH;EAEA,KAAK,MAAM,QAAQ,eACjB,IAAI;GACF,MAAM,cAAc,KAAK,GAAG,OAAO;GACnC,MAAM,WAAY,MAAM,KAAK,GAAG,IAAI,aAAa,IAAI;GAIrD,IAAI,UAAU;IACZ,MAAM,WAAW,SAAS;IAE1B,IAAI,YAAY,GAEd,MAAM,KAAK,GAAG,OAAO,aAAa,MAAM;KACtC,UAAU;KACV,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;IACrC,CAAC;SAED,MAAM,KAAK,GAAG,OAAO,aAAa,MAAM;KACtC,UAAU,WAAW;KACrB,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;IACrC,CAAC;GAEL;EACF,QAAQ,CAER;EAGF,IAAI;GACF,MAAM,cAAc,KAAK,GAAG,OAAO;GACnC,MAAM,0BAAS,IAAI,KAAK,KAAK,IAAI,IAAI,MAAc,EAAA,CAAE,YAAY;GACjE,MAAM,MAAO,MAAM,KAAK,GAAG,KAAK,WAAW;GAK3C,KAAK,MAAM,OAAO,KAChB,IAAI,IAAI,aAAa,KAAK,IAAI,aAAa,QAAQ;IACjD,MAAM,KAAK,QAAQ,OAAO,WAAW,IAAI,MAAM,CAAC,CAAC,YAAY,CAE7D,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,aAAa,IAAI,IAAI;GAC5C;EAEJ,QAAQ,CAER;EACA,OAAO,MAAM;CACf;CAEA,MAAM,mBAAmB,SAAkB,SAA0C;EACnF,IAAI,WAAW,GACb,OAAO;GAAE,iBAAiB;GAAG,kBAAkB;EAAE;EAEnD,MAAM,0BAAS,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU,KAAU,EAAA,CAAE,YAAY;EAIvE,MAAM,QAAQ,qBAAqB,MAHf,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ,EACnD,OAAO,GAAG,IAAI,KAAK,OAAO,QAAQ,WAAW,GAAG,QAAQ,EAAE,EAC5D,CAAC,GACwC,QAAQ,kBAAkB,MAAM;EACzE,IAAI,MAAM,SAAS,GACjB,OAAO;GAAE,iBAAiB;GAAG,kBAAkB;EAAE;EAGnD,MAAM,mBAAmB,MAAM,IADT,cAAc,KAAK,IAAI,KAAK,QAAQ,KAAK,OACxB,CAAC,CAAC,oBAAoB,QAAQ,IAAI,KAAK;EAC9E,MAAM,KAAK,iBAAiB,OAAO;EACnC,KAAK,QAAQ,KACX;GAAE,WAAW,QAAQ;GAAI,iBAAiB,MAAM;GAAM;EAAiB,GACvE,oBACF;EACA,OAAO;GAAE,iBAAiB,MAAM;GAAM;EAAiB;CACzD;AACF;AAoBA,SAAS,qBACP,MACA,eACA,QACa;CACb,MAAM,WAAW,eAAe,IAAI;CACpC,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,CAAC,QAAQ,cAAc,UAChC,IAAI,WAAW,iBAAiB,YAAY,QAC1C,MAAM,IAAI,MAAM;CAGpB,OAAO;AACT;AAEA,SAAS,eAAe,MAAuE;CAC7F,MAAM,2BAAW,IAAI,IAAoB;CACzC,KAAK,MAAM,OAAO,MAAM;EACtB,MAAM,UAAU,SAAS,IAAI,IAAI,SAAS;EAC1C,IAAI,CAAC,WAAW,IAAI,YAAY,SAC9B,SAAS,IAAI,IAAI,WAAW,IAAI,SAAS;CAE7C;CACA,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"retention.mjs","names":[],"sources":["../src/retention/purge.ts"],"sourcesContent":["import { and, desc, eq, inArray, lt } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { Logger } from \"pino\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { StorageAdapter } from \"../adapters/storage.ts\";\nimport { BaselineModel } from \"../models/baseline.ts\";\nimport { BuildComponentModel } from \"../models/build-component.ts\";\nimport { BuildModel, type BuildTables } from \"../models/build.ts\";\nimport { CaptureJobModel } from \"../models/capture-job.ts\";\nimport { InsightModel } from \"../models/insight.ts\";\nimport { LabelModel, type LabelTables } from \"../models/label.ts\";\nimport { PackageUsageModel } from \"../models/usage.ts\";\nimport type { Project } from \"../schema/project.ts\";\nimport { TERMINAL_BUILD_STATUSES } from \"../types.ts\";\nimport { pendingCandidates } from \"./pending.ts\";\nimport { sweepPublishedGzip } from \"./published-gzip-sweep.ts\";\nimport { sweepScreenshotContent } from \"./screenshot-sweep.ts\";\n\nexport {\n sweepScreenshotContent,\n SWEEP_GRACE_MS,\n type SweepDeps,\n type SweepResult,\n type SweepTables,\n} from \"./screenshot-sweep.ts\";\nimport { col } from \"../models/columns.ts\";\nimport { publishedGzipPath } from \"../utils/paths.ts\";\nexport { purgeAiData, STALE_RUN_MS, type AiPurgeResult } from \"./ai.ts\";\n\n/** Table handles for retention queries. */\nexport interface RetentionTables {\n builds: Table;\n buildLabels: Table;\n baselines: Table;\n}\n\n/** Removes expired transient builds while keeping baselines and persistent builds. */\nexport class Retention {\n private readonly db: DatabaseAdapter;\n private readonly storage: StorageAdapter;\n private readonly tables: RetentionTables;\n private readonly logger?: Logger;\n\n constructor(\n db: DatabaseAdapter,\n storage: StorageAdapter,\n tables: RetentionTables,\n logger?: Logger,\n ) {\n this.db = db;\n this.storage = storage;\n this.tables = tables;\n this.logger = logger;\n }\n\n async purge(project: Project, options: PurgeOptions): Promise<PurgeResult> {\n const cutoff = new Date(Date.now() - options.ttlDays * 86_400_000).toISOString();\n const { buildIds, pending } = await this.selectBuilds(project, options, cutoff);\n const results = await Promise.all(\n buildIds.map(async (buildId) => ({\n files: await this.deleteBuildFiles(project.id, buildId),\n removed: await this.removeBuild(buildId),\n })),\n );\n const removedBuilds = results.filter((r: { removed: boolean }) => r.removed).length;\n const removedFiles = results.reduce((sum: number, r: { files: number }) => sum + r.files, 0);\n await this.sweepScreenshots(project);\n const removedJobs = await this.purgeFinishedJobs(cutoff);\n this.logger?.info(\n { projectId: project.id, removedBuilds, removedFiles, removedJobs, removedPending: pending },\n \"build retention purge complete\",\n );\n return { removedBuilds, removedFiles };\n }\n\n /**\n * The builds a purge removes: terminal builds past the window (minus the latest per branch when\n * asked), and pending builds idle past it (ADR 0013, decision 9). Persistent builds stay.\n */\n private async selectBuilds(\n project: Project,\n options: PurgeOptions,\n cutoff: string,\n ): Promise<{ buildIds: string[]; pending: number }> {\n const candidates = await this.db.list(this.tables.builds, {\n where: and(\n eq(col(this.tables.builds, \"projectId\"), project.id),\n inArray(col(this.tables.builds, \"status\"), [...TERMINAL_BUILD_STATUSES]),\n lt(col(this.tables.builds, \"updatedAt\"), cutoff),\n ),\n });\n const keep = options.keepLatestPerBranch\n ? await this.latestPerBranch(project.id)\n : new Set<string>();\n const persistent = await new LabelModel(\n this.db,\n this.tables as unknown as LabelTables,\n ).persistentBuildIds(project.id);\n const terminal = candidates\n .map((build) => (build as { id: string }).id)\n .filter((buildId) => !keep.has(buildId));\n // Pending builds leave on their own clock; \"the latest on a branch\" does not shield them.\n const pending = (await pendingCandidates(this.db, project.id, cutoff)).map(\n (candidate) => candidate.buildId,\n );\n return {\n buildIds: [...terminal, ...pending].filter((buildId) => !persistent.has(buildId)),\n pending: pending.length,\n };\n }\n\n /** Reclaim screenshots no snapshot or baseline references any more; never blocks the purge. */\n private async sweepScreenshots(project: Project): Promise<void> {\n try {\n await sweepScreenshotContent(\n {\n db: this.db,\n storage: this.storage,\n tables: {\n snapshots: this.db.tables.snapshots,\n baselines: this.tables.baselines,\n builds: this.tables.builds,\n },\n logger: this.logger,\n },\n project.id,\n );\n } catch (error) {\n this.logger?.warn({ err: error, projectId: project.id }, \"screenshot sweep failed\");\n }\n }\n\n /**\n * Drop finished queue jobs older than the build cutoff (they have no foreign key to a build, and\n * a finished job is only history); never blocks the purge. Queued and running jobs are kept.\n */\n private async purgeFinishedJobs(cutoff: string): Promise<number> {\n try {\n return await new CaptureJobModel(this.db).purgeFinished(cutoff);\n } catch (error) {\n this.logger?.warn({ err: error }, \"capture job purge failed\");\n return 0;\n }\n }\n\n private async removeBuild(buildId: string): Promise<boolean> {\n await new InsightModel(this.db).removeForBuild(buildId);\n await new CaptureJobModel(this.db).removeForBuild(buildId);\n await new BuildComponentModel(this.db).removeForBuild(buildId);\n await new PackageUsageModel(this.db).removeForBuild(buildId);\n await new BuildModel(this.db, this.tables as unknown as BuildTables).remove(buildId);\n return true;\n }\n\n private async latestPerBranch(projectId: string): Promise<Set<string>> {\n const rows = (await this.db.list(this.tables.builds, {\n where: eq(col(this.tables.builds, \"projectId\"), projectId),\n orderBy: desc(col(this.tables.builds, \"updatedAt\")),\n })) as unknown as { gitBranch: string; id: string }[];\n const latest = new Map<string, string>();\n for (const row of rows) {\n const branch = row.gitBranch;\n const current = latest.get(branch);\n if (!current) {\n latest.set(branch, row.id);\n }\n }\n return new Set(latest.values());\n }\n\n private async deleteBuildFiles(projectId: string, buildId: string): Promise<number> {\n const prefix = `${projectId}/builds/${buildId}/`;\n const manifestPath = `${prefix}storybook/manifest.json`;\n let manifestFiles: string[] = [];\n try {\n if (await this.storage.exists(manifestPath)) {\n const raw = await this.storage.read(manifestPath);\n const manifest = JSON.parse(raw.toString(\"utf8\")) as Record<string, string>;\n manifestFiles = Object.values(manifest);\n }\n } catch {\n // ignore — manifest may not exist for old builds\n }\n const files = await this.storage.list(prefix);\n await Promise.all(\n files.map(async (file) => {\n await this.storage.delete(file);\n }),\n );\n // Decrement content refs for this build's manifest\n for (const hash of manifestFiles) {\n try {\n const contentRefs = this.db.tables.contentRefs;\n const existing = (await this.db.get(contentRefs, hash)) as unknown as {\n refCount: number;\n } | null;\n // oxlint-disable-next-line unicorn/prefer-ternary -- refCount check is clearer as if/else\n if (existing) {\n const refCount = existing.refCount;\n // oxlint-disable-next-line unicorn/prefer-ternary -- grace logic is clearer as if/else\n if (refCount <= 1) {\n // Keep for 7-day grace: set refCount 0 and update lastSeenAt, don't delete yet\n await this.db.update(contentRefs, hash, {\n refCount: 0,\n lastSeenAt: new Date().toISOString(),\n });\n } else {\n await this.db.update(contentRefs, hash, {\n refCount: refCount - 1,\n lastSeenAt: new Date().toISOString(),\n });\n }\n }\n } catch {\n // ignore — content_refs may not exist\n }\n }\n // GC stale content_refs with 7-day grace\n try {\n const contentRefs = this.db.tables.contentRefs;\n const cutoff = new Date(Date.now() - 7 * 86_400_000).toISOString();\n const all = (await this.db.list(contentRefs)) as unknown as {\n hash: string;\n refCount: number;\n lastSeenAt: string;\n }[];\n for (const row of all) {\n if (row.refCount === 0 && row.lastSeenAt < cutoff) {\n await this.storage.delete(`content/${row.hash}`).catch(() => {\n // ignore storage delete failure\n });\n // Variants are disposable; never let their deletion affect authoritative data.\n if (/^[a-f0-9]{64}$/u.test(row.hash)) {\n await this.storage.delete(publishedGzipPath(row.hash)).catch(() => {});\n }\n await this.db.remove(contentRefs, row.hash);\n }\n }\n } catch {\n // ignore — content_refs may not exist\n }\n await sweepPublishedGzip(this.storage).catch(() => {});\n return files.length;\n }\n\n async purgeStaleBranches(project: Project, ttlDays: number): Promise<BranchGcResult> {\n if (ttlDays <= 0) {\n return { removedBranches: 0, removedBaselines: 0 };\n }\n const cutoff = new Date(Date.now() - ttlDays * 86_400_000).toISOString();\n const rows = (await this.db.list(this.tables.builds, {\n where: eq(col(this.tables.builds, \"projectId\"), project.id),\n })) as unknown as { gitBranch: string; updatedAt: string }[];\n const stale = collectStaleBranches(rows, project.gitDefaultBranch, cutoff);\n if (stale.size === 0) {\n return { removedBranches: 0, removedBaselines: 0 };\n }\n const baselines = new BaselineModel(this.db, this.tables, this.storage);\n const removedBaselines = await baselines.removeStaleBranches(project.id, stale);\n await this.sweepScreenshots(project);\n this.logger?.info(\n { projectId: project.id, removedBranches: stale.size, removedBaselines },\n \"branch GC complete\",\n );\n return { removedBranches: stale.size, removedBaselines };\n }\n}\n\n/** Options controlling which builds a retention purge removes. */\nexport interface PurgeOptions {\n ttlDays: number;\n keepLatestPerBranch: boolean;\n}\n\n/** Counts of builds and files removed by a retention purge. */\nexport interface PurgeResult {\n removedBuilds: number;\n removedFiles: number;\n}\n\n/** Counts of stale branches and baselines removed. */\nexport interface BranchGcResult {\n removedBranches: number;\n removedBaselines: number;\n}\n\nfunction collectStaleBranches(\n rows: { gitBranch: string; updatedAt: string }[],\n defaultBranch: string,\n cutoff: string,\n): Set<string> {\n const latestAt = branchLatestAt(rows);\n const stale = new Set<string>();\n for (const [branch, updatedAt] of latestAt) {\n if (branch !== defaultBranch && updatedAt < cutoff) {\n stale.add(branch);\n }\n }\n return stale;\n}\n\nfunction branchLatestAt(rows: { gitBranch: string; updatedAt: string }[]): Map<string, string> {\n const latestAt = new Map<string, string>();\n for (const row of rows) {\n const current = latestAt.get(row.gitBranch);\n if (!current || row.updatedAt > current) {\n latestAt.set(row.gitBranch, row.updatedAt);\n }\n }\n return latestAt;\n}\n"],"mappings":"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"}
|
|
@@ -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/schema/baseline.d.ts
|
|
4
3
|
/** A baseline row. */
|
|
5
4
|
interface Baseline {
|
|
6
5
|
id: string;
|
|
@@ -9,6 +8,8 @@ interface Baseline {
|
|
|
9
8
|
viewportName: string;
|
|
10
9
|
branch: string;
|
|
11
10
|
snapshotId: string | null;
|
|
11
|
+
/** Build that actually rendered this image; null for unknown or imported origins. */
|
|
12
|
+
sourceBuildId?: string | null;
|
|
12
13
|
screenshotPath: string;
|
|
13
14
|
infraHash: string | null;
|
|
14
15
|
/** JSON `Fingerprint` behind `infraHash`; null on baselines recorded before fingerprints. */
|
|
@@ -20,6 +21,5 @@ interface Baseline {
|
|
|
20
21
|
createdAt: string;
|
|
21
22
|
updatedAt: string;
|
|
22
23
|
}
|
|
23
|
-
//#endregion
|
|
24
24
|
export { Baseline };
|
|
25
25
|
//# sourceMappingURL=baseline.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/build-component.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Row type of `build_components` (ADR 0006, decision 9): one row per component of a published
|
|
6
5
|
* build, written from the build's Storybook index when publishing ends. A component is the
|
|
@@ -20,6 +19,5 @@ interface BuildComponent {
|
|
|
20
19
|
hash: string;
|
|
21
20
|
createdAt: string;
|
|
22
21
|
}
|
|
23
|
-
//#endregion
|
|
24
22
|
export { BuildComponent };
|
|
25
23
|
//# sourceMappingURL=build-component.d.mts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { ReviewVerdict } from "../types.mjs";
|
|
4
|
-
//#region src/schema/build-review.d.ts
|
|
5
4
|
/** One verdict on one build. */
|
|
6
5
|
interface BuildReview {
|
|
7
6
|
id: string;
|
|
@@ -12,6 +11,5 @@ interface BuildReview {
|
|
|
12
11
|
body: string | null;
|
|
13
12
|
createdAt: string;
|
|
14
13
|
}
|
|
15
|
-
//#endregion
|
|
16
14
|
export { BuildReview };
|
|
17
15
|
//# sourceMappingURL=build-review.d.mts.map
|
package/dist/schema/build.d.mts
CHANGED
|
@@ -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 { BuildStatus } from "../types.mjs";
|
|
4
|
-
//#region src/schema/build.d.ts
|
|
5
4
|
/** A build row. */
|
|
6
5
|
interface Build {
|
|
7
6
|
id: string;
|
|
@@ -36,6 +35,5 @@ interface Build {
|
|
|
36
35
|
createdAt: string;
|
|
37
36
|
updatedAt: string;
|
|
38
37
|
}
|
|
39
|
-
//#endregion
|
|
40
38
|
export { Build };
|
|
41
39
|
//# sourceMappingURL=build.d.mts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { JobStatus } from "../adapter/capture-queue.mjs";
|
|
4
|
-
//#region src/schema/capture-attempt.d.ts
|
|
5
4
|
/** A capture attempt row: one queued run of a build's capture pipeline. */
|
|
6
5
|
interface CaptureAttempt {
|
|
7
6
|
id: string;
|
|
@@ -33,6 +32,5 @@ interface CaptureLog {
|
|
|
33
32
|
fields: string | null;
|
|
34
33
|
createdAt: string;
|
|
35
34
|
}
|
|
36
|
-
//#endregion
|
|
37
35
|
export { CaptureAttempt, CaptureLog, CaptureLogLevel };
|
|
38
36
|
//# sourceMappingURL=capture-attempt.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/capture-job.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Row types of `capture_jobs`, the database queue (ADR 0006, decision 4).
|
|
6
5
|
*
|
|
@@ -55,6 +54,5 @@ interface CaptureJobRow {
|
|
|
55
54
|
createdAt: string;
|
|
56
55
|
updatedAt: string;
|
|
57
56
|
}
|
|
58
|
-
//#endregion
|
|
59
57
|
export { CaptureAttemptStatus, CaptureJobEntry, CaptureJobKind, CaptureJobRow, CaptureJobStatus };
|
|
60
58
|
//# sourceMappingURL=capture-job.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/capture-shard.d.ts
|
|
4
3
|
/** What a row of `capture_shards` is: a stage of a sharded capture, or the claim that finalizes it. */
|
|
5
4
|
type CaptureShardKind = "plan" | "render" | "finalize";
|
|
6
5
|
/** Lifecycle of one shard row. */
|
|
@@ -30,6 +29,5 @@ interface CaptureShard {
|
|
|
30
29
|
createdAt: string;
|
|
31
30
|
updatedAt: string;
|
|
32
31
|
}
|
|
33
|
-
//#endregion
|
|
34
32
|
export { CaptureShard, CaptureShardKind, CaptureShardStatus };
|
|
35
33
|
//# sourceMappingURL=capture-shard.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/comment.d.ts
|
|
4
3
|
/** A comment row. */
|
|
5
4
|
interface Comment {
|
|
6
5
|
id: string;
|
|
@@ -16,6 +15,5 @@ interface Comment {
|
|
|
16
15
|
createdAt: string;
|
|
17
16
|
updatedAt: string;
|
|
18
17
|
}
|
|
19
|
-
//#endregion
|
|
20
18
|
export { Comment };
|
|
21
19
|
//# sourceMappingURL=comment.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/connection.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* A user's own OAuth connection to an external service (`design` providers today,
|
|
6
5
|
* issue trackers later). One per user and service; tokens are encrypted at rest.
|
|
@@ -19,6 +18,5 @@ interface UserConnection {
|
|
|
19
18
|
createdAt: string;
|
|
20
19
|
updatedAt: string;
|
|
21
20
|
}
|
|
22
|
-
//#endregion
|
|
23
21
|
export { UserConnection };
|
|
24
22
|
//# sourceMappingURL=connection.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/content-ref.d.ts
|
|
4
3
|
/** Content ref row for deduplicated assets. */
|
|
5
4
|
interface ContentRef {
|
|
6
5
|
hash: string;
|
|
@@ -8,6 +7,5 @@ interface ContentRef {
|
|
|
8
7
|
lastSeenAt: string;
|
|
9
8
|
createdAt: string;
|
|
10
9
|
}
|
|
11
|
-
//#endregion
|
|
12
10
|
export { ContentRef };
|
|
13
11
|
//# sourceMappingURL=content-ref.d.mts.map
|
package/dist/schema/design.d.mts
CHANGED
|
@@ -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/schema/design.d.ts
|
|
4
3
|
/** A design link: a project-level file link (`importPath` null) or a component mapping override. */
|
|
5
4
|
interface DesignLink {
|
|
6
5
|
id: string;
|
|
@@ -53,6 +52,5 @@ interface DesignNode {
|
|
|
53
52
|
createdAt: string;
|
|
54
53
|
updatedAt: string;
|
|
55
54
|
}
|
|
56
|
-
//#endregion
|
|
57
55
|
export { DesignCredential, DesignLink, DesignNode };
|
|
58
56
|
//# sourceMappingURL=design.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/insight.d.ts
|
|
4
3
|
/** Insight kinds: a build triage or a project-health digest. */
|
|
5
4
|
type InsightKind = "triage" | "health";
|
|
6
5
|
/** Lifecycle of an insight run. */
|
|
@@ -49,6 +48,5 @@ interface AiBudgetAlertRow {
|
|
|
49
48
|
threshold: number;
|
|
50
49
|
createdAt: string;
|
|
51
50
|
}
|
|
52
|
-
//#endregion
|
|
53
51
|
export { AiBudgetAlertRow, AiUsageRow, InsightKind, InsightRow, InsightStatus };
|
|
54
52
|
//# sourceMappingURL=insight.d.mts.map
|
package/dist/schema/label.d.mts
CHANGED
|
@@ -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/schema/label.d.ts
|
|
4
3
|
/** A label-type row. */
|
|
5
4
|
interface LabelType {
|
|
6
5
|
id: string;
|
|
@@ -20,6 +19,5 @@ interface BuildLabel {
|
|
|
20
19
|
value: string;
|
|
21
20
|
createdAt: string;
|
|
22
21
|
}
|
|
23
|
-
//#endregion
|
|
24
22
|
export { BuildLabel, LabelType };
|
|
25
23
|
//# sourceMappingURL=label.d.mts.map
|
package/dist/schema/member.d.mts
CHANGED
|
@@ -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 { ProjectRole } from "../types.mjs";
|
|
4
|
-
//#region src/schema/member.d.ts
|
|
5
4
|
/** A project-membership row. */
|
|
6
5
|
interface ProjectMember {
|
|
7
6
|
id: string;
|
|
@@ -12,6 +11,5 @@ interface ProjectMember {
|
|
|
12
11
|
source: string;
|
|
13
12
|
createdAt: string;
|
|
14
13
|
}
|
|
15
|
-
//#endregion
|
|
16
14
|
export { ProjectMember };
|
|
17
15
|
//# sourceMappingURL=member.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/notification.d.ts
|
|
4
3
|
/** A project (or site-wide) notification channel row. */
|
|
5
4
|
interface NotificationChannelRow {
|
|
6
5
|
id: string;
|
|
@@ -34,6 +33,5 @@ interface NotificationSubscriptionRow {
|
|
|
34
33
|
enabled: boolean;
|
|
35
34
|
createdAt: string;
|
|
36
35
|
}
|
|
37
|
-
//#endregion
|
|
38
36
|
export { NotificationChannelRow, NotificationSubscriptionRow };
|
|
39
37
|
//# sourceMappingURL=notification.d.mts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { ProjectRole } from "../types.mjs";
|
|
4
|
-
//#region src/schema/project-group-mapping.d.ts
|
|
5
4
|
/** An identity-provider group to project-role mapping row. */
|
|
6
5
|
interface ProjectGroupMapping {
|
|
7
6
|
id: string;
|
|
@@ -10,6 +9,5 @@ interface ProjectGroupMapping {
|
|
|
10
9
|
role: ProjectRole;
|
|
11
10
|
createdAt: string;
|
|
12
11
|
}
|
|
13
|
-
//#endregion
|
|
14
12
|
export { ProjectGroupMapping };
|
|
15
13
|
//# sourceMappingURL=project-group-mapping.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/project.d.ts
|
|
4
3
|
/** A project row. */
|
|
5
4
|
interface Project {
|
|
6
5
|
id: string;
|
|
@@ -54,6 +53,5 @@ interface StorybookMeta {
|
|
|
54
53
|
packagePath?: string;
|
|
55
54
|
previewParameters?: Record<string, unknown>;
|
|
56
55
|
}
|
|
57
|
-
//#endregion
|
|
58
56
|
export { Project, StorybookMeta };
|
|
59
57
|
//# sourceMappingURL=project.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/site-setting.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Row type of `site_settings`: a small key-value table for facts the app learns while running and
|
|
6
5
|
* must share between instances (ADR 0007, decision 6: the public origin an admin's browser reported).
|
|
@@ -16,6 +15,5 @@ interface SiteSetting {
|
|
|
16
15
|
createdAt: string;
|
|
17
16
|
updatedAt: string;
|
|
18
17
|
}
|
|
19
|
-
//#endregion
|
|
20
18
|
export { SiteSetting };
|
|
21
19
|
//# sourceMappingURL=site-setting.d.mts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { SnapshotStatus } from "../types.mjs";
|
|
4
|
-
//#region src/schema/snapshot.d.ts
|
|
5
4
|
/** A snapshot row. */
|
|
6
5
|
interface Snapshot {
|
|
7
6
|
id: string;
|
|
@@ -29,6 +28,11 @@ interface Snapshot {
|
|
|
29
28
|
envChange: string | null;
|
|
30
29
|
/** True when inherited unchanged from the baseline without rendering. */
|
|
31
30
|
inherited: boolean;
|
|
31
|
+
/** Build that rendered the screenshot; inherited captures carry the original source. */
|
|
32
|
+
sourceBuildId?: string | null;
|
|
33
|
+
/** Frozen comparison image and metadata, owned by this snapshot’s build. */
|
|
34
|
+
comparisonImagePath?: string | null;
|
|
35
|
+
comparisonMetadata?: string | null;
|
|
32
36
|
/** Baseline row the diff was computed against (null: no baseline, or legacy row). */
|
|
33
37
|
baselineId: string | null;
|
|
34
38
|
/** That baseline's `updatedAt` at diff time; compared on approval to detect drift. */
|
|
@@ -44,6 +48,5 @@ interface Snapshot {
|
|
|
44
48
|
createdAt: string;
|
|
45
49
|
updatedAt: string;
|
|
46
50
|
}
|
|
47
|
-
//#endregion
|
|
48
51
|
export { Snapshot };
|
|
49
52
|
//# sourceMappingURL=snapshot.d.mts.map
|
package/dist/schema/token.d.mts
CHANGED
|
@@ -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/schema/token.d.ts
|
|
4
3
|
/** A CI token row (hash only; the secret itself is never stored). */
|
|
5
4
|
interface Token {
|
|
6
5
|
id: string;
|
|
@@ -12,6 +11,5 @@ interface Token {
|
|
|
12
11
|
lastUsedAt: string | null;
|
|
13
12
|
createdAt: string;
|
|
14
13
|
}
|
|
15
|
-
//#endregion
|
|
16
14
|
export { Token };
|
|
17
15
|
//# sourceMappingURL=token.d.mts.map
|
package/dist/schema/usage.d.mts
CHANGED
|
@@ -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/schema/usage.d.ts
|
|
4
3
|
/** A link from a downstream project to the upstream project that publishes a package it consumes. */
|
|
5
4
|
interface ProjectLink {
|
|
6
5
|
id: string;
|
|
@@ -25,6 +24,5 @@ interface BuildPackageUsage {
|
|
|
25
24
|
version: string | null;
|
|
26
25
|
createdAt: string;
|
|
27
26
|
}
|
|
28
|
-
//#endregion
|
|
29
27
|
export { BuildPackageUsage, ProjectLink };
|
|
30
28
|
//# sourceMappingURL=usage.d.mts.map
|
package/dist/schema/user.d.mts
CHANGED
|
@@ -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 { SiteRole } from "../types.mjs";
|
|
4
|
-
//#region src/schema/user.d.ts
|
|
5
4
|
/** How a user authenticates. */
|
|
6
5
|
type AuthProvider = "local" | "oidc" | "shared";
|
|
7
6
|
/** A user row. */
|
|
@@ -22,6 +21,5 @@ interface User {
|
|
|
22
21
|
/** Whether the account is disabled (login rejected). */
|
|
23
22
|
disabled?: boolean;
|
|
24
23
|
}
|
|
25
|
-
//#endregion
|
|
26
24
|
export { AuthProvider, User };
|
|
27
25
|
//# sourceMappingURL=user.d.mts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/schema/webhook.d.ts
|
|
4
3
|
/** A webhook subscription row. */
|
|
5
4
|
interface Webhook {
|
|
6
5
|
id: string;
|
|
@@ -11,6 +10,5 @@ interface Webhook {
|
|
|
11
10
|
createdAt: string;
|
|
12
11
|
updatedAt: string;
|
|
13
12
|
}
|
|
14
|
-
//#endregion
|
|
15
13
|
export { Webhook };
|
|
16
14
|
//# sourceMappingURL=webhook.d.mts.map
|
package/dist/schema.d.mts
CHANGED
|
@@ -9,22 +9,20 @@ import { Snapshot } from "./schema/snapshot.mjs";
|
|
|
9
9
|
import { CaptureAttemptStatus, CaptureJobEntry, CaptureJobKind, CaptureJobRow, CaptureJobStatus } from "./schema/capture-job.mjs";
|
|
10
10
|
import { BuildComponent } from "./schema/build-component.mjs";
|
|
11
11
|
import { CaptureShard, CaptureShardKind, CaptureShardStatus } from "./schema/capture-shard.mjs";
|
|
12
|
-
import { AiBudgetAlertRow, AiUsageRow, InsightKind, InsightRow, InsightStatus } from "./schema/insight.mjs";
|
|
13
12
|
import { BuildReview } from "./schema/build-review.mjs";
|
|
13
|
+
import { SiteSetting } from "./schema/site-setting.mjs";
|
|
14
14
|
import { Comment } from "./schema/comment.mjs";
|
|
15
|
+
import { BuildLabel, LabelType } from "./schema/label.mjs";
|
|
15
16
|
import { UserConnection } from "./schema/connection.mjs";
|
|
16
17
|
import { DesignCredential, DesignLink, DesignNode } from "./schema/design.mjs";
|
|
17
|
-
import { BuildLabel, LabelType } from "./schema/label.mjs";
|
|
18
18
|
import { BuildPackageUsage, ProjectLink } from "./schema/usage.mjs";
|
|
19
19
|
import { ProjectMember } from "./schema/member.mjs";
|
|
20
|
-
import { NotificationChannelRow, NotificationSubscriptionRow } from "./schema/notification.mjs";
|
|
21
20
|
import { ProjectGroupMapping } from "./schema/project-group-mapping.mjs";
|
|
21
|
+
import { AiBudgetAlertRow, AiUsageRow, InsightKind, InsightRow, InsightStatus } from "./schema/insight.mjs";
|
|
22
|
+
import { NotificationChannelRow, NotificationSubscriptionRow } from "./schema/notification.mjs";
|
|
22
23
|
import { Token } from "./schema/token.mjs";
|
|
23
24
|
import { User } from "./schema/user.mjs";
|
|
24
|
-
import { SiteSetting } from "./schema/site-setting.mjs";
|
|
25
|
-
//#region src/schema/index.d.ts
|
|
26
25
|
/** Placeholder schema type — Drizzle schema lives in the db adapters. */
|
|
27
26
|
type Schema = Record<string, unknown>;
|
|
28
|
-
//#endregion
|
|
29
27
|
export { type AiBudgetAlertRow, type AiUsageRow, type Baseline, type Build, type BuildComponent, type BuildLabel, type BuildPackageUsage, type BuildReview, type CaptureAttempt, type CaptureAttemptStatus, type CaptureJobEntry, type CaptureJobKind, type CaptureJobRow, type CaptureJobStatus, type CaptureLog, type CaptureLogLevel, type CaptureShard, type CaptureShardKind, type CaptureShardStatus, type Comment, type DesignCredential, type DesignLink, type DesignNode, type InsightKind, type InsightRow, type InsightStatus, type LabelType, type NotificationChannelRow, type NotificationSubscriptionRow, type Project, type ProjectGroupMapping, type ProjectLink, type ProjectMember, Schema, type SiteSetting, type Snapshot, type StorybookMeta, type Token, type User, type UserConnection, type Webhook };
|
|
30
28
|
//# sourceMappingURL=schema.d.mts.map
|
package/dist/serverless.d.mts
CHANGED
|
@@ -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/serverless.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Serverless hosts (ADR 0006, decision 3): `testing` needs a process that keeps running between
|
|
6
5
|
* requests, so it is refused on AWS Lambda and warned about on the other platforms that freeze or
|
|
@@ -16,6 +15,5 @@ declare function isServerlessHost(env?: NodeJS.ProcessEnv): boolean;
|
|
|
16
15
|
* `STORYSHELF_ALLOW_SERVERLESS=1`.
|
|
17
16
|
*/
|
|
18
17
|
declare function assertServerless(testing: boolean, env?: NodeJS.ProcessEnv): string | undefined;
|
|
19
|
-
//#endregion
|
|
20
18
|
export { ALLOW_SERVERLESS_ENV, assertServerless, isServerlessHost };
|
|
21
19
|
//# sourceMappingURL=serverless.d.mts.map
|
package/dist/serverless.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
-
|
|
4
|
+
// src/serverless.ts
|
|
5
5
|
/**
|
|
6
6
|
* Serverless hosts (ADR 0006, decision 3): `testing` needs a process that keeps running between
|
|
7
7
|
* requests, so it is refused on AWS Lambda and warned about on the other platforms that freeze or
|
|
@@ -31,7 +31,6 @@ function assertServerless(testing, env = process.env) {
|
|
|
31
31
|
if (env[LAMBDA_ENV]) throw new Error(`testing needs a long-running server, and AWS Lambda ends the process after each request. Remove the testing option to host Storybooks only, or run on a container; set ${ALLOW_SERVERLESS_ENV}=1 to override.`);
|
|
32
32
|
return `testing is configured on a serverless host: capture jobs run in the background and may be cut off when the platform ends the process. Run on a container for testing; set ${ALLOW_SERVERLESS_ENV}=1 to silence this warning.`;
|
|
33
33
|
}
|
|
34
|
-
//#endregion
|
|
35
34
|
export { ALLOW_SERVERLESS_ENV, assertServerless, isServerlessHost };
|
|
36
35
|
|
|
37
36
|
//# sourceMappingURL=serverless.mjs.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { BuildReferenceLifecycle, BuildReferenceOwner } from "../adapter/database.mjs";
|
|
4
|
+
interface BuildReferenceContractFixture {
|
|
5
|
+
first: BuildReferenceLifecycle;
|
|
6
|
+
second: BuildReferenceLifecycle;
|
|
7
|
+
owner: BuildReferenceOwner;
|
|
8
|
+
buildIds: readonly [string, string];
|
|
9
|
+
}
|
|
10
|
+
type BuildReferenceContractFixtureRunner = (run: (fixture: BuildReferenceContractFixture) => Promise<void>) => Promise<void>;
|
|
11
|
+
/** Exercise atomic owner replacement and deletion using separate adapter connections. */
|
|
12
|
+
declare function buildReferenceContractSuite(label: string, withFixture: BuildReferenceContractFixtureRunner): void;
|
|
13
|
+
export { BuildReferenceContractFixture, BuildReferenceContractFixtureRunner, buildReferenceContractSuite };
|
|
14
|
+
//# sourceMappingURL=build-reference-contract.d.mts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
// src/test-helpers/build-reference-contract.ts
|
|
6
|
+
/** Shared lifecycle conformance tests. Each fixture must use independent connections. */
|
|
7
|
+
/** Exercise atomic owner replacement and deletion using separate adapter connections. */
|
|
8
|
+
function buildReferenceContractSuite(label, withFixture) {
|
|
9
|
+
describe(`build reference lifecycle contract: ${label}`, () => {
|
|
10
|
+
it("serializes replacement against deletion of the newly referenced build", async () => {
|
|
11
|
+
await withFixture(async ({ first, second, owner, buildIds }) => {
|
|
12
|
+
await first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => null);
|
|
13
|
+
const [replacement, deletion] = await Promise.allSettled([first.replaceFencedReferences(owner, 1, [buildIds[1]], async () => null), second.claimDeletion(owner.projectId, buildIds[1])]);
|
|
14
|
+
expect(deletion.status).toBe("fulfilled");
|
|
15
|
+
if (deletion.status !== "fulfilled") throw new Error("deletion failed");
|
|
16
|
+
if (replacement.status === "fulfilled") {
|
|
17
|
+
expect(deletion.value).toBe("protected");
|
|
18
|
+
expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe("claimed");
|
|
19
|
+
} else {
|
|
20
|
+
expect(deletion.value).toBe("claimed");
|
|
21
|
+
expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe("protected");
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it("serializes an admission against deletion", async () => {
|
|
26
|
+
await withFixture(async ({ first, second, owner, buildIds }) => {
|
|
27
|
+
const [admission, deletion] = await Promise.allSettled([first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => null), second.claimDeletion(owner.projectId, buildIds[0])]);
|
|
28
|
+
expect(deletion.status).toBe("fulfilled");
|
|
29
|
+
if (deletion.status !== "fulfilled") throw new Error("deletion failed");
|
|
30
|
+
if (admission.status === "fulfilled") expect(deletion.value).toBe("protected");
|
|
31
|
+
else expect(deletion.value).toBe("claimed");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
it("rolls back domain failure and rejects stale generation after release", async () => {
|
|
35
|
+
await withFixture(async ({ first, second, owner, buildIds }) => {
|
|
36
|
+
await expect(first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => {
|
|
37
|
+
throw new Error("rollback");
|
|
38
|
+
})).rejects.toThrow("rollback");
|
|
39
|
+
expect(await second.referenceGeneration(owner)).toBe(0);
|
|
40
|
+
expect((await second.replaceFencedReferences(owner, 0, [buildIds[0], buildIds[0]], async () => null)).generation).toBe(1);
|
|
41
|
+
expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe("protected");
|
|
42
|
+
expect((await first.replaceFencedReferences(owner, 1, [], async () => null)).generation).toBe(2);
|
|
43
|
+
await expect(second.replaceFencedReferences(owner, 1, [buildIds[1]], async () => null)).rejects.toThrow();
|
|
44
|
+
expect(await second.referenceGeneration(owner)).toBe(2);
|
|
45
|
+
expect(await first.claimDeletion(owner.projectId, buildIds[1])).toBe("claimed");
|
|
46
|
+
expect(await second.claimDeletion(owner.projectId, buildIds[0])).toBe("claimed");
|
|
47
|
+
await expect(first.replaceFencedReferences(owner, 2, [buildIds[0]], async () => null)).rejects.toThrow();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
it("rejects a duplicate owner in a multi-owner update", async () => {
|
|
51
|
+
await withFixture(async ({ first, owner, buildIds }) => {
|
|
52
|
+
const change = {
|
|
53
|
+
owner,
|
|
54
|
+
expectedGeneration: 0,
|
|
55
|
+
buildIds: [buildIds[0]]
|
|
56
|
+
};
|
|
57
|
+
await expect(first.replaceManyFencedReferences([change, change], async () => null)).rejects.toThrow();
|
|
58
|
+
expect(await first.referenceGeneration(owner)).toBe(0);
|
|
59
|
+
expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe("claimed");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export { buildReferenceContractSuite };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=build-reference-contract.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-reference-contract.mjs","names":[],"sources":["../../src/test-helpers/build-reference-contract.ts"],"sourcesContent":["/** Shared lifecycle conformance tests. Each fixture must use independent connections. */\nimport { describe, expect, it } from \"vitest\";\nimport type { BuildReferenceLifecycle, BuildReferenceOwner } from \"../adapters/database.ts\";\n\nexport interface BuildReferenceContractFixture {\n first: BuildReferenceLifecycle;\n second: BuildReferenceLifecycle;\n owner: BuildReferenceOwner;\n buildIds: readonly [string, string];\n}\nexport type BuildReferenceContractFixtureRunner = (\n run: (fixture: BuildReferenceContractFixture) => Promise<void>,\n) => Promise<void>;\n\n/** Exercise atomic owner replacement and deletion using separate adapter connections. */\nexport function buildReferenceContractSuite(\n label: string,\n withFixture: BuildReferenceContractFixtureRunner,\n): void {\n describe(`build reference lifecycle contract: ${label}`, () => {\n it(\"serializes replacement against deletion of the newly referenced build\", async () => {\n await withFixture(async ({ first, second, owner, buildIds }) => {\n await first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => null);\n const [replacement, deletion] = await Promise.allSettled([\n first.replaceFencedReferences(owner, 1, [buildIds[1]], async () => null),\n second.claimDeletion(owner.projectId, buildIds[1]),\n ]);\n expect(deletion.status).toBe(\"fulfilled\");\n if (deletion.status !== \"fulfilled\") throw new Error(\"deletion failed\");\n if (replacement.status === \"fulfilled\") {\n expect(deletion.value).toBe(\"protected\");\n expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe(\"claimed\");\n } else {\n expect(deletion.value).toBe(\"claimed\");\n expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe(\"protected\");\n }\n });\n });\n it(\"serializes an admission against deletion\", async () => {\n await withFixture(async ({ first, second, owner, buildIds }) => {\n const [admission, deletion] = await Promise.allSettled([\n first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => null),\n second.claimDeletion(owner.projectId, buildIds[0]),\n ]);\n expect(deletion.status).toBe(\"fulfilled\");\n if (deletion.status !== \"fulfilled\") throw new Error(\"deletion failed\");\n if (admission.status === \"fulfilled\") expect(deletion.value).toBe(\"protected\");\n else expect(deletion.value).toBe(\"claimed\");\n });\n });\n it(\"rolls back domain failure and rejects stale generation after release\", async () => {\n await withFixture(async ({ first, second, owner, buildIds }) => {\n await expect(\n first.replaceFencedReferences(owner, 0, [buildIds[0]], async () => {\n throw new Error(\"rollback\");\n }),\n ).rejects.toThrow(\"rollback\");\n expect(await second.referenceGeneration(owner)).toBe(0);\n expect(\n (\n await second.replaceFencedReferences(\n owner,\n 0,\n [buildIds[0], buildIds[0]],\n async () => null,\n )\n ).generation,\n ).toBe(1);\n expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe(\"protected\");\n expect(\n (await first.replaceFencedReferences(owner, 1, [], async () => null)).generation,\n ).toBe(2);\n await expect(\n second.replaceFencedReferences(owner, 1, [buildIds[1]], async () => null),\n ).rejects.toThrow();\n expect(await second.referenceGeneration(owner)).toBe(2);\n expect(await first.claimDeletion(owner.projectId, buildIds[1])).toBe(\"claimed\");\n expect(await second.claimDeletion(owner.projectId, buildIds[0])).toBe(\"claimed\");\n await expect(\n first.replaceFencedReferences(owner, 2, [buildIds[0]], async () => null),\n ).rejects.toThrow();\n });\n });\n it(\"rejects a duplicate owner in a multi-owner update\", async () => {\n await withFixture(async ({ first, owner, buildIds }) => {\n const change = { owner, expectedGeneration: 0, buildIds: [buildIds[0]] };\n await expect(\n first.replaceManyFencedReferences([change, change], async () => null),\n ).rejects.toThrow();\n expect(await first.referenceGeneration(owner)).toBe(0);\n expect(await first.claimDeletion(owner.projectId, buildIds[0])).toBe(\"claimed\");\n });\n });\n });\n}\n"],"mappings":"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"}
|
|
@@ -5,11 +5,9 @@ import { Build } from "../schema/build.mjs";
|
|
|
5
5
|
import { Project } from "../schema/project.mjs";
|
|
6
6
|
import { BuildTables } from "../models/build.mjs";
|
|
7
7
|
import { ProjectTables } from "../models/project.mjs";
|
|
8
|
-
//#region src/test-helpers/create-project.d.ts
|
|
9
8
|
/** Create a test project with owner/repo defaults. */
|
|
10
9
|
declare function createTestProject(db: DatabaseAdapter, tables: ProjectTables, overrides?: Partial<Project>): Promise<Project>;
|
|
11
10
|
/** Create a test build on main with sha-1 defaults. */
|
|
12
11
|
declare function createTestBuild(db: DatabaseAdapter, tables: BuildTables, projectId: string, overrides?: Partial<Build>): Promise<Build>;
|
|
13
|
-
//#endregion
|
|
14
12
|
export { createTestBuild, createTestProject };
|
|
15
13
|
//# sourceMappingURL=create-project.d.mts.map
|
|
@@ -3,7 +3,7 @@ import "node:url";
|
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { BuildModel } from "../models/build.mjs";
|
|
5
5
|
import { ProjectModel } from "../models/project.mjs";
|
|
6
|
-
|
|
6
|
+
// src/test-helpers/create-project.ts
|
|
7
7
|
/** Create a test project with owner/repo defaults. */
|
|
8
8
|
async function createTestProject(db, tables, overrides) {
|
|
9
9
|
const { gitRepository: repo, ...rest } = overrides ?? {};
|
|
@@ -22,7 +22,6 @@ async function createTestBuild(db, tables, projectId, overrides) {
|
|
|
22
22
|
...overrides
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
//#endregion
|
|
26
25
|
export { createTestBuild, createTestProject };
|
|
27
26
|
|
|
28
27
|
//# sourceMappingURL=create-project.mjs.map
|