@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,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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"}
|
|
@@ -2,14 +2,12 @@ import __tsdown_shims_path from 'node:path';
|
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
4
|
import { Build } from "../schema/build.mjs";
|
|
5
|
-
import { BuildTables } from "../models/build.mjs";
|
|
6
5
|
import { Project } from "../schema/project.mjs";
|
|
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
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
-
//#region src/test-helpers/database-contract.d.ts
|
|
5
4
|
/** Tables every adapter must expose (single-sourced from the contract). */
|
|
6
5
|
declare const REQUIRED_TABLES: string[];
|
|
7
6
|
/** Build the adapter under test (sync or async factories both work). */
|
|
8
7
|
type DatabaseFactory = () => DatabaseAdapter | Promise<DatabaseAdapter>;
|
|
9
8
|
/** Run the database contract against a factory. */
|
|
10
9
|
declare function databaseContractSuite(label: string, make: DatabaseFactory): void;
|
|
11
|
-
//#endregion
|
|
12
10
|
export { DatabaseFactory, REQUIRED_TABLES, databaseContractSuite };
|
|
13
11
|
//# sourceMappingURL=database-contract.d.mts.map
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { createShelfLogger } from "../logger.mjs";
|
|
4
5
|
import { REQUIRED_TABLE_KEYS } from "../adapter/database.mjs";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { getTableColumns, ne } from "drizzle-orm";
|
|
5
8
|
import { describe, expect, it } from "vitest";
|
|
6
|
-
|
|
9
|
+
// src/test-helpers/database-contract.ts
|
|
7
10
|
/**
|
|
8
11
|
* Published database contract suite for first- and third-party adapters.
|
|
9
12
|
*
|
|
@@ -21,6 +24,7 @@ const REQUIRED_TABLES = REQUIRED_TABLE_KEYS;
|
|
|
21
24
|
const REQUIRED_METHODS = [
|
|
22
25
|
"insert",
|
|
23
26
|
"update",
|
|
27
|
+
"updateWhere",
|
|
24
28
|
"get",
|
|
25
29
|
"remove",
|
|
26
30
|
"list",
|
|
@@ -43,6 +47,38 @@ function databaseContractSuite(label, make) {
|
|
|
43
47
|
const adapter = await make();
|
|
44
48
|
for (const method of REQUIRED_METHODS) expect(typeof adapter[method]).toBe("function");
|
|
45
49
|
});
|
|
50
|
+
it("conditionally updates and returns the current row when refused", async () => {
|
|
51
|
+
const adapter = await make();
|
|
52
|
+
await adapter.lifecycle?.setup({
|
|
53
|
+
config: {},
|
|
54
|
+
logger: createShelfLogger({ level: "silent" })
|
|
55
|
+
});
|
|
56
|
+
const table = adapter.tables.projects;
|
|
57
|
+
const id = `conditional-contract-${randomUUID()}`;
|
|
58
|
+
try {
|
|
59
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
60
|
+
await adapter.insert(table, {
|
|
61
|
+
id,
|
|
62
|
+
name: "before",
|
|
63
|
+
slug: id,
|
|
64
|
+
createdAt: now,
|
|
65
|
+
updatedAt: now
|
|
66
|
+
});
|
|
67
|
+
const condition = ne(getTableColumns(table)["name"], "locked");
|
|
68
|
+
const first = await adapter.updateWhere(table, id, { name: "locked" }, condition);
|
|
69
|
+
expect(first?.["name"]).toBe("locked");
|
|
70
|
+
const refused = await adapter.updateWhere(table, id, { name: "after" }, condition);
|
|
71
|
+
expect(refused?.["name"]).toBe("locked");
|
|
72
|
+
expect((await adapter.get(table, id))?.["name"]).toBe("locked");
|
|
73
|
+
expect(await adapter.updateWhere(table, "missing", { name: "x" }, condition)).toBeNull();
|
|
74
|
+
} finally {
|
|
75
|
+
try {
|
|
76
|
+
await adapter.remove(table, id);
|
|
77
|
+
} finally {
|
|
78
|
+
await adapter.lifecycle?.teardown();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, 3e4);
|
|
46
82
|
it("keeps the lifecycle rule (absent or all three hooks)", async () => {
|
|
47
83
|
const lifecycle = (await make()).lifecycle;
|
|
48
84
|
if (lifecycle === void 0) return;
|
|
@@ -52,7 +88,6 @@ function databaseContractSuite(label, make) {
|
|
|
52
88
|
});
|
|
53
89
|
});
|
|
54
90
|
}
|
|
55
|
-
//#endregion
|
|
56
91
|
export { REQUIRED_TABLES, databaseContractSuite };
|
|
57
92
|
|
|
58
93
|
//# sourceMappingURL=database-contract.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-contract.mjs","names":[],"sources":["../../src/test-helpers/database-contract.ts"],"sourcesContent":["/**\n * Published database contract suite for first- and third-party adapters.\n *\n * Structural conformance only (identity, table map, methods, lifecycle\n * rule) — row-level CRUD stays per-package because insert shapes differ per\n * dialect schema. A package proves conformance in one line:\n *\n * ```ts\n * import { databaseContractSuite } from \"@storyshelf/core/test-helpers\";\n * databaseContractSuite(\"sqlite\", () => createSqliteDatabase(\":memory:\"));\n * ```\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport { REQUIRED_TABLE_KEYS } from \"../adapters/database.ts\";\n\n/** Tables every adapter must expose (single-sourced from the contract). */\nexport const REQUIRED_TABLES = REQUIRED_TABLE_KEYS;\n\nconst REQUIRED_METHODS = [\"insert\"
|
|
1
|
+
{"version":3,"file":"database-contract.mjs","names":[],"sources":["../../src/test-helpers/database-contract.ts"],"sourcesContent":["/**\n * Published database contract suite for first- and third-party adapters.\n *\n * Structural conformance only (identity, table map, methods, lifecycle\n * rule) — row-level CRUD stays per-package because insert shapes differ per\n * dialect schema. A package proves conformance in one line:\n *\n * ```ts\n * import { databaseContractSuite } from \"@storyshelf/core/test-helpers\";\n * databaseContractSuite(\"sqlite\", () => createSqliteDatabase(\":memory:\"));\n * ```\n */\nimport { getTableColumns, ne } from \"drizzle-orm\";\nimport { randomUUID } from \"node:crypto\";\nimport { describe, expect, it } from \"vitest\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport { REQUIRED_TABLE_KEYS } from \"../adapters/database.ts\";\nimport { createShelfLogger } from \"../logger.ts\";\n\n/** Tables every adapter must expose (single-sourced from the contract). */\nexport const REQUIRED_TABLES = REQUIRED_TABLE_KEYS;\n\nconst REQUIRED_METHODS = [\n \"insert\",\n \"update\",\n \"updateWhere\",\n \"get\",\n \"remove\",\n \"list\",\n \"count\",\n \"all\",\n];\n\n/** Build the adapter under test (sync or async factories both work). */\nexport type DatabaseFactory = () => DatabaseAdapter | Promise<DatabaseAdapter>;\n\n/** Run the database contract against a factory. */\nexport function databaseContractSuite(label: string, make: DatabaseFactory): void {\n describe(`database contract: ${label}`, () => {\n it(\"exposes database metadata\", async () => {\n const adapter = await make();\n expect(adapter.metadata.category).toBe(\"database\");\n expect(adapter.metadata.kind.length).toBeGreaterThan(0);\n });\n\n it(\"exposes the full table map\", async () => {\n const adapter = await make();\n const tables = adapter.tables as unknown as Record<string, unknown>;\n for (const table of REQUIRED_TABLES) {\n expect(tables[table], `missing table: ${table}`).toBeDefined();\n }\n });\n\n it(\"exposes every CRUD method\", async () => {\n const adapter = await make();\n for (const method of REQUIRED_METHODS) {\n expect(typeof (adapter as unknown as Record<string, unknown>)[method]).toBe(\"function\");\n }\n });\n\n it(\"conditionally updates and returns the current row when refused\", async () => {\n const adapter = await make();\n await adapter.lifecycle?.setup({\n config: {},\n logger: createShelfLogger({ level: \"silent\" }),\n });\n const table = adapter.tables.projects;\n const id = `conditional-contract-${randomUUID()}`;\n try {\n const now = new Date().toISOString();\n await adapter.insert(table, {\n id,\n name: \"before\",\n slug: id,\n createdAt: now,\n updatedAt: now,\n });\n const condition = ne(getTableColumns(table)[\"name\"]!, \"locked\");\n const first = await adapter.updateWhere(table, id, { name: \"locked\" }, condition);\n expect(first?.[\"name\"]).toBe(\"locked\");\n const refused = await adapter.updateWhere(table, id, { name: \"after\" }, condition);\n expect(refused?.[\"name\"]).toBe(\"locked\");\n expect((await adapter.get(table, id))?.[\"name\"]).toBe(\"locked\");\n expect(await adapter.updateWhere(table, \"missing\", { name: \"x\" }, condition)).toBeNull();\n } finally {\n try {\n await adapter.remove(table, id);\n } finally {\n await adapter.lifecycle?.teardown();\n }\n }\n }, 30_000);\n\n it(\"keeps the lifecycle rule (absent or all three hooks)\", async () => {\n const adapter = await make();\n const lifecycle = adapter.lifecycle as\n | { setup?: unknown; teardown?: unknown; health?: unknown }\n | undefined;\n if (lifecycle === undefined) {\n return;\n }\n expect(typeof lifecycle.setup).toBe(\"function\");\n expect(typeof lifecycle.teardown).toBe(\"function\");\n expect(typeof lifecycle.health).toBe(\"function\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,kBAAkB;AAE/B,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAMA,SAAgB,sBAAsB,OAAe,MAA6B;CAChF,SAAS,sBAAsB,eAAe;EAC5C,GAAG,6BAA6B,YAAY;GAC1C,MAAM,UAAU,MAAM,KAAK;GAC3B,OAAO,QAAQ,SAAS,QAAQ,CAAC,CAAC,KAAK,UAAU;GACjD,OAAO,QAAQ,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACxD,CAAC;EAED,GAAG,8BAA8B,YAAY;GAE3C,MAAM,UAAS,MADO,KAAK,EAAA,CACJ;GACvB,KAAK,MAAM,SAAS,iBAClB,OAAO,OAAO,QAAQ,kBAAkB,OAAO,CAAC,CAAC,YAAY;EAEjE,CAAC;EAED,GAAG,6BAA6B,YAAY;GAC1C,MAAM,UAAU,MAAM,KAAK;GAC3B,KAAK,MAAM,UAAU,kBACnB,OAAO,OAAQ,QAA+C,OAAO,CAAC,CAAC,KAAK,UAAU;EAE1F,CAAC;EAED,GAAG,kEAAkE,YAAY;GAC/E,MAAM,UAAU,MAAM,KAAK;GAC3B,MAAM,QAAQ,WAAW,MAAM;IAC7B,QAAQ,CAAC;IACT,QAAQ,kBAAkB,EAAE,OAAO,SAAS,CAAC;GAC/C,CAAC;GACD,MAAM,QAAQ,QAAQ,OAAO;GAC7B,MAAM,KAAK,wBAAwB,WAAW;GAC9C,IAAI;IACF,MAAM,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY;IACnC,MAAM,QAAQ,OAAO,OAAO;KAC1B;KACA,MAAM;KACN,MAAM;KACN,WAAW;KACX,WAAW;IACb,CAAC;IACD,MAAM,YAAY,GAAG,gBAAgB,KAAK,CAAC,CAAC,SAAU,QAAQ;IAC9D,MAAM,QAAQ,MAAM,QAAQ,YAAY,OAAO,IAAI,EAAE,MAAM,SAAS,GAAG,SAAS;IAChF,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,QAAQ;IACrC,MAAM,UAAU,MAAM,QAAQ,YAAY,OAAO,IAAI,EAAE,MAAM,QAAQ,GAAG,SAAS;IACjF,OAAO,UAAU,OAAO,CAAC,CAAC,KAAK,QAAQ;IACvC,QAAQ,MAAM,QAAQ,IAAI,OAAO,EAAE,EAAA,GAAK,OAAO,CAAC,CAAC,KAAK,QAAQ;IAC9D,OAAO,MAAM,QAAQ,YAAY,OAAO,WAAW,EAAE,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS;GACzF,UAAU;IACR,IAAI;KACF,MAAM,QAAQ,OAAO,OAAO,EAAE;IAChC,UAAU;KACR,MAAM,QAAQ,WAAW,SAAS;IACpC;GACF;EACF,GAAG,GAAM;EAET,GAAG,wDAAwD,YAAY;GAErE,MAAM,aAAY,MADI,KAAK,EAAA,CACD;GAG1B,IAAI,cAAc,KAAA,GAChB;GAEF,OAAO,OAAO,UAAU,KAAK,CAAC,CAAC,KAAK,UAAU;GAC9C,OAAO,OAAO,UAAU,QAAQ,CAAC,CAAC,KAAK,UAAU;GACjD,OAAO,OAAO,UAAU,MAAM,CAAC,CAAC,KAAK,UAAU;EACjD,CAAC;CACH,CAAC;AACH"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* A promise a test resolves by hand, for asserting concurrency and ordering without sleeping.
|
|
5
|
+
* Tests wait on `promise` to observe an in-flight state, then call `resolve()` to let it finish.
|
|
6
|
+
*/
|
|
7
|
+
/** A manually settled promise. */
|
|
8
|
+
interface Deferred<T = void> {
|
|
9
|
+
readonly promise: Promise<T>;
|
|
10
|
+
resolve(value: T): void;
|
|
11
|
+
reject(reason?: unknown): void;
|
|
12
|
+
}
|
|
13
|
+
/** Create a promise the test settles explicitly. */
|
|
14
|
+
declare function deferred<T = void>(): Deferred<T>;
|
|
15
|
+
/** A gate that holds every waiter until opened, then lets all future calls through. */
|
|
16
|
+
interface Latch {
|
|
17
|
+
wait(): Promise<void>;
|
|
18
|
+
open(): void;
|
|
19
|
+
readonly opened: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Create a latch that stays open once opened. */
|
|
22
|
+
declare function createLatch(): Latch;
|
|
23
|
+
/** A set of deferreds a test can release one at a time, in order. */
|
|
24
|
+
interface ReleaseQueue {
|
|
25
|
+
/** The next deferred to hand to a task. */
|
|
26
|
+
next(): Promise<void>;
|
|
27
|
+
/** Release the oldest waiter. */
|
|
28
|
+
release(): void;
|
|
29
|
+
/** Release every waiter created so far. */
|
|
30
|
+
releaseAll(): void;
|
|
31
|
+
/** Waiters created but not released yet. */
|
|
32
|
+
readonly pending: number;
|
|
33
|
+
}
|
|
34
|
+
/** Create a FIFO release queue. */
|
|
35
|
+
declare function createReleaseQueue(): ReleaseQueue;
|
|
36
|
+
export { Deferred, Latch, ReleaseQueue, createLatch, createReleaseQueue, deferred };
|
|
37
|
+
//# sourceMappingURL=deferred.d.mts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/test-helpers/deferred.ts
|
|
5
|
+
/** Create a promise the test settles explicitly. */
|
|
6
|
+
function deferred() {
|
|
7
|
+
let resolve;
|
|
8
|
+
let reject;
|
|
9
|
+
return {
|
|
10
|
+
promise: new Promise((promiseResolve, promiseReject) => {
|
|
11
|
+
resolve = promiseResolve;
|
|
12
|
+
reject = promiseReject;
|
|
13
|
+
}),
|
|
14
|
+
resolve,
|
|
15
|
+
reject
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Create a latch that stays open once opened. */
|
|
19
|
+
function createLatch() {
|
|
20
|
+
let opened = false;
|
|
21
|
+
const waiters = [];
|
|
22
|
+
return {
|
|
23
|
+
wait: () => {
|
|
24
|
+
if (opened) return Promise.resolve();
|
|
25
|
+
const waiter = deferred();
|
|
26
|
+
waiters.push(waiter);
|
|
27
|
+
return waiter.promise;
|
|
28
|
+
},
|
|
29
|
+
open: () => {
|
|
30
|
+
opened = true;
|
|
31
|
+
for (const waiter of waiters.splice(0)) waiter.resolve();
|
|
32
|
+
},
|
|
33
|
+
get opened() {
|
|
34
|
+
return opened;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Create a FIFO release queue. */
|
|
39
|
+
function createReleaseQueue() {
|
|
40
|
+
const waiters = [];
|
|
41
|
+
return {
|
|
42
|
+
next: () => {
|
|
43
|
+
const waiter = deferred();
|
|
44
|
+
waiters.push(waiter);
|
|
45
|
+
return waiter.promise;
|
|
46
|
+
},
|
|
47
|
+
release: () => {
|
|
48
|
+
waiters.shift()?.resolve();
|
|
49
|
+
},
|
|
50
|
+
releaseAll: () => {
|
|
51
|
+
for (const waiter of waiters.splice(0)) waiter.resolve();
|
|
52
|
+
},
|
|
53
|
+
get pending() {
|
|
54
|
+
return waiters.length;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export { createLatch, createReleaseQueue, deferred };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=deferred.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred.mjs","names":[],"sources":["../../src/test-helpers/deferred.ts"],"sourcesContent":["/**\n * A promise a test resolves by hand, for asserting concurrency and ordering without sleeping.\n * Tests wait on `promise` to observe an in-flight state, then call `resolve()` to let it finish.\n */\n\n/** A manually settled promise. */\nexport interface Deferred<T = void> {\n readonly promise: Promise<T>;\n resolve(value: T): void;\n reject(reason?: unknown): void;\n}\n\n/** Create a promise the test settles explicitly. */\nexport function deferred<T = void>(): Deferred<T> {\n let resolve!: (value: T) => void;\n let reject!: (reason?: unknown) => void;\n const promise = new Promise<T>((promiseResolve, promiseReject) => {\n resolve = promiseResolve;\n reject = promiseReject;\n });\n return { promise, resolve, reject };\n}\n\n/** A gate that holds every waiter until opened, then lets all future calls through. */\nexport interface Latch {\n wait(): Promise<void>;\n open(): void;\n readonly opened: boolean;\n}\n\n/** Create a latch that stays open once opened. */\nexport function createLatch(): Latch {\n let opened = false;\n const waiters: Deferred[] = [];\n return {\n wait: () => {\n if (opened) return Promise.resolve();\n const waiter = deferred();\n waiters.push(waiter);\n return waiter.promise;\n },\n open: () => {\n opened = true;\n for (const waiter of waiters.splice(0)) waiter.resolve();\n },\n get opened() {\n return opened;\n },\n };\n}\n\n/** A set of deferreds a test can release one at a time, in order. */\nexport interface ReleaseQueue {\n /** The next deferred to hand to a task. */\n next(): Promise<void>;\n /** Release the oldest waiter. */\n release(): void;\n /** Release every waiter created so far. */\n releaseAll(): void;\n /** Waiters created but not released yet. */\n readonly pending: number;\n}\n\n/** Create a FIFO release queue. */\nexport function createReleaseQueue(): ReleaseQueue {\n const waiters: Deferred[] = [];\n return {\n next: () => {\n const waiter = deferred();\n waiters.push(waiter);\n return waiter.promise;\n },\n release: () => {\n waiters.shift()?.resolve();\n },\n releaseAll: () => {\n for (const waiter of waiters.splice(0)) waiter.resolve();\n },\n get pending() {\n return waiters.length;\n },\n };\n}\n"],"mappings":";;;;;AAaA,SAAgB,WAAkC;CAChD,IAAI;CACJ,IAAI;CAKJ,OAAO;EAAE,SAAA,IAJW,SAAY,gBAAgB,kBAAkB;GAChE,UAAU;GACV,SAAS;EACX,CACe;EAAG;EAAS;CAAO;AACpC;;AAUA,SAAgB,cAAqB;CACnC,IAAI,SAAS;CACb,MAAM,UAAsB,CAAC;CAC7B,OAAO;EACL,YAAY;GACV,IAAI,QAAQ,OAAO,QAAQ,QAAQ;GACnC,MAAM,SAAS,SAAS;GACxB,QAAQ,KAAK,MAAM;GACnB,OAAO,OAAO;EAChB;EACA,YAAY;GACV,SAAS;GACT,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,GAAG,OAAO,QAAQ;EACzD;EACA,IAAI,SAAS;GACX,OAAO;EACT;CACF;AACF;;AAeA,SAAgB,qBAAmC;CACjD,MAAM,UAAsB,CAAC;CAC7B,OAAO;EACL,YAAY;GACV,MAAM,SAAS,SAAS;GACxB,QAAQ,KAAK,MAAM;GACnB,OAAO,OAAO;EAChB;EACA,eAAe;GACb,QAAQ,MAAM,CAAC,EAAE,QAAQ;EAC3B;EACA,kBAAkB;GAChB,KAAK,MAAM,UAAU,QAAQ,OAAO,CAAC,GAAG,OAAO,QAAQ;EACzD;EACA,IAAI,UAAU;GACZ,OAAO,QAAQ;EACjB;CACF;AACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DesignProvider } from "../adapter/design.mjs";
|
|
4
|
+
/** Build the provider under test (sync or async factories both work). */
|
|
5
|
+
type DesignFactory = () => DesignProvider | Promise<DesignProvider>;
|
|
6
|
+
/** Links the suite uses to probe `parseUrl`. */
|
|
7
|
+
interface DesignContractSamples {
|
|
8
|
+
/** A link the provider must accept, with the file key it must yield. */
|
|
9
|
+
valid: {
|
|
10
|
+
url: string;
|
|
11
|
+
fileKey: string;
|
|
12
|
+
};
|
|
13
|
+
/** A link the provider must reject. */
|
|
14
|
+
invalid: string;
|
|
15
|
+
}
|
|
16
|
+
/** Run the design-provider contract against a factory. */
|
|
17
|
+
declare function designContractSuite(label: string, make: DesignFactory, samples: DesignContractSamples): void;
|
|
18
|
+
export { DesignContractSamples, DesignFactory, designContractSuite };
|
|
19
|
+
//# sourceMappingURL=design-contract.d.mts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
// src/test-helpers/design-contract.ts
|
|
6
|
+
/**
|
|
7
|
+
* Published design-provider contract suite for first- and third-party providers.
|
|
8
|
+
*
|
|
9
|
+
* Structural conformance (identity, descriptor, link parsing). Vendor API calls
|
|
10
|
+
* stay per-package behind faked transports.
|
|
11
|
+
*/
|
|
12
|
+
/** Run the design-provider contract against a factory. */
|
|
13
|
+
function designContractSuite(label, make, samples) {
|
|
14
|
+
describe(`design contract: ${label}`, () => {
|
|
15
|
+
it("exposes design metadata with credential copy", async () => {
|
|
16
|
+
const { metadata } = await make();
|
|
17
|
+
expect(metadata.category).toBe("design");
|
|
18
|
+
expect(metadata.kind.length).toBeGreaterThan(0);
|
|
19
|
+
expect(metadata.credentialLabel.length).toBeGreaterThan(0);
|
|
20
|
+
expect(metadata.credentialHelp.length).toBeGreaterThan(0);
|
|
21
|
+
expect(metadata.urlHint.length).toBeGreaterThan(0);
|
|
22
|
+
});
|
|
23
|
+
it("parses its own links and rejects foreign ones", async () => {
|
|
24
|
+
const provider = await make();
|
|
25
|
+
expect(provider.parseUrl(samples.valid.url)?.fileKey).toBe(samples.valid.fileKey);
|
|
26
|
+
expect(provider.parseUrl(samples.invalid)).toBeNull();
|
|
27
|
+
expect(provider.parseUrl("not a url")).toBeNull();
|
|
28
|
+
expect(provider.parseUrl("")).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
it("creates a client with both fetch methods", async () => {
|
|
31
|
+
const client = (await make()).create({ credential: "test-credential" });
|
|
32
|
+
expect(typeof client.fetchMetas).toBe("function");
|
|
33
|
+
expect(typeof client.fetchRenders).toBe("function");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export { designContractSuite };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=design-contract.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-contract.mjs","names":[],"sources":["../../src/test-helpers/design-contract.ts"],"sourcesContent":["/**\n * Published design-provider contract suite for first- and third-party providers.\n *\n * Structural conformance (identity, descriptor, link parsing). Vendor API calls\n * stay per-package behind faked transports.\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { DesignProvider } from \"../adapters/design.ts\";\n\n/** Build the provider under test (sync or async factories both work). */\nexport type DesignFactory = () => DesignProvider | Promise<DesignProvider>;\n\n/** Links the suite uses to probe `parseUrl`. */\nexport interface DesignContractSamples {\n /** A link the provider must accept, with the file key it must yield. */\n valid: { url: string; fileKey: string };\n /** A link the provider must reject. */\n invalid: string;\n}\n\n/** Run the design-provider contract against a factory. */\nexport function designContractSuite(\n label: string,\n make: DesignFactory,\n samples: DesignContractSamples,\n): void {\n describe(`design contract: ${label}`, () => {\n it(\"exposes design metadata with credential copy\", async () => {\n const { metadata } = await make();\n expect(metadata.category).toBe(\"design\");\n expect(metadata.kind.length).toBeGreaterThan(0);\n expect(metadata.credentialLabel.length).toBeGreaterThan(0);\n expect(metadata.credentialHelp.length).toBeGreaterThan(0);\n expect(metadata.urlHint.length).toBeGreaterThan(0);\n });\n\n it(\"parses its own links and rejects foreign ones\", async () => {\n const provider = await make();\n expect(provider.parseUrl(samples.valid.url)?.fileKey).toBe(samples.valid.fileKey);\n expect(provider.parseUrl(samples.invalid)).toBeNull();\n expect(provider.parseUrl(\"not a url\")).toBeNull();\n expect(provider.parseUrl(\"\")).toBeNull();\n });\n\n it(\"creates a client with both fetch methods\", async () => {\n const client = (await make()).create({ credential: \"test-credential\" });\n expect(typeof client.fetchMetas).toBe(\"function\");\n expect(typeof client.fetchRenders).toBe(\"function\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAqBA,SAAgB,oBACd,OACA,MACA,SACM;CACN,SAAS,oBAAoB,eAAe;EAC1C,GAAG,gDAAgD,YAAY;GAC7D,MAAM,EAAE,aAAa,MAAM,KAAK;GAChC,OAAO,SAAS,QAAQ,CAAC,CAAC,KAAK,QAAQ;GACvC,OAAO,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;GAC9C,OAAO,SAAS,gBAAgB,MAAM,CAAC,CAAC,gBAAgB,CAAC;GACzD,OAAO,SAAS,eAAe,MAAM,CAAC,CAAC,gBAAgB,CAAC;GACxD,OAAO,SAAS,QAAQ,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACnD,CAAC;EAED,GAAG,iDAAiD,YAAY;GAC9D,MAAM,WAAW,MAAM,KAAK;GAC5B,OAAO,SAAS,SAAS,QAAQ,MAAM,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,KAAK,QAAQ,MAAM,OAAO;GAChF,OAAO,SAAS,SAAS,QAAQ,OAAO,CAAC,CAAC,CAAC,SAAS;GACpD,OAAO,SAAS,SAAS,WAAW,CAAC,CAAC,CAAC,SAAS;GAChD,OAAO,SAAS,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS;EACzC,CAAC;EAED,GAAG,4CAA4C,YAAY;GACzD,MAAM,UAAU,MAAM,KAAK,EAAA,CAAG,OAAO,EAAE,YAAY,kBAAkB,CAAC;GACtE,OAAO,OAAO,OAAO,UAAU,CAAC,CAAC,KAAK,UAAU;GAChD,OAAO,OAAO,OAAO,YAAY,CAAC,CAAC,KAAK,UAAU;EACpD,CAAC;CACH,CAAC;AACH"}
|
|
@@ -3,12 +3,10 @@ import __tsdown_shims_url from 'node:url';
|
|
|
3
3
|
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
4
|
import { makeDatabase } from "./fake-database.mjs";
|
|
5
5
|
import { FakeStorage, makeStorage } from "./fake-storage.mjs";
|
|
6
|
-
//#region src/test-helpers/fake-adapters.d.ts
|
|
7
6
|
/**
|
|
8
7
|
* Empty table map for spec/test doubles whose methods never run (OpenAPI
|
|
9
8
|
* generation, asset serving). Satisfies boot validation without a driver.
|
|
10
9
|
*/
|
|
11
10
|
declare function stubTables(): DatabaseAdapter["tables"];
|
|
12
|
-
//#endregion
|
|
13
11
|
export { type FakeStorage, makeDatabase, makeStorage, stubTables };
|
|
14
12
|
//# sourceMappingURL=fake-adapters.d.mts.map
|
|
@@ -4,7 +4,7 @@ import.meta.url;
|
|
|
4
4
|
import { REQUIRED_TABLE_KEYS } from "../adapter/database.mjs";
|
|
5
5
|
import { makeDatabase } from "./fake-database.mjs";
|
|
6
6
|
import { makeStorage } from "./fake-storage.mjs";
|
|
7
|
-
|
|
7
|
+
// src/test-helpers/fake-adapters.ts
|
|
8
8
|
/**
|
|
9
9
|
* Empty table map for spec/test doubles whose methods never run (OpenAPI
|
|
10
10
|
* generation, asset serving). Satisfies boot validation without a driver.
|
|
@@ -14,7 +14,6 @@ function stubTables() {
|
|
|
14
14
|
for (const key of REQUIRED_TABLE_KEYS) tables[key] = {};
|
|
15
15
|
return tables;
|
|
16
16
|
}
|
|
17
|
-
//#endregion
|
|
18
17
|
export { makeDatabase, makeStorage, stubTables };
|
|
19
18
|
|
|
20
19
|
//# sourceMappingURL=fake-adapters.mjs.map
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
-
//#region src/test-helpers/fake-database.d.ts
|
|
5
4
|
/** Create an in-memory database adapter for capture pipeline tests. */
|
|
6
5
|
declare function makeDatabase(): {
|
|
7
6
|
db: DatabaseAdapter;
|
|
8
7
|
};
|
|
9
|
-
//#endregion
|
|
10
8
|
export { makeDatabase };
|
|
11
9
|
//# sourceMappingURL=fake-database.d.mts.map
|
|
@@ -4,10 +4,16 @@ import.meta.url;
|
|
|
4
4
|
import { clampListLimit } from "../adapter/database.mjs";
|
|
5
5
|
import { fakeSchema } from "./fake-tables.mjs";
|
|
6
6
|
import { orderRows, whereMatches } from "./sql-chunks.mjs";
|
|
7
|
-
|
|
7
|
+
import { getTableName } from "drizzle-orm";
|
|
8
|
+
// src/test-helpers/fake-database.ts
|
|
8
9
|
function withoutUndefined(values) {
|
|
9
10
|
return Object.fromEntries(Object.entries(values).filter((pair) => pair[1] !== void 0));
|
|
10
11
|
}
|
|
12
|
+
/** Column defaults real drivers apply on insert (the fake has no DDL). */
|
|
13
|
+
const INSERT_DEFAULTS = {
|
|
14
|
+
snapshots: { browser: "chromium" },
|
|
15
|
+
baselines: { browser: "chromium" }
|
|
16
|
+
};
|
|
11
17
|
/** Create an in-memory database adapter for capture pipeline tests. */
|
|
12
18
|
function makeDatabase() {
|
|
13
19
|
const store = /* @__PURE__ */ new Map();
|
|
@@ -20,8 +26,12 @@ function makeDatabase() {
|
|
|
20
26
|
return rowMap;
|
|
21
27
|
};
|
|
22
28
|
const insertRow = async (table, values) => {
|
|
23
|
-
const row =
|
|
29
|
+
const row = {
|
|
30
|
+
...INSERT_DEFAULTS[getTableName(table)],
|
|
31
|
+
...withoutUndefined(values)
|
|
32
|
+
};
|
|
24
33
|
const key = row["id"] ?? row["hash"];
|
|
34
|
+
if (rowsOf(table).has(key)) throw new Error(`UNIQUE constraint failed: duplicate key ${key}`);
|
|
25
35
|
rowsOf(table).set(key, row);
|
|
26
36
|
return row;
|
|
27
37
|
};
|
|
@@ -47,7 +57,9 @@ function makeDatabase() {
|
|
|
47
57
|
current = current.filter((row) => whereMatches(where, row, table));
|
|
48
58
|
}
|
|
49
59
|
if (opts.orderBy) current = orderRows(current, opts.orderBy, table);
|
|
50
|
-
|
|
60
|
+
const start = opts.offset ?? 0;
|
|
61
|
+
if (opts.limit !== void 0) current = current.slice(start, start + (clampListLimit(opts.limit) ?? 0));
|
|
62
|
+
else if (start > 0) current = current.slice(start);
|
|
51
63
|
return current;
|
|
52
64
|
};
|
|
53
65
|
const countRows = async (table, where) => {
|
|
@@ -84,6 +96,12 @@ function makeDatabase() {
|
|
|
84
96
|
tables: fakeSchema,
|
|
85
97
|
insert: insertRow,
|
|
86
98
|
update: updateRow,
|
|
99
|
+
updateWhere: async (table, id, values, where) => {
|
|
100
|
+
const current = rowsOf(table).get(id);
|
|
101
|
+
if (!current) return null;
|
|
102
|
+
if (whereMatches(where, current, table)) return await updateRow(table, id, values);
|
|
103
|
+
return current;
|
|
104
|
+
},
|
|
87
105
|
get: getRow,
|
|
88
106
|
remove: async (table, id) => {
|
|
89
107
|
rowsOf(table).delete(id);
|
|
@@ -98,7 +116,6 @@ function makeDatabase() {
|
|
|
98
116
|
}
|
|
99
117
|
} };
|
|
100
118
|
}
|
|
101
|
-
//#endregion
|
|
102
119
|
export { makeDatabase };
|
|
103
120
|
|
|
104
121
|
//# sourceMappingURL=fake-database.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-database.mjs","names":[],"sources":["../../src/test-helpers/fake-database.ts"],"sourcesContent":["import type { SQL, Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter, ListOptions, TxStore } from \"../adapters/database.ts\";\nimport { clampListLimit } from \"../adapters/database.ts\";\nimport { fakeSchema } from \"./fake-tables.ts\";\nimport { orderRows, whereMatches } from \"./sql-chunks.ts\";\n\nfunction withoutUndefined(values: unknown): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(values as Record<string, unknown>).filter((pair) => pair[1] !== undefined),\n );\n}\n\n// The in-memory fake back-fills Drizzle's inferred row types from raw maps\n// Without a driver, so the casts and await-free `async` methods are unavoidable.\n/* eslint-disable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n/** Create an in-memory database adapter for capture pipeline tests. */\nexport function makeDatabase(): { db: DatabaseAdapter } {\n const store = new Map<Table, Map<string, unknown>>();\n\n const rowsOf = (table: Table): Map<string, unknown> => {\n let rowMap = store.get(table);\n if (!rowMap) {\n rowMap = new Map();\n store.set(table, rowMap);\n }\n return rowMap;\n };\n\n const insertRow = async <T extends Table>(\n table: T,\n values: T[\"$inferInsert\"],\n ): Promise<T[\"$inferSelect\"]> => {\n const row = withoutUndefined(values);\n const key = (row[\"id\"] ?? row[\"hash\"]) as string;\n rowsOf(table).set(key, row);\n return row as T[\"$inferSelect\"];\n };\n\n const updateRow = async <T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]> => {\n const current = rowsOf(table).get(id) as Record<string, unknown> | undefined;\n if (current === undefined) {\n throw new Error(\"row not found\");\n }\n const merged = withoutUndefined({ ...current, ...values });\n rowsOf(table).set(id, merged);\n return merged as T[\"$inferSelect\"];\n };\n\n const getRow = async <T extends Table>(\n table: T,\n id: string,\n ): Promise<T[\"$inferSelect\"] | null> => {\n const found = rowsOf(table).get(id);\n if (found === undefined) {\n return null;\n }\n return found as T[\"$inferSelect\"];\n };\n\n const listRows = async <T extends Table>(\n table: T,\n opts: ListOptions = {},\n ): Promise<T[\"$inferSelect\"][]> => {\n let current = [...rowsOf(table).values()];\n if (opts.where) {\n const { where } = opts;\n current = current.filter((row) => whereMatches(where, row as Record<string, unknown>, table));\n }\n if (opts.orderBy) {\n current = orderRows(current, opts.orderBy, table);\n }\n if (opts.limit !== undefined) {\n current = current.slice(
|
|
1
|
+
{"version":3,"file":"fake-database.mjs","names":[],"sources":["../../src/test-helpers/fake-database.ts"],"sourcesContent":["import { getTableName } from \"drizzle-orm\";\nimport type { SQL, Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter, ListOptions, TxStore } from \"../adapters/database.ts\";\nimport { clampListLimit } from \"../adapters/database.ts\";\nimport { fakeSchema } from \"./fake-tables.ts\";\nimport { orderRows, whereMatches } from \"./sql-chunks.ts\";\n\nfunction withoutUndefined(values: unknown): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(values as Record<string, unknown>).filter((pair) => pair[1] !== undefined),\n );\n}\n\n/** Column defaults real drivers apply on insert (the fake has no DDL). */\nconst INSERT_DEFAULTS: Record<string, Record<string, unknown>> = {\n snapshots: { browser: \"chromium\" },\n baselines: { browser: \"chromium\" },\n};\n\n// The in-memory fake back-fills Drizzle's inferred row types from raw maps\n// Without a driver, so the casts and await-free `async` methods are unavoidable.\n/* eslint-disable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n/** Create an in-memory database adapter for capture pipeline tests. */\nexport function makeDatabase(): { db: DatabaseAdapter } {\n const store = new Map<Table, Map<string, unknown>>();\n\n const rowsOf = (table: Table): Map<string, unknown> => {\n let rowMap = store.get(table);\n if (!rowMap) {\n rowMap = new Map();\n store.set(table, rowMap);\n }\n return rowMap;\n };\n\n const insertRow = async <T extends Table>(\n table: T,\n values: T[\"$inferInsert\"],\n ): Promise<T[\"$inferSelect\"]> => {\n const row = { ...INSERT_DEFAULTS[getTableName(table)], ...withoutUndefined(values) };\n const key = (row[\"id\"] ?? row[\"hash\"]) as string;\n if (rowsOf(table).has(key)) {\n throw new Error(`UNIQUE constraint failed: duplicate key ${key}`);\n }\n rowsOf(table).set(key, row);\n return row as T[\"$inferSelect\"];\n };\n\n const updateRow = async <T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]> => {\n const current = rowsOf(table).get(id) as Record<string, unknown> | undefined;\n if (current === undefined) {\n throw new Error(\"row not found\");\n }\n const merged = withoutUndefined({ ...current, ...values });\n rowsOf(table).set(id, merged);\n return merged as T[\"$inferSelect\"];\n };\n\n const getRow = async <T extends Table>(\n table: T,\n id: string,\n ): Promise<T[\"$inferSelect\"] | null> => {\n const found = rowsOf(table).get(id);\n if (found === undefined) {\n return null;\n }\n return found as T[\"$inferSelect\"];\n };\n\n const listRows = async <T extends Table>(\n table: T,\n opts: ListOptions = {},\n ): Promise<T[\"$inferSelect\"][]> => {\n let current = [...rowsOf(table).values()];\n if (opts.where) {\n const { where } = opts;\n current = current.filter((row) => whereMatches(where, row as Record<string, unknown>, table));\n }\n if (opts.orderBy) {\n current = orderRows(current, opts.orderBy, table);\n }\n const start = opts.offset ?? 0;\n if (opts.limit !== undefined) {\n current = current.slice(start, start + (clampListLimit(opts.limit) ?? 0));\n } else if (start > 0) {\n current = current.slice(start);\n }\n return current as T[\"$inferSelect\"][];\n };\n\n const countRows = async (table: Table, where?: SQL): Promise<number> => {\n const matching = await listRows(table, where ? { where } : {});\n return matching.length;\n };\n\n const transactRows = async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> => {\n const snapshot = new Map<Table, Map<string, unknown>>();\n for (const [table, rows] of store) {\n snapshot.set(\n table,\n new Map([...rows].map(([id, row]) => [id, { ...(row as Record<string, unknown>) }])),\n );\n }\n const tx: TxStore = {\n insert: insertRow,\n update: updateRow,\n get: getRow,\n remove: async (table, id) => {\n rowsOf(table).delete(id);\n },\n list: listRows,\n count: countRows,\n };\n try {\n return await fn(tx);\n } catch (error) {\n store.clear();\n for (const [table, rows] of snapshot) {\n store.set(table, rows);\n }\n throw error;\n }\n };\n\n const db: DatabaseAdapter = {\n metadata: { name: \"Fake Database\", version: \"0.0.0\", kind: \"memory\", category: \"database\" },\n tables: fakeSchema,\n insert: insertRow,\n update: updateRow,\n updateWhere: async (table, id, values, where) => {\n const current = rowsOf(table).get(id) as Record<string, unknown> | undefined;\n if (!current) return null;\n if (whereMatches(where, current, table)) return await updateRow(table, id, values);\n return current as never;\n },\n get: getRow,\n remove: async (table, id) => {\n rowsOf(table).delete(id);\n },\n list: listRows,\n count: countRows,\n transact: transactRows,\n all: async (_query: SQL) => {\n const results: Record<string, unknown>[] = [];\n for (const rows of store.values()) {\n for (const row of rows.values()) {\n results.push(row as Record<string, unknown>);\n }\n }\n return results as never[];\n },\n };\n return { db };\n}\n/* eslint-enable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DesignProvider, DesignState } from "../adapter/design.mjs";
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
declare const FAKE_PNG: Buffer<ArrayBuffer>;
|
|
6
|
+
/** Mutable behavior and call log of a {@link makeFakeDesign} provider. */
|
|
7
|
+
interface FakeDesign {
|
|
8
|
+
provider: DesignProvider;
|
|
9
|
+
/** File version served; bump it to simulate an edit. */
|
|
10
|
+
version: string;
|
|
11
|
+
lastModified: string;
|
|
12
|
+
/** Per node id (`""` = whole file) state override; defaults to `ok`. */
|
|
13
|
+
states: Map<string, DesignState>;
|
|
14
|
+
/** Node ids the vendor cannot render. */
|
|
15
|
+
unrenderable: Set<string>;
|
|
16
|
+
/** Make every render call throw. */
|
|
17
|
+
failRenders: boolean;
|
|
18
|
+
/** Artificial latency per call, to observe concurrency. */
|
|
19
|
+
delayMs: number;
|
|
20
|
+
/** Credentials the provider was created with, in order. */
|
|
21
|
+
credentials: string[];
|
|
22
|
+
/** How each of those credentials authenticates, in the same order. */
|
|
23
|
+
authTypes: string[];
|
|
24
|
+
metaCalls: {
|
|
25
|
+
fileKey: string;
|
|
26
|
+
nodeIds: string[];
|
|
27
|
+
}[];
|
|
28
|
+
renderCalls: {
|
|
29
|
+
fileKey: string;
|
|
30
|
+
nodeIds: string[];
|
|
31
|
+
}[];
|
|
32
|
+
/** Calls currently in flight and the highest value seen. */
|
|
33
|
+
inFlight: number;
|
|
34
|
+
peak: number;
|
|
35
|
+
}
|
|
36
|
+
/** Link to a fake file, optionally a node of it. */
|
|
37
|
+
declare const fakeUrl: (fileKey: string, nodeId?: string) => string;
|
|
38
|
+
/** Create a fake provider whose behavior the test mutates through the returned object. */
|
|
39
|
+
declare function makeFakeDesign(kind?: string): FakeDesign;
|
|
40
|
+
export { FAKE_PNG, FakeDesign, fakeUrl, makeFakeDesign };
|
|
41
|
+
//# sourceMappingURL=fake-design.d.mts.map
|