@storyshelf/core 0.6.1 → 0.7.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 -2
- package/dist/adapter/capture-runner.d.mts +127 -10
- package/dist/adapter/capture-runner.mjs +5 -12
- package/dist/adapter/database.d.mts +27 -8
- package/dist/adapter/database.mjs.map +1 -1
- package/dist/adapter/design.d.mts +85 -0
- package/dist/adapter/design.mjs +28 -0
- package/dist/adapter/design.mjs.map +1 -0
- package/dist/adapter/metadata.d.mts +3 -10
- package/dist/adapter/notifier.d.mts +6 -3
- package/dist/adapter/notifier.mjs +5 -1
- package/dist/adapter/oauth.d.mts +52 -0
- package/dist/adapter/setup.d.mts +4 -5
- package/dist/adapter/setup.mjs +2 -1
- package/dist/adapter/setup.mjs.map +1 -1
- package/dist/adapter/webhook-events.mjs +1 -1
- package/dist/adapters/capture-target-offers.d.mts +28 -0
- package/dist/adapters/capture-target-offers.mjs +58 -0
- package/dist/adapters/capture-target-offers.mjs.map +1 -0
- package/dist/adapters/capture-target.d.mts +71 -0
- package/dist/adapters/capture-target.mjs +76 -0
- package/dist/adapters/capture-target.mjs.map +1 -0
- package/dist/adapters/notifier/build-comment.d.mts +24 -0
- package/dist/adapters/notifier/build-comment.mjs +24 -0
- package/dist/adapters/notifier/build-comment.mjs.map +1 -0
- package/dist/adapters/notifier/build-state.d.mts +99 -0
- package/dist/adapters/notifier/build-state.mjs +218 -0
- package/dist/adapters/notifier/build-state.mjs.map +1 -0
- package/dist/adapters/notifier/events.d.mts +4 -2
- package/dist/adapters/notifier/events.mjs +31 -18
- package/dist/adapters/notifier/events.mjs.map +1 -1
- package/dist/adapters/notifier/provider.d.mts +53 -7
- package/dist/adapters/notifier/provider.mjs +12 -0
- package/dist/adapters/notifier/provider.mjs.map +1 -0
- package/dist/adapters/notifier/state.d.mts +24 -0
- package/dist/adapters/notifier/state.mjs +66 -0
- package/dist/adapters/notifier/state.mjs.map +1 -0
- package/dist/adapters/notifier/types.d.mts +51 -2
- package/dist/adapters/remote-browser.d.mts +87 -0
- package/dist/adapters/remote-browser.mjs +103 -0
- package/dist/adapters/remote-browser.mjs.map +1 -0
- package/dist/adapters/render-runs.d.mts +25 -0
- package/dist/adapters/render-runs.mjs +41 -0
- package/dist/adapters/render-runs.mjs.map +1 -0
- package/dist/adapters/setup-runner.mjs +2 -4
- package/dist/adapters/setup-runner.mjs.map +1 -1
- package/dist/adapters/sources.d.mts +12 -0
- package/dist/adapters/sources.mjs +20 -0
- package/dist/adapters/sources.mjs.map +1 -0
- package/dist/adapters/validate.mjs +25 -18
- package/dist/adapters/validate.mjs.map +1 -1
- package/dist/ai.d.mts +105 -0
- package/dist/ai.mjs +19 -0
- package/dist/ai.mjs.map +1 -0
- package/dist/auth.d.mts +8 -1
- package/dist/auth.mjs +14 -1
- package/dist/auth.mjs.map +1 -0
- package/dist/capture/a11y/axe-source.d.mts +18 -0
- package/dist/capture/a11y/axe-source.mjs +37 -0
- package/dist/capture/a11y/axe-source.mjs.map +1 -0
- package/dist/capture/a11y/in-page.d.mts +27 -0
- package/dist/capture/a11y/in-page.mjs +60 -0
- package/dist/capture/a11y/in-page.mjs.map +1 -0
- package/dist/capture/a11y/map.d.mts +24 -0
- package/dist/capture/a11y/map.mjs +48 -0
- package/dist/capture/a11y/map.mjs.map +1 -0
- package/dist/capture/a11y/options.d.mts +23 -0
- package/dist/capture/a11y/options.mjs +75 -0
- package/dist/capture/a11y/options.mjs.map +1 -0
- package/dist/capture/adapter.d.mts +41 -3
- package/dist/capture/adapter.mjs.map +1 -1
- package/dist/capture/affected.d.mts +2 -0
- package/dist/capture/affected.mjs +13 -4
- package/dist/capture/affected.mjs.map +1 -1
- package/dist/capture/attempt-logger.mjs +84 -0
- package/dist/capture/attempt-logger.mjs.map +1 -0
- package/dist/capture/browsers.d.mts +35 -0
- package/dist/capture/browsers.mjs +67 -0
- package/dist/capture/browsers.mjs.map +1 -0
- package/dist/capture/build-state/deliver.d.mts +32 -0
- package/dist/capture/build-state/deliver.mjs +118 -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 +56 -0
- package/dist/capture/build-state/notify-job.mjs +133 -0
- package/dist/capture/build-state/notify-job.mjs.map +1 -0
- package/dist/capture/build-state/publisher.d.mts +23 -0
- package/dist/capture/build-state/publisher.mjs +107 -0
- package/dist/capture/build-state/publisher.mjs.map +1 -0
- package/dist/capture/build-state/resume.d.mts +9 -0
- package/dist/capture/build-state/resume.mjs +47 -0
- package/dist/capture/build-state/resume.mjs.map +1 -0
- package/dist/capture/build-state/types.d.mts +49 -0
- package/dist/capture/catalog/catalogue.d.mts +22 -0
- package/dist/capture/catalog/catalogue.mjs +53 -0
- package/dist/capture/catalog/catalogue.mjs.map +1 -0
- package/dist/capture/catalog/components.d.mts +23 -0
- package/dist/capture/catalog/components.mjs +55 -0
- package/dist/capture/catalog/components.mjs.map +1 -0
- package/dist/capture/catalog/history.d.mts +30 -0
- package/dist/capture/catalog/history.mjs +51 -0
- package/dist/capture/catalog/history.mjs.map +1 -0
- package/dist/capture/catalog/hook.d.mts +14 -0
- package/dist/capture/catalog/hook.mjs +19 -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 +26 -0
- package/dist/capture/catalog/load.mjs +49 -0
- package/dist/capture/catalog/load.mjs.map +1 -0
- package/dist/capture/catalog/parse.d.mts +15 -0
- package/dist/capture/catalog/parse.mjs +56 -0
- package/dist/capture/catalog/parse.mjs.map +1 -0
- package/dist/capture/catalog/read.d.mts +12 -0
- package/dist/capture/catalog/read.mjs +33 -0
- package/dist/capture/catalog/read.mjs.map +1 -0
- package/dist/capture/catalog/types.d.mts +33 -0
- package/dist/capture/consumer/capture-handler.d.mts +58 -0
- package/dist/capture/consumer/capture-handler.mjs +118 -0
- package/dist/capture/consumer/capture-handler.mjs.map +1 -0
- package/dist/capture/consumer/idle.d.mts +17 -0
- package/dist/capture/consumer/idle.mjs +25 -0
- package/dist/capture/consumer/idle.mjs.map +1 -0
- package/dist/capture/consumer/index.d.mts +13 -0
- package/dist/capture/consumer/index.mjs +139 -0
- package/dist/capture/consumer/index.mjs.map +1 -0
- package/dist/capture/consumer/loop.mjs +110 -0
- package/dist/capture/consumer/loop.mjs.map +1 -0
- package/dist/capture/consumer/metrics.d.mts +41 -0
- package/dist/capture/consumer/metrics.mjs +38 -0
- package/dist/capture/consumer/metrics.mjs.map +1 -0
- package/dist/capture/consumer/retry.d.mts +33 -0
- package/dist/capture/consumer/retry.mjs +34 -0
- package/dist/capture/consumer/retry.mjs.map +1 -0
- package/dist/capture/consumer/run-job.mjs +195 -0
- package/dist/capture/consumer/run-job.mjs.map +1 -0
- package/dist/capture/consumer/startup.mjs +38 -0
- package/dist/capture/consumer/startup.mjs.map +1 -0
- package/dist/capture/consumer/types.d.mts +97 -0
- package/dist/capture/crash-failure.d.mts +25 -0
- package/dist/capture/crash-failure.mjs +70 -0
- package/dist/capture/crash-failure.mjs.map +1 -0
- package/dist/capture/db-queue/cadence.d.mts +32 -0
- package/dist/capture/db-queue/cadence.mjs +38 -0
- package/dist/capture/db-queue/cadence.mjs.map +1 -0
- package/dist/capture/db-queue/claim.d.mts +9 -0
- package/dist/capture/db-queue/claim.mjs +132 -0
- package/dist/capture/db-queue/claim.mjs.map +1 -0
- package/dist/capture/db-queue/clock.mjs +12 -0
- package/dist/capture/db-queue/clock.mjs.map +1 -0
- package/dist/capture/db-queue/codec.mjs +76 -0
- package/dist/capture/db-queue/codec.mjs.map +1 -0
- package/dist/capture/db-queue/index.d.mts +20 -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 +36 -0
- package/dist/capture/db-queue/keeper.mjs +92 -0
- package/dist/capture/db-queue/keeper.mjs.map +1 -0
- package/dist/capture/db-queue/lease.mjs +46 -0
- package/dist/capture/db-queue/lease.mjs.map +1 -0
- package/dist/capture/db-queue/lifecycle.mjs +36 -0
- package/dist/capture/db-queue/lifecycle.mjs.map +1 -0
- package/dist/capture/db-queue/operations.mjs +94 -0
- package/dist/capture/db-queue/operations.mjs.map +1 -0
- package/dist/capture/db-queue/poll-loop.d.mts +30 -0
- package/dist/capture/db-queue/poll-loop.mjs +89 -0
- package/dist/capture/db-queue/poll-loop.mjs.map +1 -0
- package/dist/capture/db-queue/poll.d.mts +10 -0
- package/dist/capture/db-queue/poll.mjs +69 -0
- package/dist/capture/db-queue/poll.mjs.map +1 -0
- package/dist/capture/db-queue/timers.d.mts +12 -0
- package/dist/capture/db-queue/timers.mjs +37 -0
- package/dist/capture/db-queue/timers.mjs.map +1 -0
- package/dist/capture/db-queue/types.d.mts +83 -0
- package/dist/capture/db-queue/types.mjs +12 -0
- package/dist/capture/db-queue/types.mjs.map +1 -0
- package/dist/capture/db-queue/wake.mjs +48 -0
- package/dist/capture/db-queue/wake.mjs.map +1 -0
- package/dist/capture/design.mjs +39 -0
- package/dist/capture/design.mjs.map +1 -0
- package/dist/capture/diff-record.mjs +23 -3
- package/dist/capture/diff-record.mjs.map +1 -1
- package/dist/capture/dispatch.d.mts +12 -7
- package/dist/capture/dispatch.mjs +86 -107
- package/dist/capture/dispatch.mjs.map +1 -1
- package/dist/capture/enrich.mjs +60 -0
- package/dist/capture/enrich.mjs.map +1 -0
- package/dist/capture/failure-sets.mjs +22 -0
- package/dist/capture/failure-sets.mjs.map +1 -0
- package/dist/capture/fingerprint.d.mts +42 -0
- package/dist/capture/fingerprint.mjs +83 -0
- package/dist/capture/fingerprint.mjs.map +1 -0
- package/dist/capture/forked/channel.d.mts +25 -0
- package/dist/capture/forked/child.d.mts +34 -0
- package/dist/capture/forked/child.mjs +202 -0
- package/dist/capture/forked/child.mjs.map +1 -0
- package/dist/capture/forked/crash-tracker.mjs +23 -0
- package/dist/capture/forked/crash-tracker.mjs.map +1 -0
- package/dist/capture/forked/decision.d.mts +26 -0
- package/dist/capture/forked/decision.mjs +27 -0
- package/dist/capture/forked/decision.mjs.map +1 -0
- package/dist/capture/forked/exit.mjs +12 -0
- package/dist/capture/forked/exit.mjs.map +1 -0
- package/dist/capture/forked/fork.d.mts +31 -0
- package/dist/capture/forked/fork.mjs +93 -0
- package/dist/capture/forked/fork.mjs.map +1 -0
- package/dist/capture/forked/forked-capture.d.mts +40 -0
- package/dist/capture/forked/forked-capture.mjs +240 -0
- package/dist/capture/forked/forked-capture.mjs.map +1 -0
- package/dist/capture/forked/lease-book.mjs +46 -0
- package/dist/capture/forked/lease-book.mjs.map +1 -0
- package/dist/capture/forked/protocol.d.mts +38 -0
- package/dist/capture/forked/protocol.mjs +25 -0
- package/dist/capture/forked/protocol.mjs.map +1 -0
- package/dist/capture/forked/runs.mjs +75 -0
- package/dist/capture/forked/runs.mjs.map +1 -0
- package/dist/capture/isolate.mjs +141 -0
- package/dist/capture/isolate.mjs.map +1 -0
- package/dist/capture/job-lease.d.mts +28 -0
- package/dist/capture/job-lease.mjs +57 -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 +25 -0
- package/dist/capture/modes.mjs +107 -0
- package/dist/capture/modes.mjs.map +1 -0
- package/dist/capture/orchestrator.d.mts +37 -5
- package/dist/capture/orchestrator.mjs +118 -107
- package/dist/capture/orchestrator.mjs.map +1 -1
- package/dist/capture/pipeline.d.mts +9 -2
- package/dist/capture/pipeline.mjs +250 -45
- package/dist/capture/pipeline.mjs.map +1 -1
- package/dist/capture/progress.d.mts +11 -0
- package/dist/capture/progress.mjs +28 -0
- package/dist/capture/progress.mjs.map +1 -0
- package/dist/capture/publish/accept.d.mts +39 -0
- package/dist/capture/publish/accept.mjs +28 -0
- package/dist/capture/publish/accept.mjs.map +1 -0
- package/dist/capture/publish/complete.d.mts +46 -0
- package/dist/capture/publish/complete.mjs +64 -0
- package/dist/capture/publish/complete.mjs.map +1 -0
- package/dist/capture/publish/extract.d.mts +20 -0
- package/dist/capture/publish/extract.mjs +119 -0
- package/dist/capture/publish/extract.mjs.map +1 -0
- package/dist/capture/publish/handler.d.mts +28 -0
- package/dist/capture/publish/handler.mjs +62 -0
- package/dist/capture/publish/handler.mjs.map +1 -0
- package/dist/capture/publish/index.d.mts +10 -0
- package/dist/capture/publish/limits.d.mts +37 -0
- package/dist/capture/publish/limits.mjs +39 -0
- package/dist/capture/publish/limits.mjs.map +1 -0
- package/dist/capture/publish/published.d.mts +15 -0
- package/dist/capture/publish/published.mjs +18 -0
- package/dist/capture/publish/published.mjs.map +1 -0
- package/dist/capture/publish/run.d.mts +33 -0
- package/dist/capture/publish/run.mjs +30 -0
- package/dist/capture/publish/run.mjs.map +1 -0
- package/dist/capture/rediff.d.mts +1 -1
- package/dist/capture/rediff.mjs +4 -3
- package/dist/capture/rediff.mjs.map +1 -1
- package/dist/capture/render.mjs +53 -0
- package/dist/capture/render.mjs.map +1 -0
- package/dist/capture/scratch.d.mts +44 -0
- package/dist/capture/scratch.mjs +138 -0
- package/dist/capture/scratch.mjs.map +1 -0
- package/dist/capture/shard-plan.mjs +128 -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 +174 -0
- package/dist/capture/shards/execute.mjs.map +1 -0
- package/dist/capture/shards/fan-out.mjs +126 -0
- package/dist/capture/shards/fan-out.mjs.map +1 -0
- package/dist/capture/shards/history.mjs +35 -0
- package/dist/capture/shards/history.mjs.map +1 -0
- package/dist/capture/shards/reduce.mjs +97 -0
- package/dist/capture/shards/reduce.mjs.map +1 -0
- package/dist/capture/sizing.mjs +1 -11
- package/dist/capture/sizing.mjs.map +1 -1
- package/dist/capture/skip-checks.mjs +2 -65
- package/dist/capture/skip-checks.mjs.map +1 -1
- package/dist/capture/statics.d.mts +7 -8
- package/dist/capture/statics.mjs +25 -71
- package/dist/capture/statics.mjs.map +1 -1
- package/dist/capture/storybook-urls.d.mts +40 -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 -4
- package/dist/capture/storybook.mjs +56 -16
- package/dist/capture/storybook.mjs.map +1 -1
- package/dist/capture/target.mjs +21 -0
- package/dist/capture/target.mjs.map +1 -0
- package/dist/capture/targets.d.mts +25 -0
- package/dist/capture/targets.mjs +32 -0
- package/dist/capture/targets.mjs.map +1 -0
- package/dist/capture/tests.d.mts +37 -0
- package/dist/capture/tests.mjs +126 -0
- package/dist/capture/tests.mjs.map +1 -0
- package/dist/capture/token-chunks.mjs +74 -0
- package/dist/capture/token-chunks.mjs.map +1 -0
- package/dist/capture.d.mts +60 -7
- package/dist/capture.mjs +48 -3
- package/dist/config.d.mts +121 -12
- package/dist/config.mjs +9 -6
- package/dist/config.mjs.map +1 -1
- package/dist/diff.d.mts +9 -3
- package/dist/diff.mjs +16 -3
- package/dist/diff.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/insights/budget.d.mts +20 -0
- package/dist/insights/budget.mjs +33 -0
- package/dist/insights/budget.mjs.map +1 -0
- package/dist/insights/envelope.d.mts +59 -0
- package/dist/insights/envelope.mjs +60 -0
- package/dist/insights/envelope.mjs.map +1 -0
- package/dist/insights/evidence-health.d.mts +32 -0
- package/dist/insights/evidence-health.mjs +28 -0
- package/dist/insights/evidence-health.mjs.map +1 -0
- package/dist/insights/evidence.d.mts +55 -0
- package/dist/insights/evidence.mjs +64 -0
- package/dist/insights/evidence.mjs.map +1 -0
- package/dist/insights/hash.d.mts +18 -0
- package/dist/insights/hash.mjs +21 -0
- package/dist/insights/hash.mjs.map +1 -0
- package/dist/insights/limits.d.mts +24 -0
- package/dist/insights/limits.mjs +24 -0
- package/dist/insights/limits.mjs.map +1 -0
- package/dist/insights/prompts/v1.d.mts +13 -0
- package/dist/insights/prompts/v1.mjs +34 -0
- package/dist/insights/prompts/v1.mjs.map +1 -0
- package/dist/insights/redact.d.mts +9 -0
- package/dist/insights/redact.mjs +24 -0
- package/dist/insights/redact.mjs.map +1 -0
- package/dist/insights/text.mjs +44 -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.mjs +17 -1
- package/dist/logger.mjs.map +1 -1
- package/dist/models/ai-budget-alert.d.mts +23 -0
- package/dist/models/ai-budget-alert.mjs +38 -0
- package/dist/models/ai-budget-alert.mjs.map +1 -0
- package/dist/models/ai-usage.d.mts +40 -0
- package/dist/models/ai-usage.mjs +61 -0
- package/dist/models/ai-usage.mjs.map +1 -0
- package/dist/models/baseline-archive.d.mts +84 -0
- package/dist/models/baseline-archive.mjs +106 -0
- package/dist/models/baseline-archive.mjs.map +1 -0
- package/dist/models/baseline-export.d.mts +19 -0
- package/dist/models/baseline-export.mjs +136 -0
- package/dist/models/baseline-export.mjs.map +1 -0
- package/dist/models/baseline-import.mjs +118 -0
- package/dist/models/baseline-import.mjs.map +1 -0
- package/dist/models/baseline-transfer.d.mts +49 -0
- package/dist/models/baseline-transfer.mjs +121 -0
- package/dist/models/baseline-transfer.mjs.map +1 -0
- package/dist/models/baseline.d.mts +32 -5
- package/dist/models/baseline.mjs +65 -20
- package/dist/models/baseline.mjs.map +1 -1
- package/dist/models/build-component.d.mts +28 -0
- package/dist/models/build-component.mjs +55 -0
- package/dist/models/build-component.mjs.map +1 -0
- package/dist/models/build-review-status.d.mts +29 -0
- package/dist/models/build-review-status.mjs +37 -0
- package/dist/models/build-review-status.mjs.map +1 -0
- package/dist/models/build-review.d.mts +28 -0
- package/dist/models/build-review.mjs +54 -0
- package/dist/models/build-review.mjs.map +1 -0
- package/dist/models/build.d.mts +25 -3
- package/dist/models/build.mjs +50 -11
- package/dist/models/build.mjs.map +1 -1
- package/dist/models/capture-attempt.d.mts +7 -1
- package/dist/models/capture-attempt.mjs +29 -4
- package/dist/models/capture-attempt.mjs.map +1 -1
- package/dist/models/capture-job.d.mts +106 -0
- package/dist/models/capture-job.mjs +288 -0
- package/dist/models/capture-job.mjs.map +1 -0
- package/dist/models/capture-log.d.mts +1 -1
- package/dist/models/capture-log.mjs +4 -3
- package/dist/models/capture-log.mjs.map +1 -1
- package/dist/models/capture-shard.d.mts +62 -0
- package/dist/models/capture-shard.mjs +190 -0
- package/dist/models/capture-shard.mjs.map +1 -0
- package/dist/models/changeset.d.mts +48 -0
- package/dist/models/changeset.mjs +81 -0
- package/dist/models/changeset.mjs.map +1 -0
- package/dist/models/columns.mjs +19 -0
- package/dist/models/columns.mjs.map +1 -0
- package/dist/models/comment.d.mts +4 -1
- package/dist/models/comment.mjs +7 -4
- package/dist/models/comment.mjs.map +1 -1
- package/dist/models/component.d.mts +43 -0
- package/dist/models/component.mjs +60 -0
- package/dist/models/component.mjs.map +1 -0
- package/dist/models/connections.d.mts +41 -0
- package/dist/models/connections.mjs +112 -0
- package/dist/models/connections.mjs.map +1 -0
- package/dist/models/content-ref.d.mts +1 -1
- package/dist/models/content-ref.mjs +1 -1
- package/dist/models/content-ref.mjs.map +1 -1
- package/dist/models/credentials.mjs +12 -2
- package/dist/models/credentials.mjs.map +1 -1
- package/dist/models/design-credentials.d.mts +41 -0
- package/dist/models/design-credentials.mjs +86 -0
- package/dist/models/design-credentials.mjs.map +1 -0
- package/dist/models/design-health.d.mts +16 -0
- package/dist/models/design-health.mjs +25 -0
- package/dist/models/design-health.mjs.map +1 -0
- package/dist/models/design-nodes.d.mts +83 -0
- package/dist/models/design-nodes.mjs +222 -0
- package/dist/models/design-nodes.mjs.map +1 -0
- package/dist/models/design-renders.mjs +74 -0
- package/dist/models/design-renders.mjs.map +1 -0
- package/dist/models/design-resolve.d.mts +29 -0
- package/dist/models/design-resolve.mjs +41 -0
- package/dist/models/design-resolve.mjs.map +1 -0
- package/dist/models/design.d.mts +39 -0
- package/dist/models/design.mjs +90 -0
- package/dist/models/design.mjs.map +1 -0
- package/dist/models/inherited-ratio.d.mts +21 -0
- package/dist/models/inherited-ratio.mjs +22 -0
- package/dist/models/inherited-ratio.mjs.map +1 -0
- package/dist/models/insight.d.mts +70 -0
- package/dist/models/insight.mjs +162 -0
- package/dist/models/insight.mjs.map +1 -0
- package/dist/models/label.d.mts +4 -2
- package/dist/models/label.mjs +25 -10
- package/dist/models/label.mjs.map +1 -1
- package/dist/models/member.d.mts +1 -1
- package/dist/models/member.mjs +5 -4
- package/dist/models/member.mjs.map +1 -1
- package/dist/models/notification-channel.d.mts +37 -3
- package/dist/models/notification-channel.mjs +88 -9
- package/dist/models/notification-channel.mjs.map +1 -1
- package/dist/models/notification-subscription.d.mts +1 -2
- package/dist/models/notification-subscription.mjs +7 -9
- package/dist/models/notification-subscription.mjs.map +1 -1
- package/dist/models/project-group-mapping.d.mts +6 -1
- package/dist/models/project-group-mapping.mjs +14 -4
- package/dist/models/project-group-mapping.mjs.map +1 -1
- package/dist/models/project.d.mts +9 -1
- package/dist/models/project.mjs +9 -4
- package/dist/models/project.mjs.map +1 -1
- package/dist/models/public-origin.d.mts +63 -0
- package/dist/models/public-origin.mjs +114 -0
- package/dist/models/public-origin.mjs.map +1 -0
- package/dist/models/review-switch-off.d.mts +14 -0
- package/dist/models/review-switch-off.mjs +26 -0
- package/dist/models/review-switch-off.mjs.map +1 -0
- package/dist/models/site-settings.d.mts +23 -0
- package/dist/models/site-settings.mjs +48 -0
- package/dist/models/site-settings.mjs.map +1 -0
- package/dist/models/snapshot.d.mts +36 -1
- package/dist/models/snapshot.mjs +50 -3
- package/dist/models/snapshot.mjs.map +1 -1
- package/dist/models/token.d.mts +13 -1
- package/dist/models/token.mjs +23 -5
- package/dist/models/token.mjs.map +1 -1
- package/dist/models/usage.d.mts +76 -0
- package/dist/models/usage.mjs +149 -0
- package/dist/models/usage.mjs.map +1 -0
- package/dist/models/user.d.mts +1 -1
- package/dist/models/user.mjs +4 -3
- package/dist/models/user.mjs.map +1 -1
- package/dist/models/webhook.d.mts +15 -1
- package/dist/models/webhook.mjs +33 -4
- package/dist/models/webhook.mjs.map +1 -1
- package/dist/models.d.mts +26 -3
- package/dist/models.mjs +27 -5
- package/dist/options.d.mts +18 -0
- package/dist/options.mjs +90 -0
- package/dist/options.mjs.map +1 -0
- package/dist/paths.d.mts +19 -4
- package/dist/paths.mjs +51 -10
- package/dist/paths.mjs.map +1 -1
- package/dist/retention/ai.d.mts +18 -0
- package/dist/retention/ai.mjs +23 -0
- package/dist/retention/ai.mjs.map +1 -0
- package/dist/retention/pending.mjs +47 -0
- package/dist/retention/pending.mjs.map +1 -0
- package/dist/retention/screenshot-sweep.d.mts +51 -0
- package/dist/retention/screenshot-sweep.mjs +128 -0
- package/dist/retention/screenshot-sweep.mjs.map +1 -0
- package/dist/retention.d.mts +16 -2
- package/dist/retention.mjs +71 -14
- package/dist/retention.mjs.map +1 -1
- package/dist/schema/baseline.d.mts +6 -0
- package/dist/schema/build-component.d.mts +25 -0
- package/dist/schema/build-review.d.mts +17 -0
- package/dist/schema/build.d.mts +7 -0
- package/dist/schema/capture-job.d.mts +60 -0
- package/dist/schema/capture-shard.d.mts +35 -0
- package/dist/schema/comment.d.mts +2 -0
- package/dist/schema/connection.d.mts +24 -0
- package/dist/schema/design.d.mts +58 -0
- package/dist/schema/insight.d.mts +54 -0
- package/dist/schema/notification.d.mts +4 -0
- package/dist/schema/project.d.mts +21 -0
- package/dist/schema/site-setting.d.mts +21 -0
- package/dist/schema/snapshot.d.mts +12 -0
- package/dist/schema/usage.d.mts +30 -0
- package/dist/schema.d.mts +11 -3
- package/dist/serverless.d.mts +21 -0
- package/dist/serverless.mjs +37 -0
- package/dist/serverless.mjs.map +1 -0
- package/dist/test-helpers/create-project.d.mts +1 -1
- package/dist/test-helpers/deferred.d.mts +39 -0
- package/dist/test-helpers/deferred.mjs +61 -0
- package/dist/test-helpers/deferred.mjs.map +1 -0
- package/dist/test-helpers/design-contract.d.mts +21 -0
- package/dist/test-helpers/design-contract.mjs +40 -0
- package/dist/test-helpers/design-contract.mjs.map +1 -0
- package/dist/test-helpers/fake-database.mjs +14 -2
- package/dist/test-helpers/fake-database.mjs.map +1 -1
- package/dist/test-helpers/fake-design.d.mts +43 -0
- package/dist/test-helpers/fake-design.mjs +114 -0
- package/dist/test-helpers/fake-design.mjs.map +1 -0
- package/dist/test-helpers/fake-notifier.d.mts +21 -0
- package/dist/test-helpers/fake-notifier.mjs +44 -0
- package/dist/test-helpers/fake-notifier.mjs.map +1 -0
- package/dist/test-helpers/fake-tables.mjs +255 -67
- package/dist/test-helpers/fake-tables.mjs.map +1 -1
- package/dist/test-helpers/manual-clock.d.mts +27 -0
- package/dist/test-helpers/manual-clock.mjs +56 -0
- package/dist/test-helpers/manual-clock.mjs.map +1 -0
- package/dist/test-helpers/notifier-contract.d.mts +7 -1
- package/dist/test-helpers/notifier-contract.mjs +32 -3
- package/dist/test-helpers/notifier-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-contract.d.mts +16 -2
- package/dist/test-helpers/queue-contract.mjs +195 -1
- package/dist/test-helpers/queue-contract.mjs.map +1 -1
- package/dist/test-helpers/queue-multi-instance.d.mts +20 -0
- package/dist/test-helpers/queue-multi-instance.mjs +206 -0
- package/dist/test-helpers/queue-multi-instance.mjs.map +1 -0
- package/dist/test-helpers/runner-contract.mjs +11 -0
- package/dist/test-helpers/runner-contract.mjs.map +1 -1
- package/dist/test-helpers/sql-chunks.mjs +23 -0
- package/dist/test-helpers/sql-chunks.mjs.map +1 -1
- package/dist/test-helpers/storage-contract.mjs +1 -1
- package/dist/test-helpers.d.mts +9 -4
- package/dist/test-helpers.mjs +8 -3
- package/dist/types.d.mts +14 -3
- package/dist/types.mjs +21 -4
- package/dist/types.mjs.map +1 -1
- package/dist/urls.d.mts +4 -0
- package/dist/urls.mjs +11 -2
- package/dist/urls.mjs.map +1 -1
- package/dist/utils/adaptive-concurrency.d.mts +66 -0
- package/dist/utils/adaptive-concurrency.mjs +149 -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 +43 -0
- package/dist/utils/connect-retry.mjs.map +1 -0
- package/dist/utils/environment.d.mts +19 -0
- package/dist/utils/environment.mjs +59 -0
- package/dist/utils/environment.mjs.map +1 -0
- package/dist/utils/http.d.mts +17 -1
- package/dist/utils/http.mjs +22 -3
- package/dist/utils/http.mjs.map +1 -1
- package/dist/utils/map-adaptive.d.mts +15 -0
- package/dist/utils/map-adaptive.mjs +72 -0
- package/dist/utils/map-adaptive.mjs.map +1 -0
- package/dist/utils/map-limit.d.mts +10 -0
- package/dist/utils/map-limit.mjs +32 -0
- package/dist/utils/map-limit.mjs.map +1 -0
- package/dist/utils/page-limiter.d.mts +37 -0
- package/dist/utils/page-limiter.mjs +56 -0
- package/dist/utils/page-limiter.mjs.map +1 -0
- package/dist/utils/public-origin.d.mts +20 -0
- package/dist/utils/public-origin.mjs +75 -0
- package/dist/utils/public-origin.mjs.map +1 -0
- package/dist/utils/redact.mjs +3 -0
- package/dist/utils/redact.mjs.map +1 -1
- package/dist/utils/remote-environment.d.mts +39 -0
- package/dist/utils/remote-environment.mjs +114 -0
- package/dist/utils/remote-environment.mjs.map +1 -0
- package/dist/utils/resources.d.mts +64 -0
- package/dist/utils/resources.mjs +122 -0
- package/dist/utils/resources.mjs.map +1 -0
- package/dist/utils/screenshot-store.d.mts +15 -0
- package/dist/utils/screenshot-store.mjs +41 -0
- package/dist/utils/screenshot-store.mjs.map +1 -0
- package/dist/utils/session-gate.d.mts +22 -0
- package/dist/utils/session-gate.mjs +53 -0
- package/dist/utils/session-gate.mjs.map +1 -0
- package/dist/utils/storybook-token.d.mts +81 -0
- package/dist/utils/storybook-token.mjs +134 -0
- package/dist/utils/storybook-token.mjs.map +1 -0
- package/dist/utils/storybook-url.d.mts +15 -0
- package/dist/utils/storybook-url.mjs +21 -0
- package/dist/utils/storybook-url.mjs.map +1 -0
- package/dist/utils/timing.mjs +1 -1
- package/dist/utils/timing.mjs.map +1 -1
- package/dist/utils/zip-read.mjs +129 -0
- package/dist/utils/zip-read.mjs.map +1 -0
- package/dist/utils/zip-write.d.mts +18 -0
- package/dist/utils/zip-write.mjs +188 -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 +32 -20
- 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,15 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { AdaptiveConcurrency } from "./adaptive-concurrency.mjs";
|
|
4
|
+
//#region src/utils/map-adaptive.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Like `mapLimit`, but the limit is read live from `controller` and every finished item is fed
|
|
7
|
+
* back to it. `fn` reports a timeout it handled itself with `timedOut: true`.
|
|
8
|
+
*/
|
|
9
|
+
declare function mapAdaptive<T, R>(items: readonly T[], controller: AdaptiveConcurrency, fn: (item: T, index: number) => Promise<{
|
|
10
|
+
value: R;
|
|
11
|
+
timedOut?: boolean;
|
|
12
|
+
}>): Promise<R[]>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { mapAdaptive };
|
|
15
|
+
//# sourceMappingURL=map-adaptive.d.mts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
//#region src/utils/map-adaptive.ts
|
|
5
|
+
/**
|
|
6
|
+
* Like `mapLimit`, but the limit is read live from `controller` and every finished item is fed
|
|
7
|
+
* back to it. `fn` reports a timeout it handled itself with `timedOut: true`.
|
|
8
|
+
*/
|
|
9
|
+
async function mapAdaptive(items, controller, fn) {
|
|
10
|
+
return await new AdaptiveRun(items, controller, fn).run();
|
|
11
|
+
}
|
|
12
|
+
var AdaptiveRun = class {
|
|
13
|
+
results;
|
|
14
|
+
next = 0;
|
|
15
|
+
active = 0;
|
|
16
|
+
failure = null;
|
|
17
|
+
finish = null;
|
|
18
|
+
items;
|
|
19
|
+
controller;
|
|
20
|
+
fn;
|
|
21
|
+
constructor(items, controller, fn) {
|
|
22
|
+
this.items = items;
|
|
23
|
+
this.controller = controller;
|
|
24
|
+
this.fn = fn;
|
|
25
|
+
this.results = Array.from({ length: items.length });
|
|
26
|
+
}
|
|
27
|
+
async run() {
|
|
28
|
+
return await new Promise((resolve, reject) => {
|
|
29
|
+
this.finish = {
|
|
30
|
+
resolve,
|
|
31
|
+
reject
|
|
32
|
+
};
|
|
33
|
+
this.pump();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
pump() {
|
|
37
|
+
while (this.canLaunch()) {
|
|
38
|
+
this.launch(this.next);
|
|
39
|
+
this.next += 1;
|
|
40
|
+
}
|
|
41
|
+
if (this.active === 0 && (this.failure || this.next >= this.items.length)) {
|
|
42
|
+
if (this.failure) this.finish?.reject(this.failure.error);
|
|
43
|
+
else this.finish?.resolve(this.results);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
canLaunch() {
|
|
47
|
+
return !this.failure && this.active < this.controller.limit && this.next < this.items.length;
|
|
48
|
+
}
|
|
49
|
+
launch(index) {
|
|
50
|
+
this.active += 1;
|
|
51
|
+
const started = performance.now();
|
|
52
|
+
this.fn(this.items[index], index).then((outcome) => {
|
|
53
|
+
this.results[index] = outcome.value;
|
|
54
|
+
this.controller.observe({
|
|
55
|
+
durationMs: performance.now() - started,
|
|
56
|
+
timedOut: outcome.timedOut
|
|
57
|
+
});
|
|
58
|
+
this.settle();
|
|
59
|
+
}, (error) => {
|
|
60
|
+
this.failure ??= { error: error instanceof Error ? error : new Error(String(error)) };
|
|
61
|
+
this.settle();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
settle() {
|
|
65
|
+
this.active -= 1;
|
|
66
|
+
this.pump();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
export { mapAdaptive };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=map-adaptive.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-adaptive.mjs","names":[],"sources":["../../src/utils/map-adaptive.ts"],"sourcesContent":["/** `mapLimit` with a live, self-adjusting limit. */\nimport type { AdaptiveConcurrency } from \"./adaptive-concurrency.ts\";\n\n/**\n * Like `mapLimit`, but the limit is read live from `controller` and every finished item is fed\n * back to it. `fn` reports a timeout it handled itself with `timedOut: true`.\n */\nexport async function mapAdaptive<T, R>(\n items: readonly T[],\n controller: AdaptiveConcurrency,\n fn: (item: T, index: number) => Promise<{ value: R; timedOut?: boolean }>,\n): Promise<R[]> {\n return await new AdaptiveRun(items, controller, fn).run();\n}\n\nclass AdaptiveRun<T, R> {\n private readonly results: R[];\n private next = 0;\n private active = 0;\n private failure: { error: Error } | null = null;\n private finish: { resolve: (value: R[]) => void; reject: (error: Error) => void } | null = null;\n\n private readonly items: readonly T[];\n private readonly controller: AdaptiveConcurrency;\n private readonly fn: (item: T, index: number) => Promise<{ value: R; timedOut?: boolean }>;\n\n constructor(\n items: readonly T[],\n controller: AdaptiveConcurrency,\n fn: (item: T, index: number) => Promise<{ value: R; timedOut?: boolean }>,\n ) {\n this.items = items;\n this.controller = controller;\n this.fn = fn;\n this.results = Array.from<R>({ length: items.length });\n }\n\n async run(): Promise<R[]> {\n return await new Promise<R[]>((resolve, reject) => {\n this.finish = { resolve, reject };\n this.pump();\n });\n }\n\n private pump(): void {\n while (this.canLaunch()) {\n this.launch(this.next);\n this.next += 1;\n }\n if (this.active === 0 && (this.failure || this.next >= this.items.length)) {\n if (this.failure) {\n this.finish?.reject(this.failure.error);\n } else {\n this.finish?.resolve(this.results);\n }\n }\n }\n\n private canLaunch(): boolean {\n return !this.failure && this.active < this.controller.limit && this.next < this.items.length;\n }\n\n private launch(index: number): void {\n this.active += 1;\n const started = performance.now();\n this.fn(this.items[index] as T, index).then(\n (outcome) => {\n this.results[index] = outcome.value;\n this.controller.observe({\n durationMs: performance.now() - started,\n timedOut: outcome.timedOut,\n });\n this.settle();\n },\n (error: unknown) => {\n this.failure ??= { error: error instanceof Error ? error : new Error(String(error)) };\n this.settle();\n },\n );\n }\n\n private settle(): void {\n this.active -= 1;\n this.pump();\n }\n}\n"],"mappings":";;;;;;;;AAOA,eAAsB,YACpB,OACA,YACA,IACc;CACd,OAAO,MAAM,IAAI,YAAY,OAAO,YAAY,EAAE,CAAC,CAAC,IAAI;AAC1D;AAEA,IAAM,cAAN,MAAwB;CACtB;CACA,OAAe;CACf,SAAiB;CACjB,UAA2C;CAC3C,SAA2F;CAE3F;CACA;CACA;CAEA,YACE,OACA,YACA,IACA;EACA,KAAK,QAAQ;EACb,KAAK,aAAa;EAClB,KAAK,KAAK;EACV,KAAK,UAAU,MAAM,KAAQ,EAAE,QAAQ,MAAM,OAAO,CAAC;CACvD;CAEA,MAAM,MAAoB;EACxB,OAAO,MAAM,IAAI,SAAc,SAAS,WAAW;GACjD,KAAK,SAAS;IAAE;IAAS;GAAO;GAChC,KAAK,KAAK;EACZ,CAAC;CACH;CAEA,OAAqB;EACnB,OAAO,KAAK,UAAU,GAAG;GACvB,KAAK,OAAO,KAAK,IAAI;GACrB,KAAK,QAAQ;EACf;EACA,IAAI,KAAK,WAAW,MAAM,KAAK,WAAW,KAAK,QAAQ,KAAK,MAAM,SAAS;GACzE,IAAI,KAAK,SACP,KAAK,QAAQ,OAAO,KAAK,QAAQ,KAAK;QAEtC,KAAK,QAAQ,QAAQ,KAAK,OAAO;EAErC;CACF;CAEA,YAA6B;EAC3B,OAAO,CAAC,KAAK,WAAW,KAAK,SAAS,KAAK,WAAW,SAAS,KAAK,OAAO,KAAK,MAAM;CACxF;CAEA,OAAe,OAAqB;EAClC,KAAK,UAAU;EACf,MAAM,UAAU,YAAY,IAAI;EAChC,KAAK,GAAG,KAAK,MAAM,QAAa,KAAK,CAAC,CAAC,MACpC,YAAY;GACX,KAAK,QAAQ,SAAS,QAAQ;GAC9B,KAAK,WAAW,QAAQ;IACtB,YAAY,YAAY,IAAI,IAAI;IAChC,UAAU,QAAQ;GACpB,CAAC;GACD,KAAK,OAAO;EACd,IACC,UAAmB;GAClB,KAAK,YAAY,EAAE,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,EAAE;GACpF,KAAK,OAAO;EACd,CACF;CACF;CAEA,SAAuB;EACrB,KAAK,UAAU;EACf,KAAK,KAAK;CACZ;AACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
//#region src/utils/map-limit.d.ts
|
|
4
|
+
/** Split `items` into consecutive batches of at most `size` (a non-positive size means one batch). */
|
|
5
|
+
declare function chunk<T>(items: readonly T[], size: number): T[][];
|
|
6
|
+
/** Run `fn` over `items` with at most `limit` in flight; results keep input order. */
|
|
7
|
+
declare function mapLimit<T, R>(items: readonly T[], limit: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { chunk, mapLimit };
|
|
10
|
+
//# sourceMappingURL=map-limit.d.mts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
//#region src/utils/map-limit.ts
|
|
5
|
+
/** Split `items` into consecutive batches of at most `size` (a non-positive size means one batch). */
|
|
6
|
+
function chunk(items, size) {
|
|
7
|
+
const step = size > 0 ? Math.max(1, Math.floor(size)) : items.length || 1;
|
|
8
|
+
const batches = [];
|
|
9
|
+
for (let start = 0; start < items.length; start += step) batches.push(items.slice(start, start + step));
|
|
10
|
+
return batches;
|
|
11
|
+
}
|
|
12
|
+
/** Run `fn` over `items` with at most `limit` in flight; results keep input order. */
|
|
13
|
+
async function mapLimit(items, limit, fn) {
|
|
14
|
+
const results = Array.from({ length: items.length });
|
|
15
|
+
let next = 0;
|
|
16
|
+
const worker = async () => {
|
|
17
|
+
while (next < items.length) {
|
|
18
|
+
const index = next;
|
|
19
|
+
next += 1;
|
|
20
|
+
results[index] = await fn(items[index], index);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const workers = Math.max(1, Math.min(Math.floor(limit) || 1, items.length));
|
|
24
|
+
await Promise.all(Array.from({ length: workers }, async () => {
|
|
25
|
+
await worker();
|
|
26
|
+
}));
|
|
27
|
+
return results;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { chunk, mapLimit };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=map-limit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-limit.mjs","names":[],"sources":["../../src/utils/map-limit.ts"],"sourcesContent":["/** Split `items` into consecutive batches of at most `size` (a non-positive size means one batch). */\nexport function chunk<T>(items: readonly T[], size: number): T[][] {\n const step = size > 0 ? Math.max(1, Math.floor(size)) : items.length || 1;\n const batches: T[][] = [];\n for (let start = 0; start < items.length; start += step) {\n batches.push(items.slice(start, start + step));\n }\n return batches;\n}\n\n/** Run `fn` over `items` with at most `limit` in flight; results keep input order. */\nexport async function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n const results = Array.from<R>({ length: items.length });\n let next = 0;\n const worker = async (): Promise<void> => {\n while (next < items.length) {\n const index = next;\n next += 1;\n // oxlint-disable-next-line eslint/no-await-in-loop -- bounded worker pulls sequentially\n results[index] = await fn(items[index] as T, index);\n }\n };\n const workers = Math.max(1, Math.min(Math.floor(limit) || 1, items.length));\n await Promise.all(\n Array.from({ length: workers }, async () => {\n await worker();\n }),\n );\n return results;\n}\n"],"mappings":";;;;;AACA,SAAgB,MAAS,OAAqB,MAAqB;CACjE,MAAM,OAAO,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,CAAC,IAAI,MAAM,UAAU;CACxE,MAAM,UAAiB,CAAC;CACxB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,MACjD,QAAQ,KAAK,MAAM,MAAM,OAAO,QAAQ,IAAI,CAAC;CAE/C,OAAO;AACT;;AAGA,eAAsB,SACpB,OACA,OACA,IACc;CACd,MAAM,UAAU,MAAM,KAAQ,EAAE,QAAQ,MAAM,OAAO,CAAC;CACtD,IAAI,OAAO;CACX,MAAM,SAAS,YAA2B;EACxC,OAAO,OAAO,MAAM,QAAQ;GAC1B,MAAM,QAAQ;GACd,QAAQ;GAER,QAAQ,SAAS,MAAM,GAAG,MAAM,QAAa,KAAK;EACpD;CACF;CACA,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,GAAG,MAAM,MAAM,CAAC;CAC1E,MAAM,QAAQ,IACZ,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,YAAY;EAC1C,MAAM,OAAO;CACf,CAAC,CACH;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { Logger } from "../logger.mjs";
|
|
4
|
+
import { SessionGate } from "./session-gate.mjs";
|
|
5
|
+
//#region src/utils/page-limiter.d.ts
|
|
6
|
+
/** Options for {@link createPageLimiter}. */
|
|
7
|
+
interface PageLimiterOptions {
|
|
8
|
+
/** Explicit page count (config or run input). Fixed: the adaptive controller stays off. */
|
|
9
|
+
concurrency?: number;
|
|
10
|
+
/**
|
|
11
|
+
* A remote target's session cap, shared by every render of that target in the process. It
|
|
12
|
+
* replaces CPU and memory sizing: the plan's parallel-session limit is the budget, not this host.
|
|
13
|
+
* An explicit `concurrency` can lower a run's share of it, never raise it.
|
|
14
|
+
*/
|
|
15
|
+
gate?: SessionGate;
|
|
16
|
+
/** Engine being rendered; heavier engines get a smaller budget. */
|
|
17
|
+
browser?: string;
|
|
18
|
+
logger?: Logger;
|
|
19
|
+
}
|
|
20
|
+
/** Runs capture jobs under a page limit. One limiter spans a whole run so what it learns carries across batches. */
|
|
21
|
+
interface PageLimiter {
|
|
22
|
+
/**
|
|
23
|
+
* Run `fn` over `items`. `fn` resolves to whether the capture timed out (it handles its own
|
|
24
|
+
* failures, so the limiter cannot see them otherwise).
|
|
25
|
+
*/
|
|
26
|
+
each<T>(items: readonly T[], fn: (item: T) => Promise<boolean>): Promise<void>;
|
|
27
|
+
/** Release the event-loop monitor. */
|
|
28
|
+
dispose(): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The session gate's size for a remote target; a fixed limit when `concurrency` is given; otherwise start at the CPU/memory/engine-sized
|
|
32
|
+
* recommendation and let latency, event-loop lag and timeouts move it up to the adaptive ceiling.
|
|
33
|
+
*/
|
|
34
|
+
declare function createPageLimiter(options: PageLimiterOptions): PageLimiter;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { PageLimiter, PageLimiterOptions, createPageLimiter };
|
|
37
|
+
//# sourceMappingURL=page-limiter.d.mts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { mapLimit } from "./map-limit.mjs";
|
|
5
|
+
import { detectResources, maxPageConcurrency, recommendedPageConcurrency } from "./resources.mjs";
|
|
6
|
+
import { AdaptiveConcurrency } from "./adaptive-concurrency.mjs";
|
|
7
|
+
import { mapAdaptive } from "./map-adaptive.mjs";
|
|
8
|
+
//#region src/utils/page-limiter.ts
|
|
9
|
+
/**
|
|
10
|
+
* The session gate's size for a remote target; a fixed limit when `concurrency` is given; otherwise start at the CPU/memory/engine-sized
|
|
11
|
+
* recommendation and let latency, event-loop lag and timeouts move it up to the adaptive ceiling.
|
|
12
|
+
*/
|
|
13
|
+
function createPageLimiter(options) {
|
|
14
|
+
const { gate } = options;
|
|
15
|
+
if (gate !== void 0) return {
|
|
16
|
+
each: async (items, fn) => {
|
|
17
|
+
await mapLimit(items, Math.min(gate.size, options.concurrency ?? gate.size), async (item) => {
|
|
18
|
+
await gate.run(async () => await fn(item));
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
dispose: noop
|
|
22
|
+
};
|
|
23
|
+
if (options.concurrency !== void 0) {
|
|
24
|
+
const limit = options.concurrency;
|
|
25
|
+
return {
|
|
26
|
+
each: async (items, fn) => {
|
|
27
|
+
await mapLimit(items, limit, async (item) => {
|
|
28
|
+
await fn(item);
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
dispose: noop
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const resources = detectResources();
|
|
35
|
+
const controller = new AdaptiveConcurrency({
|
|
36
|
+
initial: recommendedPageConcurrency(resources, options.browser),
|
|
37
|
+
max: maxPageConcurrency(resources, options.browser),
|
|
38
|
+
logger: options.logger
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
each: async (items, fn) => {
|
|
42
|
+
await mapAdaptive(items, controller, async (item) => ({
|
|
43
|
+
value: void 0,
|
|
44
|
+
timedOut: await fn(item)
|
|
45
|
+
}));
|
|
46
|
+
},
|
|
47
|
+
dispose: () => {
|
|
48
|
+
controller.dispose();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function noop() {}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { createPageLimiter };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=page-limiter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-limiter.mjs","names":[],"sources":["../../src/utils/page-limiter.ts"],"sourcesContent":["/** How many pages a capture run renders at once: fixed when configured, adaptive otherwise. */\nimport type { Logger } from \"../logger.ts\";\nimport { AdaptiveConcurrency } from \"./adaptive-concurrency.ts\";\nimport { mapAdaptive } from \"./map-adaptive.ts\";\nimport { mapLimit } from \"./map-limit.ts\";\nimport { detectResources, maxPageConcurrency, recommendedPageConcurrency } from \"./resources.ts\";\nimport type { SessionGate } from \"./session-gate.ts\";\n\n/** Options for {@link createPageLimiter}. */\nexport interface PageLimiterOptions {\n /** Explicit page count (config or run input). Fixed: the adaptive controller stays off. */\n concurrency?: number;\n /**\n * A remote target's session cap, shared by every render of that target in the process. It\n * replaces CPU and memory sizing: the plan's parallel-session limit is the budget, not this host.\n * An explicit `concurrency` can lower a run's share of it, never raise it.\n */\n gate?: SessionGate;\n /** Engine being rendered; heavier engines get a smaller budget. */\n browser?: string;\n logger?: Logger;\n}\n\n/** Runs capture jobs under a page limit. One limiter spans a whole run so what it learns carries across batches. */\nexport interface PageLimiter {\n /**\n * Run `fn` over `items`. `fn` resolves to whether the capture timed out (it handles its own\n * failures, so the limiter cannot see them otherwise).\n */\n each<T>(items: readonly T[], fn: (item: T) => Promise<boolean>): Promise<void>;\n /** Release the event-loop monitor. */\n dispose(): void;\n}\n\n/**\n * The session gate's size for a remote target; a fixed limit when `concurrency` is given; otherwise start at the CPU/memory/engine-sized\n * recommendation and let latency, event-loop lag and timeouts move it up to the adaptive ceiling.\n */\nexport function createPageLimiter(options: PageLimiterOptions): PageLimiter {\n const { gate } = options;\n if (gate !== undefined) {\n return {\n each: async (items, fn) => {\n await mapLimit(\n items,\n Math.min(gate.size, options.concurrency ?? gate.size),\n async (item) => {\n await gate.run(async () => await fn(item));\n },\n );\n },\n dispose: noop,\n };\n }\n if (options.concurrency !== undefined) {\n const limit = options.concurrency;\n return {\n each: async (items, fn) => {\n await mapLimit(items, limit, async (item) => {\n await fn(item);\n });\n },\n dispose: noop,\n };\n }\n const resources = detectResources();\n const controller = new AdaptiveConcurrency({\n initial: recommendedPageConcurrency(resources, options.browser),\n max: maxPageConcurrency(resources, options.browser),\n logger: options.logger,\n });\n return {\n each: async (items, fn) => {\n await mapAdaptive(items, controller, async (item) => ({\n value: undefined,\n timedOut: await fn(item),\n }));\n },\n dispose: () => {\n controller.dispose();\n },\n };\n}\n\nfunction noop(): void {}\n"],"mappings":";;;;;;;;;;;;AAsCA,SAAgB,kBAAkB,SAA0C;CAC1E,MAAM,EAAE,SAAS;CACjB,IAAI,SAAS,KAAA,GACX,OAAO;EACL,MAAM,OAAO,OAAO,OAAO;GACzB,MAAM,SACJ,OACA,KAAK,IAAI,KAAK,MAAM,QAAQ,eAAe,KAAK,IAAI,GACpD,OAAO,SAAS;IACd,MAAM,KAAK,IAAI,YAAY,MAAM,GAAG,IAAI,CAAC;GAC3C,CACF;EACF;EACA,SAAS;CACX;CAEF,IAAI,QAAQ,gBAAgB,KAAA,GAAW;EACrC,MAAM,QAAQ,QAAQ;EACtB,OAAO;GACL,MAAM,OAAO,OAAO,OAAO;IACzB,MAAM,SAAS,OAAO,OAAO,OAAO,SAAS;KAC3C,MAAM,GAAG,IAAI;IACf,CAAC;GACH;GACA,SAAS;EACX;CACF;CACA,MAAM,YAAY,gBAAgB;CAClC,MAAM,aAAa,IAAI,oBAAoB;EACzC,SAAS,2BAA2B,WAAW,QAAQ,OAAO;EAC9D,KAAK,mBAAmB,WAAW,QAAQ,OAAO;EAClD,QAAQ,QAAQ;CAClB,CAAC;CACD,OAAO;EACL,MAAM,OAAO,OAAO,OAAO;GACzB,MAAM,YAAY,OAAO,YAAY,OAAO,UAAU;IACpD,OAAO,KAAA;IACP,UAAU,MAAM,GAAG,IAAI;GACzB,EAAE;EACJ;EACA,eAAe;GACb,WAAW,QAAQ;EACrB;CACF;AACF;AAEA,SAAS,OAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
//#region src/utils/public-origin.d.ts
|
|
4
|
+
/** Finding the address a deployment is reached at without being told (ADR 0007, decision 6). */
|
|
5
|
+
/** Environment variables, as `process.env` has them. */
|
|
6
|
+
type Env = Readonly<Record<string, string | undefined>>;
|
|
7
|
+
/**
|
|
8
|
+
* The origin (`scheme://host[:port]`) of `value`, or `undefined` when it is not an http(s) URL
|
|
9
|
+
* without credentials. A bare host (`app.example.com`), as platforms often publish, reads as https.
|
|
10
|
+
*/
|
|
11
|
+
declare function normalizeOrigin(value?: string): string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* The address the hosting platform publishes in `env`, as an origin, or `undefined` when none is
|
|
14
|
+
* set. It is the platform's own domain, a working fallback but the wrong link behind a custom
|
|
15
|
+
* domain. Cloud Run, AWS App Runner, Lambda function URLs and Cloudflare Workers publish nothing.
|
|
16
|
+
*/
|
|
17
|
+
declare function detectPublicBaseUrl(env: Env): string | undefined;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { Env, detectPublicBaseUrl, normalizeOrigin };
|
|
20
|
+
//# sourceMappingURL=public-origin.d.mts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
//#region src/utils/public-origin.ts
|
|
5
|
+
/**
|
|
6
|
+
* The origin (`scheme://host[:port]`) of `value`, or `undefined` when it is not an http(s) URL
|
|
7
|
+
* without credentials. A bare host (`app.example.com`), as platforms often publish, reads as https.
|
|
8
|
+
*/
|
|
9
|
+
function normalizeOrigin(value) {
|
|
10
|
+
const text = value?.trim();
|
|
11
|
+
if (!text) return;
|
|
12
|
+
if (/^[a-z][a-z\d+.-]*:(?!\/\/|\d+(?:\/|$))/iu.test(text)) return;
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(/^[a-z][a-z\d+.-]*:\/\//iu.test(text) ? text : `https://${text}`);
|
|
15
|
+
return (url.protocol === "https:" || url.protocol === "http:") && url.username === "" && url.password === "" && url.hostname !== "" ? url.origin : void 0;
|
|
16
|
+
} catch {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const PLATFORMS = [
|
|
21
|
+
{ address: ["HEROKU_APP_DEFAULT_DOMAIN_NAME"] },
|
|
22
|
+
{ address: ["RAILWAY_PUBLIC_DOMAIN"] },
|
|
23
|
+
{
|
|
24
|
+
marker: ["VERCEL", "1"],
|
|
25
|
+
address: ["VERCEL_PROJECT_PRODUCTION_URL", "VERCEL_URL"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
marker: ["NETLIFY", "true"],
|
|
29
|
+
address: ["URL", "DEPLOY_PRIME_URL"]
|
|
30
|
+
},
|
|
31
|
+
{ address: ["RENDER_EXTERNAL_URL", "RENDER_EXTERNAL_HOSTNAME"] },
|
|
32
|
+
{ address: ["WEBSITE_HOSTNAME"] },
|
|
33
|
+
{
|
|
34
|
+
marker: ["DIGITALOCEAN_APP_ID"],
|
|
35
|
+
address: ["APP_URL"]
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* The address the hosting platform publishes in `env`, as an origin, or `undefined` when none is
|
|
40
|
+
* set. It is the platform's own domain, a working fallback but the wrong link behind a custom
|
|
41
|
+
* domain. Cloud Run, AWS App Runner, Lambda function URLs and Cloudflare Workers publish nothing.
|
|
42
|
+
*/
|
|
43
|
+
function detectPublicBaseUrl(env) {
|
|
44
|
+
for (const platform of PLATFORMS) {
|
|
45
|
+
const found = fromPlatform(platform, env);
|
|
46
|
+
if (found !== void 0) return found;
|
|
47
|
+
}
|
|
48
|
+
return fromFly(env) ?? fromContainerApps(env);
|
|
49
|
+
}
|
|
50
|
+
function fromPlatform(platform, env) {
|
|
51
|
+
if (platform.marker !== void 0) {
|
|
52
|
+
const [name, expected] = platform.marker;
|
|
53
|
+
const actual = env[name];
|
|
54
|
+
if (actual === void 0 || actual === "" || expected !== void 0 && actual !== expected) return;
|
|
55
|
+
}
|
|
56
|
+
for (const name of platform.address) {
|
|
57
|
+
const origin = normalizeOrigin(env[name]);
|
|
58
|
+
if (origin !== void 0) return origin;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Fly.io: `<app>.fly.dev`. */
|
|
62
|
+
function fromFly(env) {
|
|
63
|
+
const app = env["FLY_APP_NAME"];
|
|
64
|
+
return app ? normalizeOrigin(`${app}.fly.dev`) : void 0;
|
|
65
|
+
}
|
|
66
|
+
/** Azure Container Apps: `<app>.<environment DNS suffix>`. */
|
|
67
|
+
function fromContainerApps(env) {
|
|
68
|
+
const app = env["CONTAINER_APP_NAME"];
|
|
69
|
+
const suffix = env["CONTAINER_APP_ENV_DNS_SUFFIX"];
|
|
70
|
+
return app && suffix ? normalizeOrigin(`${app}.${suffix}`) : void 0;
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { detectPublicBaseUrl, normalizeOrigin };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=public-origin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-origin.mjs","names":[],"sources":["../../src/utils/public-origin.ts"],"sourcesContent":["/** Finding the address a deployment is reached at without being told (ADR 0007, decision 6). */\n\n/** Environment variables, as `process.env` has them. */\nexport type Env = Readonly<Record<string, string | undefined>>;\n\n/**\n * The origin (`scheme://host[:port]`) of `value`, or `undefined` when it is not an http(s) URL\n * without credentials. A bare host (`app.example.com`), as platforms often publish, reads as https.\n */\nexport function normalizeOrigin(value?: string): string | undefined {\n const text = value?.trim();\n if (!text) {\n return undefined;\n }\n // `javascript:alert(1)`, `mailto:x`: a scheme with no `//` is no address (`host:8443` is).\n if (/^[a-z][a-z\\d+.-]*:(?!\\/\\/|\\d+(?:\\/|$))/iu.test(text)) {\n return undefined;\n }\n try {\n const url = new URL(/^[a-z][a-z\\d+.-]*:\\/\\//iu.test(text) ? text : `https://${text}`);\n const web = url.protocol === \"https:\" || url.protocol === \"http:\";\n return web && url.username === \"\" && url.password === \"\" && url.hostname !== \"\"\n ? url.origin\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** One platform: the variables that say its address, tried in order. */\ninterface Platform {\n /** Variable whose presence says the app runs there; absent when the address variable alone says so. */\n marker?: readonly [string, string?];\n /** Variables holding a host or URL, first set one wins. */\n address: readonly string[];\n}\n\nconst PLATFORMS: readonly Platform[] = [\n // Heroku: needs the `runtime-dyno-metadata` Labs feature.\n { address: [\"HEROKU_APP_DEFAULT_DOMAIN_NAME\"] },\n // Railway: only when the service has a public domain.\n { address: [\"RAILWAY_PUBLIC_DOMAIN\"] },\n // Vercel: the production alias beats the per-deployment URL.\n { marker: [\"VERCEL\", \"1\"], address: [\"VERCEL_PROJECT_PRODUCTION_URL\", \"VERCEL_URL\"] },\n // Netlify: `URL` is the site's main URL (a generic name, so it needs the platform marker).\n { marker: [\"NETLIFY\", \"true\"], address: [\"URL\", \"DEPLOY_PRIME_URL\"] },\n // Render.\n { address: [\"RENDER_EXTERNAL_URL\", \"RENDER_EXTERNAL_HOSTNAME\"] },\n // Azure App Service.\n { address: [\"WEBSITE_HOSTNAME\"] },\n // DigitalOcean App Platform: `APP_URL` is a bindable variable the app spec must set.\n { marker: [\"DIGITALOCEAN_APP_ID\"], address: [\"APP_URL\"] },\n];\n\n/**\n * The address the hosting platform publishes in `env`, as an origin, or `undefined` when none is\n * set. It is the platform's own domain, a working fallback but the wrong link behind a custom\n * domain. Cloud Run, AWS App Runner, Lambda function URLs and Cloudflare Workers publish nothing.\n */\nexport function detectPublicBaseUrl(env: Env): string | undefined {\n for (const platform of PLATFORMS) {\n const found = fromPlatform(platform, env);\n if (found !== undefined) {\n return found;\n }\n }\n return fromFly(env) ?? fromContainerApps(env);\n}\n\nfunction fromPlatform(platform: Platform, env: Env): string | undefined {\n if (platform.marker !== undefined) {\n const [name, expected] = platform.marker;\n const actual = env[name];\n if (actual === undefined || actual === \"\" || (expected !== undefined && actual !== expected)) {\n return undefined;\n }\n }\n for (const name of platform.address) {\n const origin = normalizeOrigin(env[name]);\n if (origin !== undefined) {\n return origin;\n }\n }\n return undefined;\n}\n\n/** Fly.io: `<app>.fly.dev`. */\nfunction fromFly(env: Env): string | undefined {\n const app = env[\"FLY_APP_NAME\"];\n return app ? normalizeOrigin(`${app}.fly.dev`) : undefined;\n}\n\n/** Azure Container Apps: `<app>.<environment DNS suffix>`. */\nfunction fromContainerApps(env: Env): string | undefined {\n const app = env[\"CONTAINER_APP_NAME\"];\n const suffix = env[\"CONTAINER_APP_ENV_DNS_SUFFIX\"];\n return app && suffix ? normalizeOrigin(`${app}.${suffix}`) : undefined;\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,gBAAgB,OAAoC;CAClE,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,MACH;CAGF,IAAI,2CAA2C,KAAK,IAAI,GACtD;CAEF,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,2BAA2B,KAAK,IAAI,IAAI,OAAO,WAAW,MAAM;EAEpF,QADY,IAAI,aAAa,YAAY,IAAI,aAAa,YAC5C,IAAI,aAAa,MAAM,IAAI,aAAa,MAAM,IAAI,aAAa,KACzE,IAAI,SACJ,KAAA;CACN,QAAQ;EACN;CACF;AACF;AAUA,MAAM,YAAiC;CAErC,EAAE,SAAS,CAAC,gCAAgC,EAAE;CAE9C,EAAE,SAAS,CAAC,uBAAuB,EAAE;CAErC;EAAE,QAAQ,CAAC,UAAU,GAAG;EAAG,SAAS,CAAC,iCAAiC,YAAY;CAAE;CAEpF;EAAE,QAAQ,CAAC,WAAW,MAAM;EAAG,SAAS,CAAC,OAAO,kBAAkB;CAAE;CAEpE,EAAE,SAAS,CAAC,uBAAuB,0BAA0B,EAAE;CAE/D,EAAE,SAAS,CAAC,kBAAkB,EAAE;CAEhC;EAAE,QAAQ,CAAC,qBAAqB;EAAG,SAAS,CAAC,SAAS;CAAE;AAC1D;;;;;;AAOA,SAAgB,oBAAoB,KAA8B;CAChE,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,QAAQ,aAAa,UAAU,GAAG;EACxC,IAAI,UAAU,KAAA,GACZ,OAAO;CAEX;CACA,OAAO,QAAQ,GAAG,KAAK,kBAAkB,GAAG;AAC9C;AAEA,SAAS,aAAa,UAAoB,KAA8B;CACtE,IAAI,SAAS,WAAW,KAAA,GAAW;EACjC,MAAM,CAAC,MAAM,YAAY,SAAS;EAClC,MAAM,SAAS,IAAI;EACnB,IAAI,WAAW,KAAA,KAAa,WAAW,MAAO,aAAa,KAAA,KAAa,WAAW,UACjF;CAEJ;CACA,KAAK,MAAM,QAAQ,SAAS,SAAS;EACnC,MAAM,SAAS,gBAAgB,IAAI,KAAK;EACxC,IAAI,WAAW,KAAA,GACb,OAAO;CAEX;AAEF;;AAGA,SAAS,QAAQ,KAA8B;CAC7C,MAAM,MAAM,IAAI;CAChB,OAAO,MAAM,gBAAgB,GAAG,IAAI,SAAS,IAAI,KAAA;AACnD;;AAGA,SAAS,kBAAkB,KAA8B;CACvD,MAAM,MAAM,IAAI;CAChB,MAAM,SAAS,IAAI;CACnB,OAAO,OAAO,SAAS,gBAAgB,GAAG,IAAI,GAAG,QAAQ,IAAI,KAAA;AAC/D"}
|
package/dist/utils/redact.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
|
+
import { STORYBOOK_TOKEN_PREFIX, STORYBOOK_TOKEN_SOURCE } from "./storybook-token.mjs";
|
|
4
5
|
//#region src/utils/redact.ts
|
|
5
6
|
/**
|
|
6
7
|
* Secret redaction for adapter errors, health details, and logs.
|
|
@@ -13,10 +14,12 @@ const SECRET_PATTERNS = [
|
|
|
13
14
|
/(:\/\/)[^/\s:]+:[^/\s@]+(?=@)/u,
|
|
14
15
|
/([?&#](?:token|secret|password|api[_-]?key|auth[_-]?token|access[_-]?key)=)[^&#\s]*/giu,
|
|
15
16
|
/((?:password|passwd|secret|token|api[_-]?key|auth[_-]?token|client[_-]?secret|access[_-]?key|private[_-]?key)\s*[:=]\s*['"]?)[^\s'";,[\]&]+/giu,
|
|
17
|
+
new RegExp(`(${STORYBOOK_TOKEN_PREFIX})${STORYBOOK_TOKEN_SOURCE}`, "gu"),
|
|
16
18
|
/AKIA[0-9A-Z]{16}/gu,
|
|
17
19
|
/gh[pous]_[A-Za-z0-9_]+/gu,
|
|
18
20
|
/github_pat_[A-Za-z0-9_]+/gu,
|
|
19
21
|
/xox[bpasr]-[A-Za-z0-9-]+/gu,
|
|
22
|
+
/eyJ[\w-]{8,}\.eyJ[\w-]{8,}\.[\w-]+/gu,
|
|
20
23
|
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu
|
|
21
24
|
];
|
|
22
25
|
/** Replace embedded secrets with `[redacted]`. Never throws on weird input. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.mjs","names":[],"sources":["../../src/utils/redact.ts"],"sourcesContent":["/**\n * Secret redaction for adapter errors, health details, and logs.\n *\n * Adapter-thrown messages routinely embed connection strings and tokens.\n * Every surface that exposes adapter text (503 gate, health report, error\n * logs) must pass through here before truncation or transport.\n */\n\nconst SECRET_PATTERNS: RegExp[] = [\n /(:\\/\\/)[^/\\s:]+:[^/\\s@]+(?=@)/u,\n /([?&#](?:token|secret|password|api[_-]?key|auth[_-]?token|access[_-]?key)=)[^&#\\s]*/giu,\n /((?:password|passwd|secret|token|api[_-]?key|auth[_-]?token|client[_-]?secret|access[_-]?key|private[_-]?key)\\s*[:=]\\s*['\"]?)[^\\s'\";,[\\]&]+/giu,\n /AKIA[0-9A-Z]{16}/gu,\n /gh[pous]_[A-Za-z0-9_]+/gu,\n /github_pat_[A-Za-z0-9_]+/gu,\n /xox[bpasr]-[A-Za-z0-9-]+/gu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu,\n];\n\n/** Replace embedded secrets with `[redacted]`. Never throws on weird input. */\nexport function redactSecrets(text: string): string {\n let redacted = text;\n for (const pattern of SECRET_PATTERNS) {\n pattern.lastIndex = 0;\n redacted = redacted.replace(pattern, (...args: unknown[]) => {\n const group = args[1];\n return typeof group === \"string\" ? `${group}[redacted]` : \"[redacted]\";\n });\n }\n return redacted;\n}\n\n/** Redact secrets, then truncate to `maxLength`. */\nexport function sanitizeErrorText(text: string, maxLength: number): string {\n const redacted = redactSecrets(text);\n return redacted.length > maxLength ? redacted.slice(0, maxLength) : redacted;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"redact.mjs","names":[],"sources":["../../src/utils/redact.ts"],"sourcesContent":["/**\n * Secret redaction for adapter errors, health details, and logs.\n *\n * Adapter-thrown messages routinely embed connection strings and tokens.\n * Every surface that exposes adapter text (503 gate, health report, error\n * logs) must pass through here before truncation or transport.\n */\n\nimport { STORYBOOK_TOKEN_PREFIX, STORYBOOK_TOKEN_SOURCE } from \"./storybook-token.ts\";\n\nconst SECRET_PATTERNS: RegExp[] = [\n /(:\\/\\/)[^/\\s:]+:[^/\\s@]+(?=@)/u,\n /([?&#](?:token|secret|password|api[_-]?key|auth[_-]?token|access[_-]?key)=)[^&#\\s]*/giu,\n /((?:password|passwd|secret|token|api[_-]?key|auth[_-]?token|client[_-]?secret|access[_-]?key|private[_-]?key)\\s*[:=]\\s*['\"]?)[^\\s'\";,[\\]&]+/giu,\n new RegExp(`(${STORYBOOK_TOKEN_PREFIX})${STORYBOOK_TOKEN_SOURCE}`, \"gu\"),\n /AKIA[0-9A-Z]{16}/gu,\n /gh[pous]_[A-Za-z0-9_]+/gu,\n /github_pat_[A-Za-z0-9_]+/gu,\n /xox[bpasr]-[A-Za-z0-9-]+/gu,\n /eyJ[\\w-]{8,}\\.eyJ[\\w-]{8,}\\.[\\w-]+/gu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu,\n];\n\n/** Replace embedded secrets with `[redacted]`. Never throws on weird input. */\nexport function redactSecrets(text: string): string {\n let redacted = text;\n for (const pattern of SECRET_PATTERNS) {\n pattern.lastIndex = 0;\n redacted = redacted.replace(pattern, (...args: unknown[]) => {\n const group = args[1];\n return typeof group === \"string\" ? `${group}[redacted]` : \"[redacted]\";\n });\n }\n return redacted;\n}\n\n/** Redact secrets, then truncate to `maxLength`. */\nexport function sanitizeErrorText(text: string, maxLength: number): string {\n const redacted = redactSecrets(text);\n return redacted.length > maxLength ? redacted.slice(0, maxLength) : redacted;\n}\n"],"mappings":";;;;;;;;;;;;AAUA,MAAM,kBAA4B;CAChC;CACA;CACA;CACA,IAAI,OAAO,IAAI,uBAAuB,GAAG,0BAA0B,IAAI;CACvE;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,SAAgB,cAAc,MAAsB;CAClD,IAAI,WAAW;CACf,KAAK,MAAM,WAAW,iBAAiB;EACrC,QAAQ,YAAY;EACpB,WAAW,SAAS,QAAQ,UAAU,GAAG,SAAoB;GAC3D,MAAM,QAAQ,KAAK;GACnB,OAAO,OAAO,UAAU,WAAW,GAAG,MAAM,cAAc;EAC5D,CAAC;CACH;CACA,OAAO;AACT;;AAGA,SAAgB,kBAAkB,MAAc,WAA2B;CACzE,MAAM,WAAW,cAAc,IAAI;CACnC,OAAO,SAAS,SAAS,YAAY,SAAS,MAAM,GAAG,SAAS,IAAI;AACtE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
import { CaptureEnvironment } from "../adapter/capture-runner.mjs";
|
|
4
|
+
//#region src/utils/remote-environment.d.ts
|
|
5
|
+
/** What the probe page reports. */
|
|
6
|
+
interface BrowserProbe {
|
|
7
|
+
/** OS as the page sees it (`navigator.userAgentData.platform`, else `navigator.platform`). */
|
|
8
|
+
platform?: string;
|
|
9
|
+
deviceScaleFactor?: number;
|
|
10
|
+
/** Which of {@link FONT_PROBE_FAMILIES} are installed. */
|
|
11
|
+
fonts?: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Families probed for the fonts digest: system fonts that differ between operating systems and
|
|
15
|
+
* image builds, so a provider-side change moves the hash. A fixed list; changing it re-baselines
|
|
16
|
+
* every remote target's fingerprint.
|
|
17
|
+
*/
|
|
18
|
+
declare const FONT_PROBE_FAMILIES: readonly string[];
|
|
19
|
+
/**
|
|
20
|
+
* Read the OS, the device pixel ratio and the installed probe fonts. Runs inside the page, so it
|
|
21
|
+
* must stay one self-contained function (no imports, no closures): the runners pass it to
|
|
22
|
+
* `page.evaluate`, which sends its source. A font counts as installed when text in it measures
|
|
23
|
+
* differently from the generic family it would fall back to; `document.fonts.check` answers `true`
|
|
24
|
+
* for a family that does not exist, so it cannot tell.
|
|
25
|
+
*/
|
|
26
|
+
declare function inPageProbe(families: string[]): BrowserProbe;
|
|
27
|
+
/**
|
|
28
|
+
* The environment of a remote render: the driver's browser version and what the page reported. A
|
|
29
|
+
* field the page could not give is left out, except the OS, which falls back to what the service
|
|
30
|
+
* was configured to render on; an unknown fingerprint component is never a change (ADR 0005).
|
|
31
|
+
*/
|
|
32
|
+
declare function remoteEnvironment(options: {
|
|
33
|
+
browserVersion?: string | undefined;
|
|
34
|
+
probe?: BrowserProbe | undefined;
|
|
35
|
+
declaredPlatform?: string | undefined;
|
|
36
|
+
}): CaptureEnvironment;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { BrowserProbe, FONT_PROBE_FAMILIES, inPageProbe, remoteEnvironment };
|
|
39
|
+
//# sourceMappingURL=remote-environment.d.mts.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import "node:path";
|
|
2
|
+
import "node:url";
|
|
3
|
+
import.meta.url;
|
|
4
|
+
import { sha256 } from "./hash.mjs";
|
|
5
|
+
//#region src/utils/remote-environment.ts
|
|
6
|
+
/**
|
|
7
|
+
* Families probed for the fonts digest: system fonts that differ between operating systems and
|
|
8
|
+
* image builds, so a provider-side change moves the hash. A fixed list; changing it re-baselines
|
|
9
|
+
* every remote target's fingerprint.
|
|
10
|
+
*/
|
|
11
|
+
const FONT_PROBE_FAMILIES = [
|
|
12
|
+
"Arial",
|
|
13
|
+
"Helvetica",
|
|
14
|
+
"Helvetica Neue",
|
|
15
|
+
"Times New Roman",
|
|
16
|
+
"Georgia",
|
|
17
|
+
"Verdana",
|
|
18
|
+
"Tahoma",
|
|
19
|
+
"Trebuchet MS",
|
|
20
|
+
"Courier New",
|
|
21
|
+
"Consolas",
|
|
22
|
+
"Menlo",
|
|
23
|
+
"Monaco",
|
|
24
|
+
"Segoe UI",
|
|
25
|
+
"Calibri",
|
|
26
|
+
"Cambria",
|
|
27
|
+
"San Francisco",
|
|
28
|
+
"SF Pro Text",
|
|
29
|
+
"Lucida Grande",
|
|
30
|
+
"Roboto",
|
|
31
|
+
"Open Sans",
|
|
32
|
+
"Noto Sans",
|
|
33
|
+
"Noto Serif",
|
|
34
|
+
"Noto Sans Mono",
|
|
35
|
+
"Noto Color Emoji",
|
|
36
|
+
"Apple Color Emoji",
|
|
37
|
+
"Segoe UI Emoji",
|
|
38
|
+
"DejaVu Sans",
|
|
39
|
+
"DejaVu Serif",
|
|
40
|
+
"DejaVu Sans Mono",
|
|
41
|
+
"Liberation Sans",
|
|
42
|
+
"Liberation Serif",
|
|
43
|
+
"Liberation Mono",
|
|
44
|
+
"Ubuntu",
|
|
45
|
+
"Cantarell",
|
|
46
|
+
"Droid Sans",
|
|
47
|
+
"Source Sans Pro",
|
|
48
|
+
"Fira Sans",
|
|
49
|
+
"Inter",
|
|
50
|
+
"Arial Unicode MS",
|
|
51
|
+
"MS Gothic",
|
|
52
|
+
"Hiragino Sans",
|
|
53
|
+
"PingFang SC",
|
|
54
|
+
"Microsoft YaHei",
|
|
55
|
+
"Malgun Gothic"
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* Read the OS, the device pixel ratio and the installed probe fonts. Runs inside the page, so it
|
|
59
|
+
* must stay one self-contained function (no imports, no closures): the runners pass it to
|
|
60
|
+
* `page.evaluate`, which sends its source. A font counts as installed when text in it measures
|
|
61
|
+
* differently from the generic family it would fall back to; `document.fonts.check` answers `true`
|
|
62
|
+
* for a family that does not exist, so it cannot tell.
|
|
63
|
+
*/
|
|
64
|
+
function inPageProbe(families) {
|
|
65
|
+
const win = globalThis;
|
|
66
|
+
const probe = {};
|
|
67
|
+
const reported = win.navigator.userAgentData?.platform;
|
|
68
|
+
const platform = reported === void 0 || reported === "" ? win.navigator.platform : reported;
|
|
69
|
+
if (platform) probe.platform = platform;
|
|
70
|
+
if (typeof win.devicePixelRatio === "number") probe.deviceScaleFactor = win.devicePixelRatio;
|
|
71
|
+
const context = win.document.createElement("canvas").getContext("2d");
|
|
72
|
+
if (!context) return probe;
|
|
73
|
+
const text = "mmmmmmmmmmlli1WwQqÅgy 漢字";
|
|
74
|
+
const generics = [
|
|
75
|
+
"monospace",
|
|
76
|
+
"sans-serif",
|
|
77
|
+
"serif"
|
|
78
|
+
];
|
|
79
|
+
const widthOf = (font) => {
|
|
80
|
+
context.font = `72px ${font}`;
|
|
81
|
+
return context.measureText(text).width;
|
|
82
|
+
};
|
|
83
|
+
const baseline = generics.map((generic) => widthOf(generic));
|
|
84
|
+
probe.fonts = families.filter((family) => generics.some((generic, index) => widthOf(`"${family}", ${generic}`) !== baseline[index]));
|
|
85
|
+
return probe;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The environment of a remote render: the driver's browser version and what the page reported. A
|
|
89
|
+
* field the page could not give is left out, except the OS, which falls back to what the service
|
|
90
|
+
* was configured to render on; an unknown fingerprint component is never a change (ADR 0005).
|
|
91
|
+
*/
|
|
92
|
+
function remoteEnvironment(options) {
|
|
93
|
+
const { probe, browserVersion } = options;
|
|
94
|
+
const platform = normalizePlatform(probe?.platform) ?? options.declaredPlatform;
|
|
95
|
+
const fonts = probe?.fonts;
|
|
96
|
+
return {
|
|
97
|
+
...browserVersion ? { browserVersion } : {},
|
|
98
|
+
...platform ? { platform } : {},
|
|
99
|
+
...probe?.deviceScaleFactor ? { deviceScaleFactor: probe.deviceScaleFactor } : {},
|
|
100
|
+
...fonts && fonts.length > 0 ? { fontsHash: sha256(fonts.toSorted().join("\n")).slice(0, 16) } : {}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** `Win32`, `Windows` and `Linux x86_64` read as the OS, in one spelling per OS. */
|
|
104
|
+
function normalizePlatform(value) {
|
|
105
|
+
const text = value?.trim().toLowerCase();
|
|
106
|
+
if (!text) return;
|
|
107
|
+
if (text.startsWith("win")) return "windows";
|
|
108
|
+
if (text.startsWith("mac") || text === "iphone" || text === "ipad") return "macos";
|
|
109
|
+
return text.startsWith("linux") ? "linux" : text;
|
|
110
|
+
}
|
|
111
|
+
//#endregion
|
|
112
|
+
export { FONT_PROBE_FAMILIES, inPageProbe, remoteEnvironment };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=remote-environment.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-environment.mjs","names":[],"sources":["../../src/utils/remote-environment.ts"],"sourcesContent":["/**\n * The environment of a remote browser, measured inside it (ADR 0007, decision 2). `fc-list` and\n * `process.platform` describe the machine running the runner, not the one that rendered.\n */\nimport type { CaptureEnvironment } from \"../adapters/capture-runner.ts\";\nimport { sha256 } from \"./hash.ts\";\n\n/** What the probe page reports. */\nexport interface BrowserProbe {\n /** OS as the page sees it (`navigator.userAgentData.platform`, else `navigator.platform`). */\n platform?: string;\n deviceScaleFactor?: number;\n /** Which of {@link FONT_PROBE_FAMILIES} are installed. */\n fonts?: string[];\n}\n\n/**\n * Families probed for the fonts digest: system fonts that differ between operating systems and\n * image builds, so a provider-side change moves the hash. A fixed list; changing it re-baselines\n * every remote target's fingerprint.\n */\nexport const FONT_PROBE_FAMILIES: readonly string[] = [\n \"Arial\",\n \"Helvetica\",\n \"Helvetica Neue\",\n \"Times New Roman\",\n \"Georgia\",\n \"Verdana\",\n \"Tahoma\",\n \"Trebuchet MS\",\n \"Courier New\",\n \"Consolas\",\n \"Menlo\",\n \"Monaco\",\n \"Segoe UI\",\n \"Calibri\",\n \"Cambria\",\n \"San Francisco\",\n \"SF Pro Text\",\n \"Lucida Grande\",\n \"Roboto\",\n \"Open Sans\",\n \"Noto Sans\",\n \"Noto Serif\",\n \"Noto Sans Mono\",\n \"Noto Color Emoji\",\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"DejaVu Sans\",\n \"DejaVu Serif\",\n \"DejaVu Sans Mono\",\n \"Liberation Sans\",\n \"Liberation Serif\",\n \"Liberation Mono\",\n \"Ubuntu\",\n \"Cantarell\",\n \"Droid Sans\",\n \"Source Sans Pro\",\n \"Fira Sans\",\n \"Inter\",\n \"Arial Unicode MS\",\n \"MS Gothic\",\n \"Hiragino Sans\",\n \"PingFang SC\",\n \"Microsoft YaHei\",\n \"Malgun Gothic\",\n];\n\n/**\n * Read the OS, the device pixel ratio and the installed probe fonts. Runs inside the page, so it\n * must stay one self-contained function (no imports, no closures): the runners pass it to\n * `page.evaluate`, which sends its source. A font counts as installed when text in it measures\n * differently from the generic family it would fall back to; `document.fonts.check` answers `true`\n * for a family that does not exist, so it cannot tell.\n */\n// oxlint-disable-next-line eslint/max-statements, eslint/max-lines-per-function -- must stay one self-contained function (see above)\nexport function inPageProbe(families: string[]): BrowserProbe {\n const win = globalThis as unknown as {\n devicePixelRatio?: number;\n navigator: { userAgentData?: { platform?: string }; platform?: string };\n document: {\n createElement: (tag: string) => {\n getContext: (kind: string) => {\n font: string;\n measureText: (text: string) => { width: number };\n } | null;\n };\n };\n };\n const probe: BrowserProbe = {};\n const reported = win.navigator.userAgentData?.platform;\n const platform = reported === undefined || reported === \"\" ? win.navigator.platform : reported;\n if (platform) probe.platform = platform;\n if (typeof win.devicePixelRatio === \"number\") probe.deviceScaleFactor = win.devicePixelRatio;\n const context = win.document.createElement(\"canvas\").getContext(\"2d\");\n if (!context) return probe;\n const text = \"mmmmmmmmmmlli1WwQqÅgy 漢字\";\n const generics = [\"monospace\", \"sans-serif\", \"serif\"];\n const widthOf = (font: string): number => {\n context.font = `72px ${font}`;\n return context.measureText(text).width;\n };\n const baseline = generics.map((generic) => widthOf(generic));\n probe.fonts = families.filter((family) =>\n generics.some((generic, index) => widthOf(`\"${family}\", ${generic}`) !== baseline[index]),\n );\n return probe;\n}\n\n/**\n * The environment of a remote render: the driver's browser version and what the page reported. A\n * field the page could not give is left out, except the OS, which falls back to what the service\n * was configured to render on; an unknown fingerprint component is never a change (ADR 0005).\n */\nexport function remoteEnvironment(options: {\n browserVersion?: string | undefined;\n probe?: BrowserProbe | undefined;\n declaredPlatform?: string | undefined;\n}): CaptureEnvironment {\n const { probe, browserVersion } = options;\n const platform = normalizePlatform(probe?.platform) ?? options.declaredPlatform;\n const fonts = probe?.fonts;\n return {\n ...(browserVersion ? { browserVersion } : {}),\n ...(platform ? { platform } : {}),\n ...(probe?.deviceScaleFactor ? { deviceScaleFactor: probe.deviceScaleFactor } : {}),\n ...(fonts && fonts.length > 0\n ? { fontsHash: sha256(fonts.toSorted().join(\"\\n\")).slice(0, 16) }\n : {}),\n };\n}\n\n/** `Win32`, `Windows` and `Linux x86_64` read as the OS, in one spelling per OS. */\nfunction normalizePlatform(value: string | undefined): string | undefined {\n const text = value?.trim().toLowerCase();\n if (!text) {\n return undefined;\n }\n if (text.startsWith(\"win\")) return \"windows\";\n if (text.startsWith(\"mac\") || text === \"iphone\" || text === \"ipad\") return \"macos\";\n return text.startsWith(\"linux\") ? \"linux\" : text;\n}\n"],"mappings":";;;;;;;;;;AAqBA,MAAa,sBAAyC;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;AAUA,SAAgB,YAAY,UAAkC;CAC5D,MAAM,MAAM;CAYZ,MAAM,QAAsB,CAAC;CAC7B,MAAM,WAAW,IAAI,UAAU,eAAe;CAC9C,MAAM,WAAW,aAAa,KAAA,KAAa,aAAa,KAAK,IAAI,UAAU,WAAW;CACtF,IAAI,UAAU,MAAM,WAAW;CAC/B,IAAI,OAAO,IAAI,qBAAqB,UAAU,MAAM,oBAAoB,IAAI;CAC5E,MAAM,UAAU,IAAI,SAAS,cAAc,QAAQ,CAAC,CAAC,WAAW,IAAI;CACpE,IAAI,CAAC,SAAS,OAAO;CACrB,MAAM,OAAO;CACb,MAAM,WAAW;EAAC;EAAa;EAAc;CAAO;CACpD,MAAM,WAAW,SAAyB;EACxC,QAAQ,OAAO,QAAQ;EACvB,OAAO,QAAQ,YAAY,IAAI,CAAC,CAAC;CACnC;CACA,MAAM,WAAW,SAAS,KAAK,YAAY,QAAQ,OAAO,CAAC;CAC3D,MAAM,QAAQ,SAAS,QAAQ,WAC7B,SAAS,MAAM,SAAS,UAAU,QAAQ,IAAI,OAAO,KAAK,SAAS,MAAM,SAAS,MAAM,CAC1F;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,kBAAkB,SAIX;CACrB,MAAM,EAAE,OAAO,mBAAmB;CAClC,MAAM,WAAW,kBAAkB,OAAO,QAAQ,KAAK,QAAQ;CAC/D,MAAM,QAAQ,OAAO;CACrB,OAAO;EACL,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;EAC3C,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,GAAI,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,kBAAkB,IAAI,CAAC;EACjF,GAAI,SAAS,MAAM,SAAS,IACxB,EAAE,WAAW,OAAO,MAAM,SAAS,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,EAAE,IAC9D,CAAC;CACP;AACF;;AAGA,SAAS,kBAAkB,OAA+C;CACxE,MAAM,OAAO,OAAO,KAAK,CAAC,CAAC,YAAY;CACvC,IAAI,CAAC,MACH;CAEF,IAAI,KAAK,WAAW,KAAK,GAAG,OAAO;CACnC,IAAI,KAAK,WAAW,KAAK,KAAK,SAAS,YAAY,SAAS,QAAQ,OAAO;CAC3E,OAAO,KAAK,WAAW,OAAO,IAAI,UAAU;AAC9C"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import __tsdown_shims_path from 'node:path';
|
|
2
|
+
import __tsdown_shims_url from 'node:url';
|
|
3
|
+
//#region src/utils/resources.d.ts
|
|
4
|
+
/** CPU and memory actually available to this process (container limits included). */
|
|
5
|
+
interface HostResources {
|
|
6
|
+
/** Fractional vCPUs: a cgroup quota of 0.5 CPU reports `0.5`. */
|
|
7
|
+
cpus: number;
|
|
8
|
+
memoryBytes: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Detect the CPU and memory budget. Container limits win over the host's: a
|
|
12
|
+
* 0.5 vCPU / 1 GB container on a large machine must be sized as 0.5 / 1 GB.
|
|
13
|
+
*/
|
|
14
|
+
declare function detectResources(): HostResources;
|
|
15
|
+
/**
|
|
16
|
+
* Cost of one page in Chromium-page slots. Firefox and WebKit pages cost about twice a Chromium
|
|
17
|
+
* page in CPU time (ray.run cross-browser benchmarks: Firefox +71%, WebKit +60%; some Playwright
|
|
18
|
+
* reports show WebKit worse), so they get half the page budget. Takes a capture target too.
|
|
19
|
+
*/
|
|
20
|
+
declare function engineWeight(browser?: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* Pages to render at once: no more than the CPUs (extra pages only slow each
|
|
23
|
+
* other down and trip timeouts) and no more than memory allows. A heavier engine
|
|
24
|
+
* (see {@link engineWeight}) spends the same budget on fewer pages.
|
|
25
|
+
*/
|
|
26
|
+
declare function recommendedPageConcurrency(resources?: HostResources, browser?: string): number;
|
|
27
|
+
/**
|
|
28
|
+
* Most pages the adaptive controller may reach: memory is a hard limit, but CPU is only a
|
|
29
|
+
* starting point (latency tells us when it is saturated), so allow up to twice the CPUs.
|
|
30
|
+
*/
|
|
31
|
+
declare function maxPageConcurrency(resources?: HostResources, browser?: string): number;
|
|
32
|
+
/** Builds to capture at once: each launches its own browser, so only on roomy hosts. */
|
|
33
|
+
declare function recommendedBuildConcurrency(resources?: HostResources): number;
|
|
34
|
+
/** Playwright's 30 s default assumes a full CPU; starved containers parse the Storybook bundle slower. */
|
|
35
|
+
declare function recommendedNavigationTimeoutMs(resources?: HostResources): number;
|
|
36
|
+
/** Captures between browser restarts: Chromium grows slowly over a long run, so recycle it. */
|
|
37
|
+
declare const DEFAULT_RECYCLE_BROWSER_EVERY = 150;
|
|
38
|
+
/** Loggable summary of the host budget and the capture settings derived from it. */
|
|
39
|
+
declare function describeSizing(settings: {
|
|
40
|
+
browser?: string;
|
|
41
|
+
concurrency?: number;
|
|
42
|
+
navigationTimeoutMs?: number;
|
|
43
|
+
recycleBrowserEvery?: number;
|
|
44
|
+
}): Record<string, number>;
|
|
45
|
+
/** What capture will use on this host: detected resources and the effective concurrency. */
|
|
46
|
+
interface CaptureHostSummary {
|
|
47
|
+
cpus: number;
|
|
48
|
+
memoryMb: number;
|
|
49
|
+
/** Builds captured at once, and whether that was sized from the hardware or configured. */
|
|
50
|
+
builds: {
|
|
51
|
+
value: number;
|
|
52
|
+
auto: boolean;
|
|
53
|
+
};
|
|
54
|
+
/** Pages per build when the runner is not pinned: where it starts and the most it may reach (Chromium). */
|
|
55
|
+
pages: {
|
|
56
|
+
start: number;
|
|
57
|
+
max: number;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Summarise the host budget and effective capture concurrency, for the System page. */
|
|
61
|
+
declare function describeCaptureHost(configuredBuilds?: number, resources?: HostResources): CaptureHostSummary;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { CaptureHostSummary, DEFAULT_RECYCLE_BROWSER_EVERY, HostResources, describeCaptureHost, describeSizing, detectResources, engineWeight, maxPageConcurrency, recommendedBuildConcurrency, recommendedNavigationTimeoutMs, recommendedPageConcurrency };
|
|
64
|
+
//# sourceMappingURL=resources.d.mts.map
|