@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
|
@@ -4,15 +4,14 @@ import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
|
4
4
|
import { ProjectRole } from "../types.mjs";
|
|
5
5
|
import { ProjectGroupMapping } from "../schema/project-group-mapping.mjs";
|
|
6
6
|
import { Table } from "drizzle-orm";
|
|
7
|
-
//#region src/models/project-group-mapping.d.ts
|
|
8
7
|
/** Tables required by {@link ProjectGroupMappingModel}. */
|
|
9
8
|
interface ProjectGroupMappingTables {
|
|
10
9
|
projectGroupMappings: Table;
|
|
11
10
|
}
|
|
12
11
|
/** Data operations for identity-provider group mappings. */
|
|
13
12
|
declare class ProjectGroupMappingModel {
|
|
14
|
-
private readonly db;
|
|
15
13
|
private readonly tables;
|
|
14
|
+
private readonly db;
|
|
16
15
|
/**
|
|
17
16
|
* @param db - Database adapter.
|
|
18
17
|
* @param tables - Table handles.
|
|
@@ -20,11 +19,15 @@ declare class ProjectGroupMappingModel {
|
|
|
20
19
|
constructor(db: DatabaseAdapter, tables?: ProjectGroupMappingTables);
|
|
21
20
|
/** List all group mappings for a project. */
|
|
22
21
|
list(projectId: string): Promise<ProjectGroupMapping[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Validate group-mapping input; returns an error message, or null when acceptable.
|
|
24
|
+
* Names match exactly: a wildcard would silently grant org-wide access.
|
|
25
|
+
*/
|
|
26
|
+
static inputError(groupName: string | undefined, role: string | undefined): string | null;
|
|
23
27
|
/** Create a group mapping for a project. */
|
|
24
28
|
create(projectId: string, groupName: string, role: ProjectRole): Promise<ProjectGroupMapping>;
|
|
25
29
|
/** Remove a group mapping by id within a project. */
|
|
26
30
|
remove(projectId: string, id: string): Promise<void>;
|
|
27
31
|
}
|
|
28
|
-
//#endregion
|
|
29
32
|
export { ProjectGroupMappingModel, ProjectGroupMappingTables };
|
|
30
33
|
//# sourceMappingURL=project-group-mapping.d.mts.map
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { isProjectRole } from "../types.mjs";
|
|
4
5
|
import { ulid } from "../utils/ulid.mjs";
|
|
5
|
-
import {
|
|
6
|
-
|
|
6
|
+
import { col } from "./columns.mjs";
|
|
7
|
+
import { and, eq } from "drizzle-orm";
|
|
8
|
+
// src/models/project-group-mapping.ts
|
|
7
9
|
/** Project group-to-role mappings for OIDC team sync. */
|
|
8
10
|
/** Data operations for identity-provider group mappings. */
|
|
9
11
|
var ProjectGroupMappingModel = class {
|
|
10
|
-
db;
|
|
11
12
|
tables;
|
|
13
|
+
db;
|
|
12
14
|
/**
|
|
13
15
|
* @param db - Database adapter.
|
|
14
16
|
* @param tables - Table handles.
|
|
@@ -19,7 +21,15 @@ var ProjectGroupMappingModel = class {
|
|
|
19
21
|
}
|
|
20
22
|
/** List all group mappings for a project. */
|
|
21
23
|
async list(projectId) {
|
|
22
|
-
return await this.db.list(this.tables.projectGroupMappings, { where: eq(
|
|
24
|
+
return await this.db.list(this.tables.projectGroupMappings, { where: eq(col(this.tables.projectGroupMappings, "projectId"), projectId) });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validate group-mapping input; returns an error message, or null when acceptable.
|
|
28
|
+
* Names match exactly: a wildcard would silently grant org-wide access.
|
|
29
|
+
*/
|
|
30
|
+
static inputError(groupName, role) {
|
|
31
|
+
if (!groupName || !role || !isProjectRole(role)) return "Group and role are required";
|
|
32
|
+
return groupName.includes("*") ? "Group names match exactly; wildcards are not expanded. A broad pattern can silently grant org-wide access." : null;
|
|
23
33
|
}
|
|
24
34
|
/** Create a group mapping for a project. */
|
|
25
35
|
async create(projectId, groupName, role) {
|
|
@@ -34,13 +44,12 @@ var ProjectGroupMappingModel = class {
|
|
|
34
44
|
/** Remove a group mapping by id within a project. */
|
|
35
45
|
async remove(projectId, id) {
|
|
36
46
|
const rows = await this.db.list(this.tables.projectGroupMappings, {
|
|
37
|
-
where: and(eq(
|
|
47
|
+
where: and(eq(col(this.tables.projectGroupMappings, "id"), id), eq(col(this.tables.projectGroupMappings, "projectId"), projectId)),
|
|
38
48
|
limit: 1
|
|
39
49
|
});
|
|
40
50
|
if (rows[0]) await this.db.remove(this.tables.projectGroupMappings, rows[0].id);
|
|
41
51
|
}
|
|
42
52
|
};
|
|
43
|
-
//#endregion
|
|
44
53
|
export { ProjectGroupMappingModel };
|
|
45
54
|
|
|
46
55
|
//# sourceMappingURL=project-group-mapping.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-group-mapping.mjs","names":[],"sources":["../../src/models/project-group-mapping.ts"],"sourcesContent":["/** Project group-to-role mappings for OIDC team sync. */\nimport { and, eq
|
|
1
|
+
{"version":3,"file":"project-group-mapping.mjs","names":[],"sources":["../../src/models/project-group-mapping.ts"],"sourcesContent":["/** Project group-to-role mappings for OIDC team sync. */\nimport { and, eq } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { ProjectGroupMapping } from \"../schema/project-group-mapping.ts\";\nimport { isProjectRole, type ProjectRole } from \"../types.ts\";\nimport { ulid } from \"../utils/ulid.ts\";\nimport { col } from \"./columns.ts\";\n\n/** Tables required by {@link ProjectGroupMappingModel}. */\nexport interface ProjectGroupMappingTables {\n projectGroupMappings: Table;\n}\n\n/** Data operations for identity-provider group mappings. */\nexport class ProjectGroupMappingModel {\n private readonly tables: ProjectGroupMappingTables;\n private readonly db: DatabaseAdapter;\n\n /**\n * @param db - Database adapter.\n * @param tables - Table handles.\n */\n constructor(db: DatabaseAdapter, tables?: ProjectGroupMappingTables) {\n this.db = db;\n this.tables = tables ?? { projectGroupMappings: db.tables.projectGroupMappings };\n }\n\n /** List all group mappings for a project. */\n async list(projectId: string): Promise<ProjectGroupMapping[]> {\n return (await this.db.list(this.tables.projectGroupMappings, {\n where: eq(col(this.tables.projectGroupMappings, \"projectId\"), projectId),\n })) as unknown as ProjectGroupMapping[];\n }\n\n /**\n * Validate group-mapping input; returns an error message, or null when acceptable.\n * Names match exactly: a wildcard would silently grant org-wide access.\n */\n static inputError(groupName: string | undefined, role: string | undefined): string | null {\n if (!groupName || !role || !isProjectRole(role)) {\n return \"Group and role are required\";\n }\n return groupName.includes(\"*\")\n ? \"Group names match exactly; wildcards are not expanded. A broad pattern can silently grant org-wide access.\"\n : null;\n }\n\n /** Create a group mapping for a project. */\n async create(\n projectId: string,\n groupName: string,\n role: ProjectRole,\n ): Promise<ProjectGroupMapping> {\n return (await this.db.insert(this.tables.projectGroupMappings, {\n id: ulid(),\n projectId,\n groupName,\n role,\n createdAt: new Date().toISOString(),\n })) as unknown as ProjectGroupMapping;\n }\n\n /** Remove a group mapping by id within a project. */\n async remove(projectId: string, id: string): Promise<void> {\n const rows = (await this.db.list(this.tables.projectGroupMappings, {\n where: and(\n eq(col(this.tables.projectGroupMappings, \"id\"), id),\n eq(col(this.tables.projectGroupMappings, \"projectId\"), projectId),\n ),\n limit: 1,\n })) as unknown as ProjectGroupMapping[];\n if (rows[0]) {\n await this.db.remove(this.tables.projectGroupMappings, rows[0].id);\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAeA,IAAa,2BAAb,MAAsC;CACpC;CACA;;;;;CAMA,YAAY,IAAqB,QAAoC;EACnE,KAAK,KAAK;EACV,KAAK,SAAS,UAAU,EAAE,sBAAsB,GAAG,OAAO,qBAAqB;CACjF;;CAGA,MAAM,KAAK,WAAmD;EAC5D,OAAQ,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,sBAAsB,EAC3D,OAAO,GAAG,IAAI,KAAK,OAAO,sBAAsB,WAAW,GAAG,SAAS,EACzE,CAAC;CACH;;;;;CAMA,OAAO,WAAW,WAA+B,MAAyC;EACxF,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,IAAI,GAC5C,OAAO;EAET,OAAO,UAAU,SAAS,GAAG,IACzB,+GACA;CACN;;CAGA,MAAM,OACJ,WACA,WACA,MAC8B;EAC9B,OAAQ,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,sBAAsB;GAC7D,IAAI,KAAK;GACT;GACA;GACA;GACA,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;EACpC,CAAC;CACH;;CAGA,MAAM,OAAO,WAAmB,IAA2B;EACzD,MAAM,OAAQ,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,sBAAsB;GACjE,OAAO,IACL,GAAG,IAAI,KAAK,OAAO,sBAAsB,IAAI,GAAG,EAAE,GAClD,GAAG,IAAI,KAAK,OAAO,sBAAsB,WAAW,GAAG,SAAS,CAClE;GACA,OAAO;EACT,CAAC;EACD,IAAI,KAAK,IACP,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,sBAAsB,KAAK,EAAE,CAAC,EAAE;CAErE;AACF"}
|
|
@@ -3,15 +3,14 @@ import __tsdown_shims_url from 'node:url';
|
|
|
3
3
|
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
4
|
import { Project } from "../schema/project.mjs";
|
|
5
5
|
import { Table } from "drizzle-orm";
|
|
6
|
-
//#region src/models/project.d.ts
|
|
7
6
|
/** Tables required by {@link ProjectModel}. */
|
|
8
7
|
interface ProjectTables {
|
|
9
8
|
projects: Table;
|
|
10
9
|
}
|
|
11
10
|
/** Data operations for project records. */
|
|
12
11
|
declare class ProjectModel {
|
|
13
|
-
private readonly db;
|
|
14
12
|
private readonly tables;
|
|
13
|
+
private readonly db;
|
|
15
14
|
/**
|
|
16
15
|
* @param db - Database adapter.
|
|
17
16
|
* @param tables - Table handles (injected by the database adapter).
|
|
@@ -46,9 +45,16 @@ interface ProjectCreateInput {
|
|
|
46
45
|
storybookMeta?: unknown;
|
|
47
46
|
/** Run Storybook `play` functions during capture (opt-in; default false). */
|
|
48
47
|
executePlay?: boolean;
|
|
48
|
+
/** Run axe accessibility checks during capture (column default true when omitted). */
|
|
49
|
+
runA11y?: boolean;
|
|
50
|
+
/** Run Storybook 10 `.test()` entries as interaction tests (column default false when omitted). */
|
|
51
|
+
runTests?: boolean;
|
|
49
52
|
/** Per-story play timeout in milliseconds (column default applies when omitted). */
|
|
50
53
|
playTimeoutMs?: number;
|
|
54
|
+
/** Review switch (column default true when omitted; ADR 0013, decision 1). */
|
|
55
|
+
reviewEnabled?: boolean;
|
|
56
|
+
/** Approvals a build needs with `testing` off (column default 1 when omitted). */
|
|
57
|
+
reviewApprovals?: number;
|
|
51
58
|
}
|
|
52
|
-
//#endregion
|
|
53
59
|
export { ProjectCreateInput, ProjectModel, ProjectTables };
|
|
54
60
|
//# sourceMappingURL=project.d.mts.map
|
package/dist/models/project.mjs
CHANGED
|
@@ -2,13 +2,14 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { slugify, ulid } from "../utils/ulid.mjs";
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { col } from "./columns.mjs";
|
|
6
|
+
import { eq } from "drizzle-orm";
|
|
7
|
+
// src/models/project.ts
|
|
7
8
|
/** Project records and slug management. */
|
|
8
9
|
/** Data operations for project records. */
|
|
9
10
|
var ProjectModel = class {
|
|
10
|
-
db;
|
|
11
11
|
tables;
|
|
12
|
+
db;
|
|
12
13
|
/**
|
|
13
14
|
* @param db - Database adapter.
|
|
14
15
|
* @param tables - Table handles (injected by the database adapter).
|
|
@@ -34,7 +35,11 @@ var ProjectModel = class {
|
|
|
34
35
|
gitDefaultBranch: input.gitDefaultBranch ?? "main",
|
|
35
36
|
storybookMeta: input.storybookMeta ? JSON.stringify(input.storybookMeta) : null,
|
|
36
37
|
...input.executePlay === void 0 ? {} : { executePlay: input.executePlay },
|
|
38
|
+
...input.runA11y === void 0 ? {} : { runA11y: input.runA11y },
|
|
39
|
+
...input.runTests === void 0 ? {} : { runTests: input.runTests },
|
|
37
40
|
...input.playTimeoutMs === void 0 ? {} : { playTimeoutMs: input.playTimeoutMs },
|
|
41
|
+
...input.reviewEnabled === void 0 ? {} : { reviewEnabled: input.reviewEnabled },
|
|
42
|
+
...input.reviewApprovals === void 0 ? {} : { reviewApprovals: input.reviewApprovals },
|
|
38
43
|
createdAt: now,
|
|
39
44
|
updatedAt: now
|
|
40
45
|
});
|
|
@@ -46,7 +51,7 @@ var ProjectModel = class {
|
|
|
46
51
|
/** Fetch a project by its slug, or null if not found. */
|
|
47
52
|
async getBySlug(slug) {
|
|
48
53
|
return (await this.db.list(this.tables.projects, {
|
|
49
|
-
where: eq(
|
|
54
|
+
where: eq(col(this.tables.projects, "slug"), slug),
|
|
50
55
|
limit: 1
|
|
51
56
|
}))[0] ?? null;
|
|
52
57
|
}
|
|
@@ -69,7 +74,7 @@ var ProjectModel = class {
|
|
|
69
74
|
}
|
|
70
75
|
async uniqueSlug(name) {
|
|
71
76
|
const base = slugify(name) || "project";
|
|
72
|
-
const existing = await this.db.list(this.tables.projects, { where: eq(
|
|
77
|
+
const existing = await this.db.list(this.tables.projects, { where: eq(col(this.tables.projects, "slug"), base) });
|
|
73
78
|
if (existing.length === 0) return base;
|
|
74
79
|
const taken = new Set(existing.map((p) => p.slug));
|
|
75
80
|
let suffix = 2;
|
|
@@ -77,7 +82,6 @@ var ProjectModel = class {
|
|
|
77
82
|
return `${base}-${suffix}`;
|
|
78
83
|
}
|
|
79
84
|
};
|
|
80
|
-
//#endregion
|
|
81
85
|
export { ProjectModel };
|
|
82
86
|
|
|
83
87
|
//# sourceMappingURL=project.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.mjs","names":[],"sources":["../../src/models/project.ts"],"sourcesContent":["/** Project records and slug management. */\nimport { eq
|
|
1
|
+
{"version":3,"file":"project.mjs","names":[],"sources":["../../src/models/project.ts"],"sourcesContent":["/** Project records and slug management. */\nimport { eq } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { Project } from \"../schema/project.ts\";\nimport { slugify, ulid } from \"../utils/ulid.ts\";\nimport { col } from \"./columns.ts\";\n\n/** Tables required by {@link ProjectModel}. */\nexport interface ProjectTables {\n projects: Table;\n}\n\n/** Data operations for project records. */\nexport class ProjectModel {\n private readonly tables: ProjectTables;\n private readonly db: DatabaseAdapter;\n\n /**\n * @param db - Database adapter.\n * @param tables - Table handles (injected by the database adapter).\n */\n constructor(db: DatabaseAdapter, tables?: ProjectTables) {\n this.db = db;\n this.tables = tables ?? { projects: db.tables.projects };\n }\n\n /**\n * Create a project with a unique slug.\n *\n * @param input - Project creation input.\n * @returns The created project.\n */\n async create(input: ProjectCreateInput): Promise<Project> {\n const now = new Date().toISOString();\n const slug = await this.uniqueSlug(input.name);\n return (await this.db.insert(this.tables.projects, {\n id: ulid(),\n name: input.name,\n slug,\n gitRepository: input.gitRepository,\n gitDefaultBranch: input.gitDefaultBranch ?? \"main\",\n storybookMeta: input.storybookMeta ? JSON.stringify(input.storybookMeta) : null,\n ...(input.executePlay === undefined ? {} : { executePlay: input.executePlay }),\n ...(input.runA11y === undefined ? {} : { runA11y: input.runA11y }),\n ...(input.runTests === undefined ? {} : { runTests: input.runTests }),\n ...(input.playTimeoutMs === undefined ? {} : { playTimeoutMs: input.playTimeoutMs }),\n ...(input.reviewEnabled === undefined ? {} : { reviewEnabled: input.reviewEnabled }),\n ...(input.reviewApprovals === undefined ? {} : { reviewApprovals: input.reviewApprovals }),\n createdAt: now,\n updatedAt: now,\n })) as unknown as Project;\n }\n\n /** Fetch a project by id, or null if not found. */\n async get(id: string): Promise<Project | null> {\n return (await this.db.get(this.tables.projects, id)) as unknown as Project | null;\n }\n\n /** Fetch a project by its slug, or null if not found. */\n async getBySlug(slug: string): Promise<Project | null> {\n const rows = (await this.db.list(this.tables.projects, {\n where: eq(col(this.tables.projects, \"slug\"), slug),\n limit: 1,\n })) as unknown as Project[];\n return rows[0] ?? null;\n }\n\n /** List all projects. */\n async list(): Promise<Project[]> {\n return (await this.db.list(this.tables.projects)) as unknown as Project[];\n }\n\n /** Update mutable fields of a project. */\n async update(\n id: string,\n patch: Partial<Omit<Project, \"storybookMeta\">> & {\n storybookMeta?: unknown;\n },\n ): Promise<Project> {\n const normalized: Partial<Project> & Record<string, unknown> = {\n ...patch,\n } as unknown as Partial<Project> & Record<string, unknown>;\n if (\n patch.storybookMeta !== undefined &&\n patch.storybookMeta !== null &&\n typeof patch.storybookMeta !== \"string\"\n ) {\n normalized.storybookMeta = JSON.stringify(patch.storybookMeta);\n }\n return (await this.db.update(this.tables.projects, id, {\n ...normalized,\n updatedAt: new Date().toISOString(),\n })) as unknown as Project;\n }\n\n /** Delete a project by id. */\n async remove(id: string): Promise<void> {\n await this.db.remove(this.tables.projects, id);\n }\n\n private async uniqueSlug(name: string): Promise<string> {\n const base = slugify(name) || \"project\";\n const existing = (await this.db.list(this.tables.projects, {\n where: eq(col(this.tables.projects, \"slug\"), base),\n })) as unknown as Project[];\n if (existing.length === 0) {\n return base;\n }\n const taken = new Set(existing.map((p) => p.slug));\n let suffix = 2;\n while (taken.has(`${base}-${suffix}`)) {\n suffix += 1;\n }\n return `${base}-${suffix}`;\n }\n}\n\n/** Input for creating a project. */\nexport interface ProjectCreateInput {\n name: string;\n gitRepository?: string;\n gitDefaultBranch?: string;\n storybookMeta?: unknown;\n /** Run Storybook `play` functions during capture (opt-in; default false). */\n executePlay?: boolean;\n /** Run axe accessibility checks during capture (column default true when omitted). */\n runA11y?: boolean;\n /** Run Storybook 10 `.test()` entries as interaction tests (column default false when omitted). */\n runTests?: boolean;\n /** Per-story play timeout in milliseconds (column default applies when omitted). */\n playTimeoutMs?: number;\n /** Review switch (column default true when omitted; ADR 0013, decision 1). */\n reviewEnabled?: boolean;\n /** Approvals a build needs with `testing` off (column default 1 when omitted). */\n reviewApprovals?: number;\n}\n"],"mappings":";;;;;;;;;AAcA,IAAa,eAAb,MAA0B;CACxB;CACA;;;;;CAMA,YAAY,IAAqB,QAAwB;EACvD,KAAK,KAAK;EACV,KAAK,SAAS,UAAU,EAAE,UAAU,GAAG,OAAO,SAAS;CACzD;;;;;;;CAQA,MAAM,OAAO,OAA6C;EACxD,MAAM,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY;EACnC,MAAM,OAAO,MAAM,KAAK,WAAW,MAAM,IAAI;EAC7C,OAAQ,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,UAAU;GACjD,IAAI,KAAK;GACT,MAAM,MAAM;GACZ;GACA,eAAe,MAAM;GACrB,kBAAkB,MAAM,oBAAoB;GAC5C,eAAe,MAAM,gBAAgB,KAAK,UAAU,MAAM,aAAa,IAAI;GAC3E,GAAI,MAAM,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,MAAM,YAAY;GAC5E,GAAI,MAAM,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;GAChE,GAAI,MAAM,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;GACnE,GAAI,MAAM,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,MAAM,cAAc;GAClF,GAAI,MAAM,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,MAAM,cAAc;GAClF,GAAI,MAAM,oBAAoB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB,MAAM,gBAAgB;GACxF,WAAW;GACX,WAAW;EACb,CAAC;CACH;;CAGA,MAAM,IAAI,IAAqC;EAC7C,OAAQ,MAAM,KAAK,GAAG,IAAI,KAAK,OAAO,UAAU,EAAE;CACpD;;CAGA,MAAM,UAAU,MAAuC;EAKrD,QAAO,MAJa,KAAK,GAAG,KAAK,KAAK,OAAO,UAAU;GACrD,OAAO,GAAG,IAAI,KAAK,OAAO,UAAU,MAAM,GAAG,IAAI;GACjD,OAAO;EACT,CAAC,EAAA,CACW,MAAM;CACpB;;CAGA,MAAM,OAA2B;EAC/B,OAAQ,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,QAAQ;CACjD;;CAGA,MAAM,OACJ,IACA,OAGkB;EAClB,MAAM,aAAyD,EAC7D,GAAG,MACL;EACA,IACE,MAAM,kBAAkB,KAAA,KACxB,MAAM,kBAAkB,QACxB,OAAO,MAAM,kBAAkB,UAE/B,WAAW,gBAAgB,KAAK,UAAU,MAAM,aAAa;EAE/D,OAAQ,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,UAAU,IAAI;GACrD,GAAG;GACH,4BAAW,IAAI,KAAK,EAAA,CAAE,YAAY;EACpC,CAAC;CACH;;CAGA,MAAM,OAAO,IAA2B;EACtC,MAAM,KAAK,GAAG,OAAO,KAAK,OAAO,UAAU,EAAE;CAC/C;CAEA,MAAc,WAAW,MAA+B;EACtD,MAAM,OAAO,QAAQ,IAAI,KAAK;EAC9B,MAAM,WAAY,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO,UAAU,EACzD,OAAO,GAAG,IAAI,KAAK,OAAO,UAAU,MAAM,GAAG,IAAI,EACnD,CAAC;EACD,IAAI,SAAS,WAAW,GACtB,OAAO;EAET,MAAM,QAAQ,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,IAAI,CAAC;EACjD,IAAI,SAAS;EACb,OAAO,MAAM,IAAI,GAAG,KAAK,GAAG,QAAQ,GAClC,UAAU;EAEZ,OAAO,GAAG,KAAK,GAAG;CACpB;AACF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
+
import { ShelfConfig } from "../config.mjs";
|
|
5
|
+
import { Env } from "../utils/public-origin.mjs";
|
|
6
|
+
/** Key of the stored origin in `site_settings`. */
|
|
7
|
+
declare const PUBLIC_ORIGIN_KEY = "public_origin";
|
|
8
|
+
/** Where the resolved origin came from. */
|
|
9
|
+
type PublicOriginSource = "config" | "platform" | "admin";
|
|
10
|
+
/** An origin that may be used, and its provenance. */
|
|
11
|
+
interface ResolvedPublicOrigin {
|
|
12
|
+
/** Base URL without a trailing slash. */
|
|
13
|
+
url: string;
|
|
14
|
+
source: PublicOriginSource;
|
|
15
|
+
}
|
|
16
|
+
/** The origin an admin's browser reported, as stored. */
|
|
17
|
+
interface StoredPublicOrigin {
|
|
18
|
+
origin: string;
|
|
19
|
+
confirmed: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Resolves the public origin; reads the database at most once per `ttlMs`. */
|
|
22
|
+
interface PublicOriginResolver {
|
|
23
|
+
/**
|
|
24
|
+
* The origin background code may use now, or `null` when nothing is confirmed: a configured or
|
|
25
|
+
* platform origin, or one an admin confirmed. A detected, unconfirmed origin never resolves.
|
|
26
|
+
*/
|
|
27
|
+
resolve(): Promise<ResolvedPublicOrigin | null>;
|
|
28
|
+
/** Shorthand for `resolve()` when only the URL matters. */
|
|
29
|
+
url(): Promise<string | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* The origin for an interactive authentication route (OAuth redirect URI, OIDC helper): the
|
|
32
|
+
* resolved origin, else `requestOrigin`, the address the request itself came in on. Never use
|
|
33
|
+
* it for a link that outlives the request.
|
|
34
|
+
*/
|
|
35
|
+
authOrigin(requestOrigin: string): Promise<string>;
|
|
36
|
+
/** The value the System page shows and edits; `null` when no browser reported one. */
|
|
37
|
+
stored(): Promise<StoredPublicOrigin | null>;
|
|
38
|
+
/**
|
|
39
|
+
* An admin's browser reported `origin`. First report wins: nothing is stored when a value already
|
|
40
|
+
* is, so a visit through another domain cannot replace a confirmed origin. Returns what is stored.
|
|
41
|
+
*/
|
|
42
|
+
report(origin: string, userId?: string): Promise<StoredPublicOrigin>;
|
|
43
|
+
/** An admin confirmed or entered `origin`: it replaces whatever is stored. */
|
|
44
|
+
set(origin: string, userId?: string): Promise<StoredPublicOrigin>;
|
|
45
|
+
/** An admin dropped the stored origin. */
|
|
46
|
+
clear(): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/** Inputs of {@link createPublicOriginResolver}. */
|
|
49
|
+
interface PublicOriginOptions {
|
|
50
|
+
db: DatabaseAdapter;
|
|
51
|
+
/** Only `publicBaseUrl` is read. */
|
|
52
|
+
config?: Pick<ShelfConfig, "publicBaseUrl"> | undefined;
|
|
53
|
+
/** Environment to detect the platform from; `process.env` when absent. */
|
|
54
|
+
env?: Env | undefined;
|
|
55
|
+
/** How long a database read is reused (default 10 s). */
|
|
56
|
+
ttlMs?: number | undefined;
|
|
57
|
+
}
|
|
58
|
+
/** Build the resolver for one app instance. */
|
|
59
|
+
declare function createPublicOriginResolver(options: PublicOriginOptions): PublicOriginResolver;
|
|
60
|
+
export { PUBLIC_ORIGIN_KEY, PublicOriginOptions, PublicOriginResolver, PublicOriginSource, ResolvedPublicOrigin, StoredPublicOrigin, createPublicOriginResolver };
|
|
61
|
+
//# sourceMappingURL=public-origin.d.mts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { detectPublicBaseUrl, normalizeOrigin } from "../utils/public-origin.mjs";
|
|
5
|
+
import { SiteSettingsModel } from "./site-settings.mjs";
|
|
6
|
+
// src/models/public-origin.ts
|
|
7
|
+
/** Key of the stored origin in `site_settings`. */
|
|
8
|
+
const PUBLIC_ORIGIN_KEY = "public_origin";
|
|
9
|
+
/** Build the resolver for one app instance. */
|
|
10
|
+
function createPublicOriginResolver(options) {
|
|
11
|
+
const store = createStoredOrigin(new SiteSettingsModel(options.db), options.ttlMs ?? 1e4);
|
|
12
|
+
const resolver = {
|
|
13
|
+
async resolve() {
|
|
14
|
+
const configured = configuredBase(options.config?.publicBaseUrl);
|
|
15
|
+
if (configured !== void 0) return {
|
|
16
|
+
url: configured,
|
|
17
|
+
source: "config"
|
|
18
|
+
};
|
|
19
|
+
const platform = detectPublicBaseUrl(options.env ?? process.env);
|
|
20
|
+
if (platform !== void 0) return {
|
|
21
|
+
url: platform,
|
|
22
|
+
source: "platform"
|
|
23
|
+
};
|
|
24
|
+
const stored = await store.read();
|
|
25
|
+
return stored?.confirmed === true ? {
|
|
26
|
+
url: stored.origin,
|
|
27
|
+
source: "admin"
|
|
28
|
+
} : null;
|
|
29
|
+
},
|
|
30
|
+
async url() {
|
|
31
|
+
return (await resolver.resolve())?.url;
|
|
32
|
+
},
|
|
33
|
+
async authOrigin(requestOrigin) {
|
|
34
|
+
return await resolver.url() ?? requestOrigin;
|
|
35
|
+
},
|
|
36
|
+
stored: async () => await store.read(),
|
|
37
|
+
report: async (origin, userId) => await store.report(origin, userId),
|
|
38
|
+
set: async (origin, userId) => await store.write(origin, true, userId),
|
|
39
|
+
clear: async () => {
|
|
40
|
+
await store.clear();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return resolver;
|
|
44
|
+
}
|
|
45
|
+
/** The stored origin behind a small read cache, shared by every method of one resolver. */
|
|
46
|
+
function createStoredOrigin(settings, ttlMs) {
|
|
47
|
+
let cache;
|
|
48
|
+
const remember = (value) => {
|
|
49
|
+
cache = {
|
|
50
|
+
at: Date.now(),
|
|
51
|
+
value
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
const write = async (origin, confirmed, userId) => {
|
|
55
|
+
const value = {
|
|
56
|
+
origin: requireOrigin(origin),
|
|
57
|
+
confirmed
|
|
58
|
+
};
|
|
59
|
+
await settings.set(PUBLIC_ORIGIN_KEY, JSON.stringify(value), userId);
|
|
60
|
+
remember(value);
|
|
61
|
+
return value;
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
async read() {
|
|
65
|
+
if (cache !== void 0 && Date.now() - cache.at < ttlMs) return cache.value;
|
|
66
|
+
const value = parseStored(await settings.get(PUBLIC_ORIGIN_KEY));
|
|
67
|
+
remember(value);
|
|
68
|
+
return value;
|
|
69
|
+
},
|
|
70
|
+
write,
|
|
71
|
+
async report(origin, userId) {
|
|
72
|
+
const existing = parseStored(await settings.get(PUBLIC_ORIGIN_KEY));
|
|
73
|
+
remember(existing);
|
|
74
|
+
return existing ?? await write(origin, false, userId);
|
|
75
|
+
},
|
|
76
|
+
async clear() {
|
|
77
|
+
await settings.remove(PUBLIC_ORIGIN_KEY);
|
|
78
|
+
remember(null);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** `publicBaseUrl` as a base URL: trailing slashes dropped, a path prefix kept. */
|
|
83
|
+
function configuredBase(value) {
|
|
84
|
+
const trimmed = value?.trim().replace(/\/+$/u, "");
|
|
85
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
86
|
+
}
|
|
87
|
+
/** `origin` as an origin; throws unless it is an http(s) origin with no path, query or fragment. */
|
|
88
|
+
function requireOrigin(origin) {
|
|
89
|
+
const normalized = normalizeOrigin(origin);
|
|
90
|
+
const url = normalized === void 0 ? void 0 : new URL(withScheme(origin));
|
|
91
|
+
if (normalized === void 0 || url?.pathname !== "/" || url.search || url.hash) throw new Error("The public origin must be an http(s) origin such as https://shelf.example.com");
|
|
92
|
+
return normalized;
|
|
93
|
+
}
|
|
94
|
+
function withScheme(value) {
|
|
95
|
+
const text = value.trim();
|
|
96
|
+
return /^[a-z][a-z\d+.-]*:\/\//iu.test(text) ? text : `https://${text}`;
|
|
97
|
+
}
|
|
98
|
+
function parseStored(raw) {
|
|
99
|
+
if (raw === null) return null;
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(raw);
|
|
102
|
+
const origin = normalizeOrigin(parsed.origin);
|
|
103
|
+
return origin === void 0 ? null : {
|
|
104
|
+
origin,
|
|
105
|
+
confirmed: parsed.confirmed === true
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export { PUBLIC_ORIGIN_KEY, createPublicOriginResolver };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=public-origin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-origin.mjs","names":[],"sources":["../../src/models/public-origin.ts"],"sourcesContent":["/**\n * The deployment's public origin (ADR 0007, decision 6): one resolver for anything that needs an\n * absolute URL in the background (commit-status links, email links, signed Storybook URLs).\n * It tries `config.publicBaseUrl`, then the platform's own address from the environment, then the\n * origin an admin's browser reported and an admin confirmed. A reported origin nobody confirmed is\n * only a suggestion: `resolve()` and `url()` do not return it, so no link, notification or signed\n * URL is built on it. The `Host` of a request is never used for those: a background job has none,\n * and it can be forged to plant links in emails and commit statuses.\n *\n * The one exception is authentication (OAuth redirect URIs, the OIDC helper): those routes are\n * interactive and request-bound, so {@link PublicOriginResolver.authOrigin} may answer with the\n * request's own origin when no origin is confirmed.\n */\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { ShelfConfig } from \"../config.ts\";\nimport { detectPublicBaseUrl, normalizeOrigin, type Env } from \"../utils/public-origin.ts\";\nimport { SiteSettingsModel } from \"./site-settings.ts\";\n\n/** Key of the stored origin in `site_settings`. */\nexport const PUBLIC_ORIGIN_KEY = \"public_origin\";\n\n/** Where the resolved origin came from. */\nexport type PublicOriginSource = \"config\" | \"platform\" | \"admin\";\n\n/** An origin that may be used, and its provenance. */\nexport interface ResolvedPublicOrigin {\n /** Base URL without a trailing slash. */\n url: string;\n source: PublicOriginSource;\n}\n\n/** The origin an admin's browser reported, as stored. */\nexport interface StoredPublicOrigin {\n origin: string;\n confirmed: boolean;\n}\n\n/** Resolves the public origin; reads the database at most once per `ttlMs`. */\nexport interface PublicOriginResolver {\n /**\n * The origin background code may use now, or `null` when nothing is confirmed: a configured or\n * platform origin, or one an admin confirmed. A detected, unconfirmed origin never resolves.\n */\n resolve(): Promise<ResolvedPublicOrigin | null>;\n /** Shorthand for `resolve()` when only the URL matters. */\n url(): Promise<string | undefined>;\n /**\n * The origin for an interactive authentication route (OAuth redirect URI, OIDC helper): the\n * resolved origin, else `requestOrigin`, the address the request itself came in on. Never use\n * it for a link that outlives the request.\n */\n authOrigin(requestOrigin: string): Promise<string>;\n /** The value the System page shows and edits; `null` when no browser reported one. */\n stored(): Promise<StoredPublicOrigin | null>;\n /**\n * An admin's browser reported `origin`. First report wins: nothing is stored when a value already\n * is, so a visit through another domain cannot replace a confirmed origin. Returns what is stored.\n */\n report(origin: string, userId?: string): Promise<StoredPublicOrigin>;\n /** An admin confirmed or entered `origin`: it replaces whatever is stored. */\n set(origin: string, userId?: string): Promise<StoredPublicOrigin>;\n /** An admin dropped the stored origin. */\n clear(): Promise<void>;\n}\n\n/** Inputs of {@link createPublicOriginResolver}. */\nexport interface PublicOriginOptions {\n db: DatabaseAdapter;\n /** Only `publicBaseUrl` is read. */\n config?: Pick<ShelfConfig, \"publicBaseUrl\"> | undefined;\n /** Environment to detect the platform from; `process.env` when absent. */\n env?: Env | undefined;\n /** How long a database read is reused (default 10 s). */\n ttlMs?: number | undefined;\n}\n\n/** Build the resolver for one app instance. */\nexport function createPublicOriginResolver(options: PublicOriginOptions): PublicOriginResolver {\n const store = createStoredOrigin(new SiteSettingsModel(options.db), options.ttlMs ?? 10_000);\n const resolver: PublicOriginResolver = {\n async resolve() {\n const configured = configuredBase(options.config?.publicBaseUrl);\n if (configured !== undefined) {\n return { url: configured, source: \"config\" };\n }\n const platform = detectPublicBaseUrl(options.env ?? process.env);\n if (platform !== undefined) {\n return { url: platform, source: \"platform\" };\n }\n const stored = await store.read();\n return stored?.confirmed === true ? { url: stored.origin, source: \"admin\" } : null;\n },\n async url() {\n return (await resolver.resolve())?.url;\n },\n async authOrigin(requestOrigin) {\n return (await resolver.url()) ?? requestOrigin;\n },\n stored: async () => await store.read(),\n report: async (origin, userId) => await store.report(origin, userId),\n set: async (origin, userId) => await store.write(origin, true, userId),\n clear: async () => {\n await store.clear();\n },\n };\n return resolver;\n}\n\n/** The stored origin behind a small read cache, shared by every method of one resolver. */\nfunction createStoredOrigin(\n settings: SiteSettingsModel,\n ttlMs: number,\n): Pick<PublicOriginResolver, \"report\" | \"clear\"> & {\n read(): Promise<StoredPublicOrigin | null>;\n write(origin: string, confirmed: boolean, userId?: string): Promise<StoredPublicOrigin>;\n} {\n let cache: { at: number; value: StoredPublicOrigin | null } | undefined;\n const remember = (value: StoredPublicOrigin | null): void => {\n cache = { at: Date.now(), value };\n };\n const write = async (\n origin: string,\n confirmed: boolean,\n userId?: string,\n ): Promise<StoredPublicOrigin> => {\n const value: StoredPublicOrigin = { origin: requireOrigin(origin), confirmed };\n await settings.set(PUBLIC_ORIGIN_KEY, JSON.stringify(value), userId);\n remember(value);\n return value;\n };\n return {\n async read() {\n if (cache !== undefined && Date.now() - cache.at < ttlMs) {\n return cache.value;\n }\n const value = parseStored(await settings.get(PUBLIC_ORIGIN_KEY));\n remember(value);\n return value;\n },\n write,\n async report(origin, userId) {\n const existing = parseStored(await settings.get(PUBLIC_ORIGIN_KEY));\n remember(existing);\n return existing ?? (await write(origin, false, userId));\n },\n async clear() {\n await settings.remove(PUBLIC_ORIGIN_KEY);\n remember(null);\n },\n };\n}\n\n/** `publicBaseUrl` as a base URL: trailing slashes dropped, a path prefix kept. */\nfunction configuredBase(value: string | undefined): string | undefined {\n const trimmed = value?.trim().replace(/\\/+$/u, \"\");\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/** `origin` as an origin; throws unless it is an http(s) origin with no path, query or fragment. */\nfunction requireOrigin(origin: string): string {\n const normalized = normalizeOrigin(origin);\n const url = normalized === undefined ? undefined : new URL(withScheme(origin));\n if (normalized === undefined || url?.pathname !== \"/\" || url.search || url.hash) {\n throw new Error(\n \"The public origin must be an http(s) origin such as https://shelf.example.com\",\n );\n }\n return normalized;\n}\n\nfunction withScheme(value: string): string {\n const text = value.trim();\n return /^[a-z][a-z\\d+.-]*:\\/\\//iu.test(text) ? text : `https://${text}`;\n}\n\nfunction parseStored(raw: string | null): StoredPublicOrigin | null {\n if (raw === null) {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<StoredPublicOrigin>;\n const origin = normalizeOrigin(parsed.origin);\n return origin === undefined ? null : { origin, confirmed: parsed.confirmed === true };\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;AAmBA,MAAa,oBAAoB;;AA0DjC,SAAgB,2BAA2B,SAAoD;CAC7F,MAAM,QAAQ,mBAAmB,IAAI,kBAAkB,QAAQ,EAAE,GAAG,QAAQ,SAAS,GAAM;CAC3F,MAAM,WAAiC;EACrC,MAAM,UAAU;GACd,MAAM,aAAa,eAAe,QAAQ,QAAQ,aAAa;GAC/D,IAAI,eAAe,KAAA,GACjB,OAAO;IAAE,KAAK;IAAY,QAAQ;GAAS;GAE7C,MAAM,WAAW,oBAAoB,QAAQ,OAAO,QAAQ,GAAG;GAC/D,IAAI,aAAa,KAAA,GACf,OAAO;IAAE,KAAK;IAAU,QAAQ;GAAW;GAE7C,MAAM,SAAS,MAAM,MAAM,KAAK;GAChC,OAAO,QAAQ,cAAc,OAAO;IAAE,KAAK,OAAO;IAAQ,QAAQ;GAAQ,IAAI;EAChF;EACA,MAAM,MAAM;GACV,QAAQ,MAAM,SAAS,QAAQ,EAAA,EAAI;EACrC;EACA,MAAM,WAAW,eAAe;GAC9B,OAAQ,MAAM,SAAS,IAAI,KAAM;EACnC;EACA,QAAQ,YAAY,MAAM,MAAM,KAAK;EACrC,QAAQ,OAAO,QAAQ,WAAW,MAAM,MAAM,OAAO,QAAQ,MAAM;EACnE,KAAK,OAAO,QAAQ,WAAW,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM;EACrE,OAAO,YAAY;GACjB,MAAM,MAAM,MAAM;EACpB;CACF;CACA,OAAO;AACT;;AAGA,SAAS,mBACP,UACA,OAIA;CACA,IAAI;CACJ,MAAM,YAAY,UAA2C;EAC3D,QAAQ;GAAE,IAAI,KAAK,IAAI;GAAG;EAAM;CAClC;CACA,MAAM,QAAQ,OACZ,QACA,WACA,WACgC;EAChC,MAAM,QAA4B;GAAE,QAAQ,cAAc,MAAM;GAAG;EAAU;EAC7E,MAAM,SAAS,IAAI,mBAAmB,KAAK,UAAU,KAAK,GAAG,MAAM;EACnE,SAAS,KAAK;EACd,OAAO;CACT;CACA,OAAO;EACL,MAAM,OAAO;GACX,IAAI,UAAU,KAAA,KAAa,KAAK,IAAI,IAAI,MAAM,KAAK,OACjD,OAAO,MAAM;GAEf,MAAM,QAAQ,YAAY,MAAM,SAAS,IAAI,iBAAiB,CAAC;GAC/D,SAAS,KAAK;GACd,OAAO;EACT;EACA;EACA,MAAM,OAAO,QAAQ,QAAQ;GAC3B,MAAM,WAAW,YAAY,MAAM,SAAS,IAAI,iBAAiB,CAAC;GAClE,SAAS,QAAQ;GACjB,OAAO,YAAa,MAAM,MAAM,QAAQ,OAAO,MAAM;EACvD;EACA,MAAM,QAAQ;GACZ,MAAM,SAAS,OAAO,iBAAiB;GACvC,SAAS,IAAI;EACf;CACF;AACF;;AAGA,SAAS,eAAe,OAA+C;CACrE,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC,QAAQ,SAAS,EAAE;CACjD,OAAO,YAAY,KAAK,KAAA,IAAY;AACtC;;AAGA,SAAS,cAAc,QAAwB;CAC7C,MAAM,aAAa,gBAAgB,MAAM;CACzC,MAAM,MAAM,eAAe,KAAA,IAAY,KAAA,IAAY,IAAI,IAAI,WAAW,MAAM,CAAC;CAC7E,IAAI,eAAe,KAAA,KAAa,KAAK,aAAa,OAAO,IAAI,UAAU,IAAI,MACzE,MAAM,IAAI,MACR,+EACF;CAEF,OAAO;AACT;AAEA,SAAS,WAAW,OAAuB;CACzC,MAAM,OAAO,MAAM,KAAK;CACxB,OAAO,2BAA2B,KAAK,IAAI,IAAI,OAAO,WAAW;AACnE;AAEA,SAAS,YAAY,KAA+C;CAClE,IAAI,QAAQ,MACV,OAAO;CAET,IAAI;EACF,MAAM,SAAS,KAAK,MAAM,GAAG;EAC7B,MAAM,SAAS,gBAAgB,OAAO,MAAM;EAC5C,OAAO,WAAW,KAAA,IAAY,OAAO;GAAE;GAAQ,WAAW,OAAO,cAAc;EAAK;CACtF,QAAQ;EACN,OAAO;CACT;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
+
import { Build } from "../schema/build.mjs";
|
|
5
|
+
/**
|
|
6
|
+
* Accept the project's `pending` builds that have no capture attempts and no snapshots; resolves
|
|
7
|
+
* to the builds it accepted. Builds a capture touched keep their status (snapshot approval decides
|
|
8
|
+
* them), and a second run finds nothing left to do. No approval event is raised.
|
|
9
|
+
*/
|
|
10
|
+
declare function acceptPendingWithoutWork(db: DatabaseAdapter, projectId: string): Promise<Build[]>;
|
|
11
|
+
export { acceptPendingWithoutWork };
|
|
12
|
+
//# sourceMappingURL=review-switch-off.d.mts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { CaptureAttemptModel } from "./capture-attempt.mjs";
|
|
5
|
+
import { BuildModel } from "./build.mjs";
|
|
6
|
+
import { SnapshotModel } from "./snapshot.mjs";
|
|
7
|
+
// src/models/review-switch-off.ts
|
|
8
|
+
/**
|
|
9
|
+
* Accept the project's `pending` builds that have no capture attempts and no snapshots; resolves
|
|
10
|
+
* to the builds it accepted. Builds a capture touched keep their status (snapshot approval decides
|
|
11
|
+
* them), and a second run finds nothing left to do. No approval event is raised.
|
|
12
|
+
*/
|
|
13
|
+
async function acceptPendingWithoutWork(db, projectId) {
|
|
14
|
+
const builds = new BuildModel(db);
|
|
15
|
+
const pending = await builds.list(projectId, { status: "pending" });
|
|
16
|
+
const idle = await Promise.all(pending.map(async (build) => await hasWork(db, build.id) ? null : build));
|
|
17
|
+
return await Promise.all(idle.flatMap((build) => build === null ? [] : [builds.setStatus(build.id, "approved")]));
|
|
18
|
+
}
|
|
19
|
+
async function hasWork(db, buildId) {
|
|
20
|
+
const [attempts, snapshots] = await Promise.all([new CaptureAttemptModel(db).listByBuild(buildId), new SnapshotModel(db).listByBuild(buildId)]);
|
|
21
|
+
return attempts.length > 0 || snapshots.length > 0;
|
|
22
|
+
}
|
|
23
|
+
export { acceptPendingWithoutWork };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=review-switch-off.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-switch-off.mjs","names":[],"sources":["../../src/models/review-switch-off.ts"],"sourcesContent":["/**\n * The switch-off pass (ADR 0013, decision 1): when a project turns review off, the builds it left\n * `pending` that no capture ever worked on are accepted in one pass, so the project does not keep\n * a queue nobody will clear.\n */\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { Build } from \"../schema/build.ts\";\nimport { BuildModel } from \"./build.ts\";\nimport { CaptureAttemptModel } from \"./capture-attempt.ts\";\nimport { SnapshotModel } from \"./snapshot.ts\";\n\n/**\n * Accept the project's `pending` builds that have no capture attempts and no snapshots; resolves\n * to the builds it accepted. Builds a capture touched keep their status (snapshot approval decides\n * them), and a second run finds nothing left to do. No approval event is raised.\n */\nexport async function acceptPendingWithoutWork(\n db: DatabaseAdapter,\n projectId: string,\n): Promise<Build[]> {\n const builds = new BuildModel(db);\n const pending = await builds.list(projectId, { status: \"pending\" });\n const idle = await Promise.all(\n pending.map(async (build) => ((await hasWork(db, build.id)) ? null : build)),\n );\n return await Promise.all(\n idle.flatMap((build) => (build === null ? [] : [builds.setStatus(build.id, \"approved\")])),\n );\n}\n\nasync function hasWork(db: DatabaseAdapter, buildId: string): Promise<boolean> {\n const [attempts, snapshots] = await Promise.all([\n new CaptureAttemptModel(db).listByBuild(buildId),\n new SnapshotModel(db).listByBuild(buildId),\n ]);\n return attempts.length > 0 || snapshots.length > 0;\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,eAAsB,yBACpB,IACA,WACkB;CAClB,MAAM,SAAS,IAAI,WAAW,EAAE;CAChC,MAAM,UAAU,MAAM,OAAO,KAAK,WAAW,EAAE,QAAQ,UAAU,CAAC;CAClE,MAAM,OAAO,MAAM,QAAQ,IACzB,QAAQ,IAAI,OAAO,UAAY,MAAM,QAAQ,IAAI,MAAM,EAAE,IAAK,OAAO,KAAM,CAC7E;CACA,OAAO,MAAM,QAAQ,IACnB,KAAK,SAAS,UAAW,UAAU,OAAO,CAAC,IAAI,CAAC,OAAO,UAAU,MAAM,IAAI,UAAU,CAAC,CAAE,CAC1F;AACF;AAEA,eAAe,QAAQ,IAAqB,SAAmC;CAC7E,MAAM,CAAC,UAAU,aAAa,MAAM,QAAQ,IAAI,CAC9C,IAAI,oBAAoB,EAAE,CAAC,CAAC,YAAY,OAAO,GAC/C,IAAI,cAAc,EAAE,CAAC,CAAC,YAAY,OAAO,CAC3C,CAAC;CACD,OAAO,SAAS,SAAS,KAAK,UAAU,SAAS;AACnD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
4
|
+
import { Table } from "drizzle-orm";
|
|
5
|
+
/** Tables required by {@link SiteSettingsModel}. */
|
|
6
|
+
interface SiteSettingsTables {
|
|
7
|
+
siteSettings: Table;
|
|
8
|
+
}
|
|
9
|
+
/** Data operations for `site_settings`, keyed by setting name. */
|
|
10
|
+
declare class SiteSettingsModel {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(db: DatabaseAdapter, tables?: SiteSettingsTables);
|
|
13
|
+
/** The setting's value, or `null` when it was never written. */
|
|
14
|
+
get(key: string): Promise<string | null>;
|
|
15
|
+
/** Write the setting, replacing any value; `updatedBy` names the person behind it. */
|
|
16
|
+
set(key: string, value: string, updatedBy?: string): Promise<void>;
|
|
17
|
+
/** Delete the setting; a no-op when it is absent. */
|
|
18
|
+
remove(key: string): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export { SiteSettingsModel, SiteSettingsTables };
|
|
21
|
+
//# sourceMappingURL=site-settings.d.mts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
// src/models/site-settings.ts
|
|
5
|
+
/** Data operations for `site_settings`, keyed by setting name. */
|
|
6
|
+
var SiteSettingsModel = class {
|
|
7
|
+
#db;
|
|
8
|
+
#table;
|
|
9
|
+
constructor(db, tables) {
|
|
10
|
+
this.#db = db;
|
|
11
|
+
this.#table = (tables ?? { siteSettings: db.tables.siteSettings }).siteSettings;
|
|
12
|
+
}
|
|
13
|
+
/** The setting's value, or `null` when it was never written. */
|
|
14
|
+
async get(key) {
|
|
15
|
+
return (await this.#db.get(this.#table, key))?.value ?? null;
|
|
16
|
+
}
|
|
17
|
+
/** Write the setting, replacing any value; `updatedBy` names the person behind it. */
|
|
18
|
+
async set(key, value, updatedBy) {
|
|
19
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
+
const fields = {
|
|
21
|
+
value,
|
|
22
|
+
updatedBy: updatedBy ?? null,
|
|
23
|
+
updatedAt: now
|
|
24
|
+
};
|
|
25
|
+
if (await this.#db.get(this.#table, key) !== null) {
|
|
26
|
+
await this.#db.update(this.#table, key, fields);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
await this.#db.insert(this.#table, {
|
|
31
|
+
id: key,
|
|
32
|
+
createdAt: now,
|
|
33
|
+
...fields
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (await this.#db.get(this.#table, key) === null) throw error;
|
|
37
|
+
await this.#db.update(this.#table, key, fields);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Delete the setting; a no-op when it is absent. */
|
|
41
|
+
async remove(key) {
|
|
42
|
+
await this.#db.remove(this.#table, key);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export { SiteSettingsModel };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=site-settings.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-settings.mjs","names":[],"sources":["../../src/models/site-settings.ts"],"sourcesContent":["/** Site-wide key-value settings (`site_settings`): what the app learns while running. */\nimport type { Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport type { SiteSetting } from \"../schema/site-setting.ts\";\n\n/** Tables required by {@link SiteSettingsModel}. */\nexport interface SiteSettingsTables {\n siteSettings: Table;\n}\n\n/** Data operations for `site_settings`, keyed by setting name. */\nexport class SiteSettingsModel {\n readonly #db: DatabaseAdapter;\n readonly #table: Table;\n\n constructor(db: DatabaseAdapter, tables?: SiteSettingsTables) {\n this.#db = db;\n this.#table = (tables ?? { siteSettings: db.tables.siteSettings }).siteSettings;\n }\n\n /** The setting's value, or `null` when it was never written. */\n async get(key: string): Promise<string | null> {\n const row = (await this.#db.get(this.#table, key)) as SiteSetting | null;\n return row?.value ?? null;\n }\n\n /** Write the setting, replacing any value; `updatedBy` names the person behind it. */\n async set(key: string, value: string, updatedBy?: string): Promise<void> {\n const now = new Date().toISOString();\n const fields = { value, updatedBy: updatedBy ?? null, updatedAt: now };\n if ((await this.#db.get(this.#table, key)) !== null) {\n await this.#db.update(this.#table, key, fields);\n return;\n }\n try {\n await this.#db.insert(this.#table, { id: key, createdAt: now, ...fields });\n } catch (error) {\n // Another instance wrote the key first: this write still wins, as a later one.\n if ((await this.#db.get(this.#table, key)) === null) {\n throw error;\n }\n await this.#db.update(this.#table, key, fields);\n }\n }\n\n /** Delete the setting; a no-op when it is absent. */\n async remove(key: string): Promise<void> {\n await this.#db.remove(this.#table, key);\n }\n}\n"],"mappings":";;;;;AAWA,IAAa,oBAAb,MAA+B;CAC7B;CACA;CAEA,YAAY,IAAqB,QAA6B;EAC5D,KAAK,MAAM;EACX,KAAK,UAAU,UAAU,EAAE,cAAc,GAAG,OAAO,aAAa,EAAA,CAAG;CACrE;;CAGA,MAAM,IAAI,KAAqC;EAE7C,QAAO,MADY,KAAK,IAAI,IAAI,KAAK,QAAQ,GAAG,EAAA,EACpC,SAAS;CACvB;;CAGA,MAAM,IAAI,KAAa,OAAe,WAAmC;EACvE,MAAM,uBAAM,IAAI,KAAK,EAAA,CAAE,YAAY;EACnC,MAAM,SAAS;GAAE;GAAO,WAAW,aAAa;GAAM,WAAW;EAAI;EACrE,IAAK,MAAM,KAAK,IAAI,IAAI,KAAK,QAAQ,GAAG,MAAO,MAAM;GACnD,MAAM,KAAK,IAAI,OAAO,KAAK,QAAQ,KAAK,MAAM;GAC9C;EACF;EACA,IAAI;GACF,MAAM,KAAK,IAAI,OAAO,KAAK,QAAQ;IAAE,IAAI;IAAK,WAAW;IAAK,GAAG;GAAO,CAAC;EAC3E,SAAS,OAAO;GAEd,IAAK,MAAM,KAAK,IAAI,IAAI,KAAK,QAAQ,GAAG,MAAO,MAC7C,MAAM;GAER,MAAM,KAAK,IAAI,OAAO,KAAK,QAAQ,KAAK,MAAM;EAChD;CACF;;CAGA,MAAM,OAAO,KAA4B;EACvC,MAAM,KAAK,IAAI,OAAO,KAAK,QAAQ,GAAG;CACxC;AACF"}
|
|
@@ -4,15 +4,15 @@ import { DatabaseAdapter } from "../adapter/database.mjs";
|
|
|
4
4
|
import { SnapshotStatus } from "../types.mjs";
|
|
5
5
|
import { Snapshot } from "../schema/snapshot.mjs";
|
|
6
6
|
import { Table } from "drizzle-orm";
|
|
7
|
-
//#region src/models/snapshot.d.ts
|
|
8
7
|
/** Tables required by {@link SnapshotModel}. */
|
|
9
8
|
interface SnapshotTables {
|
|
10
9
|
snapshots: Table;
|
|
11
10
|
}
|
|
12
11
|
/** Data operations for snapshot records. */
|
|
13
12
|
declare class SnapshotModel {
|
|
14
|
-
private
|
|
13
|
+
#private;
|
|
15
14
|
private readonly tables;
|
|
15
|
+
private readonly db;
|
|
16
16
|
/**
|
|
17
17
|
* @param db - Database adapter.
|
|
18
18
|
* @param tables - Table handles.
|
|
@@ -27,8 +27,30 @@ declare class SnapshotModel {
|
|
|
27
27
|
* @returns The created snapshot.
|
|
28
28
|
*/
|
|
29
29
|
create(projectId: string, buildId: string, input: SnapshotCreateInput): Promise<Snapshot>;
|
|
30
|
+
/**
|
|
31
|
+
* Delete the rendered snapshots a shard is about to write again: rows of `(story, engine)` pairs
|
|
32
|
+
* in `work`, so a rerun starts from a clean slate instead of colliding with rows an earlier,
|
|
33
|
+
* interrupted run left behind. Inherited rows are kept: the plan wrote them, for engines or
|
|
34
|
+
* viewports this shard does not render.
|
|
35
|
+
*/
|
|
36
|
+
removeRendered(buildId: string, work: readonly {
|
|
37
|
+
browser: string;
|
|
38
|
+
storyIds: ReadonlySet<string>;
|
|
39
|
+
}[]): Promise<number>;
|
|
40
|
+
/** Delete every snapshot of a build: a new plan of it starts clean. */
|
|
41
|
+
removeForBuild(buildId: string): Promise<number>;
|
|
42
|
+
/**
|
|
43
|
+
* Milliseconds each story cost on one build, summed over its viewports and engines. Stories the
|
|
44
|
+
* renderer did not time are left out, so an empty map means this build carries no timings.
|
|
45
|
+
*/
|
|
46
|
+
durationsByStory(buildId: string): Promise<Map<string, number>>;
|
|
30
47
|
/** List all snapshots belonging to a build. */
|
|
31
48
|
listByBuild(buildId: string): Promise<Snapshot[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Every snapshot of a story file across the project's builds. Index paths are
|
|
51
|
+
* stored raw (`./src/A.stories.tsx`), so both spellings of `importPath` match.
|
|
52
|
+
*/
|
|
53
|
+
listByImportPath(projectId: string, importPath: string): Promise<Snapshot[]>;
|
|
32
54
|
/** Fetch a snapshot by id, or null if not found. */
|
|
33
55
|
get(id: string): Promise<Snapshot | null>;
|
|
34
56
|
/** Update mutable fields of a snapshot. */
|
|
@@ -44,15 +66,29 @@ interface SnapshotCreateInput {
|
|
|
44
66
|
storyName: string;
|
|
45
67
|
storyTitle: string;
|
|
46
68
|
storyImportPath?: string;
|
|
69
|
+
/** Figma URL declared by the story (`parameters.design` / `storyshelf.figma`). */
|
|
70
|
+
designUrl?: string | null;
|
|
47
71
|
viewportName: string;
|
|
48
72
|
viewportWidth: number;
|
|
49
73
|
viewportHeight: number;
|
|
50
74
|
screenshotPath: string;
|
|
51
75
|
infraHash?: string | null;
|
|
76
|
+
/** JSON `EnvironmentChange` when accepted as an environment migration. */
|
|
77
|
+
envChange?: string | null;
|
|
52
78
|
inherited?: boolean;
|
|
79
|
+
sourceBuildId?: string | null;
|
|
80
|
+
comparisonImagePath?: string | null;
|
|
81
|
+
comparisonMetadata?: string | null;
|
|
53
82
|
baselineId?: string | null;
|
|
54
83
|
baselineVersion?: string | null;
|
|
84
|
+
/** Resolved mode definition as JSON (display/capture only). */
|
|
85
|
+
mode?: string | null;
|
|
86
|
+
/** Engine the screenshot was captured with (default chromium). */
|
|
87
|
+
browser?: string;
|
|
88
|
+
/** Milliseconds the renderer spent on this capture, when it reported any. */
|
|
89
|
+
durationMs?: number | null;
|
|
90
|
+
/** JSON array of axe violation texts found on this capture; null when none. */
|
|
91
|
+
a11yViolations?: string | null;
|
|
55
92
|
}
|
|
56
|
-
//#endregion
|
|
57
93
|
export { SnapshotCreateInput, SnapshotModel, SnapshotTables };
|
|
58
94
|
//# sourceMappingURL=snapshot.d.mts.map
|