diff --git a/.github/workflows/release-shared.yml b/.github/workflows/release-shared.yml index 45c2b4d04d..f2950451cb 100644 --- a/.github/workflows/release-shared.yml +++ b/.github/workflows/release-shared.yml @@ -38,6 +38,10 @@ on: required: false type: string default: supabase + outputs: + setup_cli_npm_fallback: + description: "'true' when a setup-cli v3 smoke job installed from the GitHub release because the npm install failed" + value: ${{ jobs.setup-cli-smoke.outputs.npm_fallback }} secrets: SENTRY_DSN: required: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6f32d098ac..e5ab3ce936 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -473,6 +473,28 @@ jobs: status: success version: ${{ needs.plan.outputs.version }} channel: ${{ needs.plan.outputs.channel }} + setup_cli_npm_fallback: ${{ needs.release.outputs.setup_cli_npm_fallback == 'true' }} + secrets: + SLACK_RELEASE_WEBHOOK: ${{ secrets.SLACK_RELEASE_WEBHOOK }} + + # notify-slack posts no success message for beta and next, so a setup-cli npm fallback on those + # channels gets a notice of its own. + notify-slack-npm-fallback: + name: Notify Slack (setup-cli npm fallback) + needs: [plan, release] + if: >- + ${{ !cancelled() && + needs.release.result == 'success' && + needs.plan.outputs.dry_run != 'true' && + needs.release.outputs.setup_cli_npm_fallback == 'true' && + needs.plan.outputs.channel != 'stable' && + needs.plan.outputs.channel != 'maintenance' }} + uses: ./.github/workflows/slack-notify.yml + with: + package: Supabase CLI + status: setup-cli-npm-fallback + version: ${{ needs.plan.outputs.version }} + channel: ${{ needs.plan.outputs.channel }} secrets: SLACK_RELEASE_WEBHOOK: ${{ secrets.SLACK_RELEASE_WEBHOOK }} diff --git a/.github/workflows/setup-cli-smoke-test.yml b/.github/workflows/setup-cli-smoke-test.yml index 7250265fcd..db5e4c0596 100644 --- a/.github/workflows/setup-cli-smoke-test.yml +++ b/.github/workflows/setup-cli-smoke-test.yml @@ -5,7 +5,7 @@ name: setup-cli Smoke Test # workflow_dispatch when debugging setup-cli regressions. Catches regressions like # supabase/setup-cli#427, where musl libc + archive layout changes silently broke the action on # Alpine. v3 installs from npm: each v3 runner first waits until npm serves the version, and the -# job fails if setup-cli fell back to the GitHub release. A separate job forces that fallback. +# job warns if setup-cli fell back to the GitHub release. A separate job forces that fallback. on: workflow_call: @@ -14,6 +14,10 @@ on: description: Supabase CLI version to install via setup-cli (must already be published to GitHub Releases and npm) required: true type: string + outputs: + npm_fallback: + description: "'true' when any v3 job installed from the GitHub release because the npm install failed" + value: ${{ jobs.summary.outputs.npm_fallback }} workflow_dispatch: inputs: version: @@ -89,7 +93,8 @@ jobs: echo "Version mismatch: expected ${expected}, got ${actual}" >&2 exit 1 fi - - name: Verify setup-cli installed from npm + - name: Warn if setup-cli fell back from npm + id: npm-source if: matrix.major-version == 'v3' shell: bash env: @@ -97,9 +102,18 @@ jobs: run: | set -euo pipefail if [ "${INSTALL_SOURCE}" != "npm" ]; then - echo "::error::setup-cli fell back to ${INSTALL_SOURCE} because installing supabase@${VERSION#v} from npm failed; check the setup-cli step log" - exit 1 + echo "::warning::setup-cli fell back to ${INSTALL_SOURCE} because installing supabase@${VERSION#v} from npm failed; check the setup-cli step log" + echo "${INSTALL_SOURCE}" > npm-fallback.txt + echo "fallback=true" >> "$GITHUB_OUTPUT" fi + - name: Record the npm fallback + if: steps.npm-source.outputs.fallback == 'true' + # Best-effort: a failed upload must not fail the release; the warning above still annotates the run. + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: npm-fallback-v3-${{ matrix.runner }} + path: npm-fallback.txt # A separate job because GitHub Actions only honours `container:` on Linux runners, and mixing # container + non-container entries in one matrix is fragile when the value is empty. The @@ -172,7 +186,8 @@ jobs: echo "Version mismatch: expected ${expected}, got ${actual}" >&2 exit 1 fi - - name: Verify setup-cli installed from npm + - name: Warn if setup-cli fell back from npm + id: npm-source if: matrix.major-version == 'v3' shell: bash env: @@ -180,9 +195,18 @@ jobs: run: | set -euo pipefail if [ "${INSTALL_SOURCE}" != "npm" ]; then - echo "::error::setup-cli fell back to ${INSTALL_SOURCE} because installing supabase@${VERSION#v} from npm failed; check the setup-cli step log" - exit 1 + echo "::warning::setup-cli fell back to ${INSTALL_SOURCE} because installing supabase@${VERSION#v} from npm failed; check the setup-cli step log" + echo "${INSTALL_SOURCE}" > npm-fallback.txt + echo "fallback=true" >> "$GITHUB_OUTPUT" fi + - name: Record the npm fallback + if: steps.npm-source.outputs.fallback == 'true' + # Best-effort: a failed upload must not fail the release; the warning above still annotates the run. + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: npm-fallback-v3-alpine + path: npm-fallback.txt setup-cli-smoke-test-github-release: name: setup-cli v3 GitHub release fallback (ubuntu-latest) @@ -222,3 +246,30 @@ jobs: echo "::error::setup-cli installed from ${INSTALL_SOURCE} instead of falling back to the GitHub release with npm disabled" exit 1 fi + + summary: + name: setup-cli npm fallback summary + needs: [setup-cli-smoke-test, setup-cli-smoke-test-alpine] + if: ${{ always() }} + runs-on: ubuntu-latest + timeout-minutes: 2 + permissions: + actions: read + outputs: + npm_fallback: ${{ steps.fallbacks.outputs.npm_fallback }} + steps: + - id: fallbacks + shell: bash + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} + run: | + set -euo pipefail + # Never exits nonzero: failing here would fail the release. + if ! names="$(gh api --paginate "repos/${REPO}/actions/runs/${RUN_ID}/artifacts" --jq '.artifacts[].name')"; then + echo "::warning::Could not list this run's artifacts, so the setup-cli npm fallback check did not run; check the setup-cli v3 smoke jobs for a fallback warning" + exit 0 + fi + count="$(grep -c '^npm-fallback-' <<< "${names}" || true)" + echo "npm_fallback=$([ "${count}" -gt 0 ] && echo true || echo false)" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/slack-notify.yml b/.github/workflows/slack-notify.yml index 6bfbf2c800..18c03259b3 100644 --- a/.github/workflows/slack-notify.yml +++ b/.github/workflows/slack-notify.yml @@ -18,7 +18,7 @@ on: type: string default: "" status: - description: Notification kind (success | failure | publish-failure | awaiting-approval | declined | sync-conflict) + description: Notification kind (success | failure | publish-failure | setup-cli-npm-fallback | awaiting-approval | declined | sync-conflict) required: false type: string default: success @@ -37,6 +37,11 @@ on: required: false type: string default: "" + setup_cli_npm_fallback: + description: Whether the setup-cli smoke test fell back from npm to the GitHub release. Adds a notice to success messages. + required: false + type: boolean + default: false secrets: SLACK_RELEASE_WEBHOOK: required: true @@ -58,6 +63,7 @@ jobs: TAG_PREFIX: ${{ inputs.tag_prefix }} NPM_PACKAGE: ${{ inputs.npm_package }} PULL_REQUEST: ${{ inputs.pull_request }} + SETUP_CLI_NPM_FALLBACK: ${{ inputs.setup_cli_npm_fallback }} REPO: ${{ github.repository }} RUN_ID: ${{ github.run_id }} SHA: ${{ github.sha }} @@ -86,6 +92,9 @@ jobs: if [[ -n "$NPM_PACKAGE" ]]; then DETAILS="*npm:* \n${DETAILS}" fi + if [[ "$SETUP_CLI_NPM_FALLBACK" == "true" ]]; then + DETAILS="⚠️ *setup-cli smoke test:* installing from npm failed and setup-cli fell back to the GitHub release. See the setup-cli smoke jobs in the workflow run.\n${DETAILS}" + fi ;; failure) # version/channel may be empty when the planning job itself failed, so @@ -110,6 +119,11 @@ jobs: FALLBACK_TEXT="⚠️ ${PACKAGE} v${VERSION} was released, but publishing to supabase.com failed" DETAILS="The CLI reference or config schemas pull request in supabase/supabase was not opened or updated. Rerun the *Publish to supabase.com* job.\n*Version:* v${VERSION}\n*Commit:* <${COMMIT_URL}|${SHORT_SHA}>\n*Workflow run:* <${RUN_URL}|view failed run>" ;; + setup-cli-npm-fallback) + HEADER="⚠️ ${PACKAGE} v${VERSION} released, but setup-cli fell back from npm" + FALLBACK_TEXT="⚠️ ${PACKAGE} v${VERSION} was released, but setup-cli fell back from npm to the GitHub release" + DETAILS="Installing from npm failed in the setup-cli smoke test and setup-cli fell back to the GitHub release. See the setup-cli smoke jobs in the workflow run.\n*Version:* v${VERSION}\n*Commit:* <${COMMIT_URL}|${SHORT_SHA}>\n*Workflow run:* <${RUN_URL}|view run>" + ;; awaiting-approval) # The approval itself happens on the workflow run page (Approve button + # the plan job's evidence summary) — an incoming webhook is one-way and diff --git a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/2.response.json b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/2.response.json index 094d8a0403..f804e58f0b 100644 --- a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/2.response.json +++ b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/2.response.json @@ -211,6 +211,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/3.response.json b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/3.response.json index 287ee554dc..2dceb7b86b 100644 --- a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/3.response.json +++ b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/3.response.json @@ -211,6 +211,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/default.response.json b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/default.response.json index 49f7407b5b..a7f3195df3 100644 --- a/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/default.response.json +++ b/apps/cli-e2e/fixtures/recorded/GET_v1_projects_replayfixtureprojref_config_auth/default.response.json @@ -211,6 +211,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/recorded/GET_v2_projects_replayfixtureprojref_config/default.response.json b/apps/cli-e2e/fixtures/recorded/GET_v2_projects_replayfixtureprojref_config/default.response.json index 3bddcd789d..1240bf53b4 100644 --- a/apps/cli-e2e/fixtures/recorded/GET_v2_projects_replayfixtureprojref_config/default.response.json +++ b/apps/cli-e2e/fixtures/recorded/GET_v2_projects_replayfixtureprojref_config/default.response.json @@ -249,6 +249,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/recorded/PATCH_v1_projects_replayfixtureprojref_config_auth/default.response.json b/apps/cli-e2e/fixtures/recorded/PATCH_v1_projects_replayfixtureprojref_config_auth/default.response.json index 402a0c2d5b..4f71d9bd0d 100644 --- a/apps/cli-e2e/fixtures/recorded/PATCH_v1_projects_replayfixtureprojref_config_auth/default.response.json +++ b/apps/cli-e2e/fixtures/recorded/PATCH_v1_projects_replayfixtureprojref_config_auth/default.response.json @@ -211,6 +211,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": null, "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/scenarios/config-push-emits-http-trace-with-debug/interactions.json b/apps/cli-e2e/fixtures/scenarios/config-push-emits-http-trace-with-debug/interactions.json index 3592f95830..364587aa38 100644 --- a/apps/cli-e2e/fixtures/scenarios/config-push-emits-http-trace-with-debug/interactions.json +++ b/apps/cli-e2e/fixtures/scenarios/config-push-emits-http-trace-with-debug/interactions.json @@ -1006,6 +1006,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/scenarios/config-push-reconciles-every-section-against-the-remote/interactions.json b/apps/cli-e2e/fixtures/scenarios/config-push-reconciles-every-section-against-the-remote/interactions.json index 08cd367f99..55ab56ae37 100644 --- a/apps/cli-e2e/fixtures/scenarios/config-push-reconciles-every-section-against-the-remote/interactions.json +++ b/apps/cli-e2e/fixtures/scenarios/config-push-reconciles-every-section-against-the-remote/interactions.json @@ -1006,6 +1006,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli-e2e/fixtures/scenarios/link-links-when-only-supabase-project-id-is-set-in-non-tty/interactions.json b/apps/cli-e2e/fixtures/scenarios/link-links-when-only-supabase-project-id-is-set-in-non-tty/interactions.json index c6976da175..533d5a944a 100644 --- a/apps/cli-e2e/fixtures/scenarios/link-links-when-only-supabase-project-id-is-set-in-non-tty/interactions.json +++ b/apps/cli-e2e/fixtures/scenarios/link-links-when-only-supabase-project-id-is-set-in-non-tty/interactions.json @@ -526,6 +526,7 @@ "saml_enabled": false, "saml_external_url": null, "security_sb_forwarded_for_enabled": false, + "external_email_magic_link_disabled": false, "security_captcha_enabled": false, "security_captcha_provider": "hcaptcha", "security_captcha_secret": null, diff --git a/apps/cli/AGENTS.md b/apps/cli/AGENTS.md index 255aa73a61..248aae28d3 100644 --- a/apps/cli/AGENTS.md +++ b/apps/cli/AGENTS.md @@ -229,9 +229,12 @@ text layer. Therefore stdout is payload-only for either machine flag. Do not cha layer to move spinners; that would change text output globally. Handlers check `--output` first and use established encoders before the `output.format` branch. -Plan-gated denials carry an optional `entitlement: { feature, upgrade_url }` on the json and -stream-json error object. `mapHttpError` attaches it from the Management API's -`entitlement_required` body, so a handler that rebuilds a mapped status error must forward it. +Plan-gated denials carry an optional `entitlement: { feature, upgrade_url }` on the error. +`mapHttpError` attaches it from the Management API's `entitlement_required` body. The json and +stream-json error object carries it, the text layer's `fail` prints the upgrade hint from it, and +`withCommandTelemetry` fires `cli_upgrade_suggested` from it, so a handler that rebuilds a mapped +status error must forward it. `suggestUpgrade` prints and fires only on its entitlements-lookup +fallback. ## Targets and hosted consent diff --git a/apps/cli/bench/workloads.pr.json b/apps/cli/bench/workloads.pr.json index d599457f3d..d735b5d552 100644 --- a/apps/cli/bench/workloads.pr.json +++ b/apps/cli/bench/workloads.pr.json @@ -4,6 +4,7 @@ { "id": "help", "args": ["--help"], "cwdSetup": "none" }, { "id": "init", "args": ["init"], "cwdSetup": "none" }, { "id": "migration-new", "args": ["migration", "new", "bench"], "cwdSetup": "init" }, + { "id": "config-convert", "args": ["config", "convert"], "cwdSetup": "init" }, { "id": "gen-types", "args": ["gen", "types", "--lang", "typescript", "--project-id", "replayfixtureprojref"], diff --git a/apps/cli/docs/analytics.md b/apps/cli/docs/analytics.md index f56f6bc8c3..fba2781e52 100644 --- a/apps/cli/docs/analytics.md +++ b/apps/cli/docs/analytics.md @@ -68,6 +68,9 @@ It is emitted once per handled command invocation and includes: - `exit_code` - `duration_ms` - `output_format` +- `config_format` (`toml`, `json` or `jsonc`) once the command reads the project's config file, + set on success and on failure, including when the file fails to parse. Commands that never read + the project config, and projects without one, omit it Failed invocations (`exit_code != 0`) handled by the TS shells also carry a sanitized error classification: diff --git a/apps/cli/docs/release-process.md b/apps/cli/docs/release-process.md index 7ade1efbf7..de78ea5264 100644 --- a/apps/cli/docs/release-process.md +++ b/apps/cli/docs/release-process.md @@ -534,7 +534,7 @@ Both updaters run automatically from `release-shared.yml`'s `publish-homebrew` a Once the channels are live, two reusable workflows run automatically (last in `release-shared.yml`, non-gating — by the time they run the artifacts are already published, so a failure surfaces as a red post-release signal rather than blocking distribution): -- `[setup-cli-smoke-test.yml](../../../.github/workflows/setup-cli-smoke-test.yml)` (`setup-cli-smoke` job) — installs the released version through `supabase/setup-cli` v1 and v2 (the GitHub Release download path) and v3 (the npm package) on Linux, macOS, Windows, and Alpine. v3 waits on each runner until npm serves the version (up to 15 minutes) and fails unless setup-cli installed from npm; one ubuntu job forces the GitHub release fallback. +- `[setup-cli-smoke-test.yml](../../../.github/workflows/setup-cli-smoke-test.yml)` (`setup-cli-smoke` job) — installs the released version through `supabase/setup-cli` v1 and v2 (the GitHub Release download path) and v3 (the npm package) on Linux, macOS, Windows, and Alpine. v3 waits on each runner until npm serves the version (up to 15 minutes) and warns when setup-cli installed from somewhere other than npm, since the GitHub release fallback is a supported path; the fallback is added as a notice to the success Slack message on `stable`/`maintenance` and posted as its own notice on `beta`/`next`, which get no success message; one ubuntu job forces the GitHub release fallback. - `[verify-install-channels.yml](../../../.github/workflows/verify-install-channels.yml)` (`verify-install-channels` job) — runs a **real** `brew install` (macOS **and** Linux, so both the `on_macos` and `on_linux` stanzas of the formula are exercised), `scoop install`, and `curl|bash` install of the **published** install script (fetched from the release asset, not the repo checkout) against the just-published Homebrew tap, Scoop bucket, and GitHub Release. Each leg then asserts `supabase --version` matches and runs `supabase --help` to exercise the actual command tree. brew, scoop, and the install script each verify the published `sha256`/`hash` against the downloaded tarball, so this is the signal that would have caught CLI v2.107.0 (where the brew/scoop manifests shipped checksums that did not match the release tarballs and every `brew install` / `scoop install` failed). It only runs for `beta`/`stable`/`maintenance` (the channels that publish brew/scoop) and can be dispatched manually against any already-published version via the Actions tab. ### Code signing (macOS) diff --git a/apps/cli/docs/stack-commands.md b/apps/cli/docs/stack-commands.md index d2128923cc..3db8236729 100644 --- a/apps/cli/docs/stack-commands.md +++ b/apps/cli/docs/stack-commands.md @@ -339,6 +339,20 @@ The flag is local CLI configuration in `supabase/config.toml` or `supabase/confi excluded from hosted project configuration. Routing applies the CLI's working-directory rules, including `--workdir` and `SUPABASE_WORKDIR`, and prefers JSON when both files exist. +Stack mode rejects a `db.major_version` other than 15 or 17, a non-empty `experimental.s3_*` value +while `db.orioledb_version` is set, an `edge_runtime.deno_version` other than 2 while Edge Runtime +is enabled, and `analytics.backend = "bigquery"` or a non-empty `analytics.gcp_*` value while +Analytics is enabled. The error names the setting. + +`[api.tls]` serves the API port over HTTPS, with plain HTTP only from loopback. The certificate must +have an IP subject alternative name for `127.0.0.1` (for example `mkcert localhost 127.0.0.1`; +bucket seeding and stack `storage` commands then also need +`NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"`), and +containers must reach the host from loopback: on macOS, Docker Desktop, colima and Podman machine +do; on Linux, rootful Docker, rootful Podman and rootless Podman on pasta don't, so a start that +serves the API over TLS fails there with `api.tls: unsupported networking`. The `stack start` side +effects list its errors. + Stack mode keeps its state under `SUPABASE_HOME` and never reads or writes `supabase/.temp`: Storage uploads live in `stacks//uploads`, command scratch output (pgdelta debug bundles, Functions bundling) in `tmp`, the release-check cache in `cli-latest`, and service versions come from @@ -449,15 +463,17 @@ unaffected by the flag either way. Under the stack backend, local Storage operations resolve their endpoint and credential from the selected composition rather than `[api]`/`[api.tls]`: the endpoint is the Storage member's -observed HTTP binding plus `/storage/v1/...`, and the service-role JWT is generated from the -primary database member's observed JWT secret. The stack is located by the project root -(workdir realpath) through the `@supabase/stack` API, which reads stack state under -`SUPABASE_HOME`. +observed HTTP binding plus `/storage/v1/...`, and the service-role JWT is the one the stack saved +with its credentials. The stack is located by the project root (workdir realpath) through the +`@supabase/stack` API, which reads stack state under `SUPABASE_HOME`. A stack started with +`[api.tls]` serves that endpoint over HTTPS, and Storage uses the certificate saved at start, +not `config.toml`: a saved certificate with a self-signed root is the only trusted CA; a CA-issued +one is verified against Bun's default trust store and `NODE_EXTRA_CA_CERTS`. Neither `storage` nor `seed buckets` ever creates a stack; the legacy `[api]` port/external-URL/TLS fields, their `SUPABASE_API_*` overrides, `SUPABASE_AUTH_JWT_SECRET`/ -`SUPABASE_AUTH_SERVICE_ROLE_KEY`, `SUPABASE_SERVICES_HOSTNAME`, the Docker daemon hostname, and -the embedded Kong CA are all legacy-backend only and are not consulted on this path. The -service-role JWT is never printed or logged. +`SUPABASE_AUTH_SERVICE_ROLE_KEY`, `SUPABASE_SERVICES_HOSTNAME` and the Docker daemon hostname are +legacy-backend only and are not consulted on this path. The service-role JWT is never printed or +logged. Storage's capability state gates these operations: @@ -489,8 +505,9 @@ states are observed directly by Storage operations, including `stack start`. **`stack start` seeds on first configured start.** When a `stack start` (or the top-level `start` under the flag) invocation runs the stack's first configured start (never when it resumes an existing one) and -Storage is not `disabled`, it seeds `[storage.buckets]` against the stack before printing status, -reusing the `seed buckets` core. A project with no `[storage.buckets]` or +Storage is not `disabled`, it seeds `[storage.buckets]` and, while `storage.vector.enabled`, +`[storage.vector.buckets]` against the stack before printing status, reusing the `seed buckets` +core. A project with no `[storage.buckets]` or `[storage.vector.buckets]` configured resolves no credentials and prints nothing. Auto-confirm is safe here since a first-start stack has no pre-existing buckets. Any other unusable Storage state, a missing capability/endpoint, a gateway activation failure, or an invalid bucket entry fails the diff --git a/apps/cli/docs/supabase/config/convert.md b/apps/cli/docs/supabase/config/convert.md new file mode 100644 index 0000000000..b7557fb070 --- /dev/null +++ b/apps/cli/docs/supabase/config/convert.md @@ -0,0 +1,39 @@ +# supabase-config-convert + +Converts `supabase/config.toml` to `supabase/config.jsonc` and moves the TOML file to `supabase/config.toml.bak`. Comments are carried over as `//` comments and the document gets a `$schema` entry, so editors validate it against the hosted config schema. + +The conversion reads the file as written: values keep their meaning, `env(NAME)` references are copied as text, and nothing is resolved from your environment. Numbers are written in JSON form, so `0x1F` becomes `31` and `1_000` becomes `1000`. The converted document is parsed again and compared with the original before anything is written; if the two differ, the file is not valid UTF-8, or it holds a value JSON cannot represent (a TOML date, `inf` or `nan`), the command refuses and leaves `config.toml` untouched. + +Comments keep their place by these rules: a comment directly above a key or table leads it; a comment block directly below a key or table, followed by a blank line or another table, trails it; a comment block with blank lines on both sides leads the next entry, or the commented-out example that follows it; a comment on the same line as a key or table header stays on that line. Comments inside a multi-line array of plain values stay beside their elements. Comments inside nested arrays or inline tables cannot be placed, so this command does not keep them in place: they move to the line above their key and the command lists each one. + +Commented-out TOML examples become commented-out JSONC members, so removing the `//` from one member gives valid JSONC. A commented `# key = value` stays in the object it follows as `// "key": value,`. A commented table (`# [auth.hook.custom_access_token]` and the keys under it) is written as a commented object inside the nearest enclosing table that exists, merged with other examples under the same missing parent, and moves with the comment lines directly above it; it sits before the first later-defined entry of that table, or at the end of the table when none follows. Comments that do not parse as a single TOML key or table header stay as plain `//` comments. + +Two kinds of commented example are copied as plain comments or need care when uncommented. Examples inside an array of tables (`[[name]]`, commented or not) stay as plain `//` comments. When a table lists alternative values for the same key (`# key = "a"` then `# key = "b"`), both become commented members, so uncomment only one of them. + +`--dry-run` prints the converted document to stdout and writes nothing. If the project has `.vscode/settings.json`, the command also adds the schema domain to `json.schemaDownload.trustedDomains` there, keeping its comments; the file is never created. + +Everyone on the project needs Supabase CLI 3.1.0 or later: older CLIs ignore `config.jsonc` and run with defaults. The command ends with a summary of the files it created, moved and updated, any relocated comments, this compatibility note and the undo command; with `--dry-run` the same summary, as a preview, goes to stderr. + +If only `supabase/config.json` or `supabase/config.jsonc` exists, the command reports that there is nothing to convert and exits 0. It fails when `config.toml` and a JSON config both exist, because the JSON file takes precedence; delete it first to convert `config.toml` again. The legacy global `-o`/`--output` flag is not supported; use `--output-format json|stream-json` for a machine-readable result. + +## Undo + +Move the backup back and remove the JSONC file: + +```sh +mv -- supabase/config.toml.bak supabase/config.toml && rm -- supabase/config.jsonc +``` + +If a backup from an earlier conversion already exists, the command uses the next free name (`config.toml.2.bak`, and so on). The printed undo command names that backup, with paths relative to the directory you ran the command from; on Windows it is the PowerShell equivalent. + +## After converting + +- Delete `supabase/config.toml.bak` once you no longer need the undo, so it is not committed. It stays outside `supabase/.temp` because `supabase unlink` and `supabase projects delete` remove that directory. +- Commit the conversion on its own. The history of the old file stays available with `git log -- supabase/config.toml`. +- Search the repository, CI workflows and Dockerfiles for `config.toml` and update any references. +- Bump pinned Supabase CLI versions (for example `supabase/setup-cli`) to 3.1.0 or later. + +```sh +supabase config convert --dry-run +supabase config convert +``` diff --git a/apps/cli/docs/tracing-monitoring.md b/apps/cli/docs/tracing-monitoring.md index c42cee4b1e..4668a5f7c3 100644 --- a/apps/cli/docs/tracing-monitoring.md +++ b/apps/cli/docs/tracing-monitoring.md @@ -194,12 +194,12 @@ the timing ranges, API calls per command, and the slowest phases. It reports: The baseline API calls per workload on `develop` (a project-scoped command also refreshes the linked-project cache, so it makes two calls): -| Workload | API calls | -| ------------------------------------------ | ---------------------------------------------------------------------- | -| `version`, `help`, `init`, `migration-new` | 0 | -| `projects-list` | 1: `GET /v1/projects` | -| `gen-types` | 2: `GET /v1/projects/{ref}/types/typescript`, `GET /v1/projects/{ref}` | -| `functions-list` | 2: `GET /v1/projects/{ref}/functions`, `GET /v1/projects/{ref}` | +| Workload | API calls | +| ------------------------------------------------------------ | ---------------------------------------------------------------------- | +| `version`, `help`, `init`, `migration-new`, `config-convert` | 0 | +| `projects-list` | 1: `GET /v1/projects` | +| `gen-types` | 2: `GET /v1/projects/{ref}/types/typescript`, `GET /v1/projects/{ref}` | +| `functions-list` | 2: `GET /v1/projects/{ref}/functions`, `GET /v1/projects/{ref}` | `SUPABASE_NO_KEYRING=1` disables the keyring (`CommandCredentials.load` reports `keyring.enabled=false`); the value `true` is not recognized. Counts come from the untimed traced diff --git a/apps/cli/package.json b/apps/cli/package.json index 6f2dda5d0e..e62e898d83 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -60,7 +60,7 @@ "@supabase/pg-topo": "1.0.0-alpha.8", "@supabase/stack": "workspace:*", "@supabase/supabase-js": "catalog:", - "@supabase/typegen": "0.3.2", + "@supabase/typegen": "0.3.4", "@tsconfig/bun": "catalog:", "@types/bun": "catalog:", "@types/pg": "^8.23.1", diff --git a/apps/cli/src/cli/main.e2e.test.ts b/apps/cli/src/cli/main.e2e.test.ts index 545f989f98..761778ef43 100644 --- a/apps/cli/src/cli/main.e2e.test.ts +++ b/apps/cli/src/cli/main.e2e.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "@effect/vitest"; -import { Effect } from "effect"; +import { Effect, Schema } from "effect"; import { runSupabaseEffect, withTempCliProject, withTempHome } from "../../tests/helpers/cli.ts"; describe("CLI feature routing", () => { @@ -25,4 +25,38 @@ describe("CLI feature routing", () => { ), ), ); + + it.live("names the stack opt-in when the legacy backend rejects a stack-only flag", () => + withTempHome((home) => + withTempCliProject("supabase-main-routing-e2e-", (project) => + Effect.gen(function* () { + const options = { + cwd: project.dir, + home: home.dir, + env: { SUPABASE_EXPERIMENTAL_STACK: undefined, SUPABASE_WORKDIR: undefined }, + }; + const hint = + "Hint: --runtime needs the stack backend. Set SUPABASE_EXPERIMENTAL_STACK=1, or set stack = true under [experimental] in your project config and leave SUPABASE_EXPERIMENTAL_STACK unset."; + + const text = yield* runSupabaseEffect(["start", "--runtime", "native"], options); + expect(text.exitCode).toBe(1); + expect(text.stderr).toContain("Unrecognized flag: --runtime"); + expect(text.stderr).toContain(hint); + + const json = yield* runSupabaseEffect( + ["start", "--runtime", "native", "--output-format", "json"], + options, + ); + expect(json.exitCode).toBe(1); + const envelope = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Unknown))( + json.stdout, + ); + expect(envelope).toMatchObject({ + _tag: "Error", + error: { code: "UnrecognizedOption", message: expect.stringContaining(hint) }, + }); + }), + ), + ), + ); }); diff --git a/apps/cli/src/cli/main.ts b/apps/cli/src/cli/main.ts index 4198aeed5a..4e7a099358 100644 --- a/apps/cli/src/cli/main.ts +++ b/apps/cli/src/cli/main.ts @@ -9,7 +9,7 @@ import { defaultCompleteDeps, tryComplete } from "./complete.ts"; import { resolveProjectStateSelection } from "../command-internal/stack-backend.ts"; import { resolveComputeEnabled } from "../commands/experimental/compute/compute-backend.ts"; import { cliConfigProviderLayer } from "../shared/config/cli-config-provider.layer.ts"; -import { cliEntrypointForFeatures } from "./root.ts"; +import { cliEntrypointForFeatures, rootCommandForFeatures } from "./root.ts"; const args = await Effect.runPromise( Effect.gen(function* () { @@ -31,12 +31,17 @@ const selectionExit = await Effect.runPromiseExit( return { projectState, stackBackend, computeEnabled }; }).pipe(Effect.provide(Layer.mergeAll(BunServices.layer, cliConfigProviderLayer))), ); +const selectedFeatures = Exit.isSuccess(selectionExit) + ? selectionExit.value + : ({ stackBackend: "legacy", computeEnabled: false } as const); const { rootCommand: selectedRoot, agentDefaultOutputFormat } = cliEntrypointForFeatures( - Exit.isSuccess(selectionExit) - ? selectionExit.value - : { stackBackend: "legacy", computeEnabled: false }, + selectedFeatures, args, ); +const stackRootCommand = + selectedFeatures.stackBackend === "stack" + ? undefined + : rootCommandForFeatures({ ...selectedFeatures, stackBackend: "stack" }); const selectionCause = Exit.isFailure(selectionExit) ? selectionExit.cause : undefined; const selectedProjectState = Exit.isSuccess(selectionExit) ? selectionExit.value.projectState @@ -63,6 +68,7 @@ if ( : "legacy", ).pipe(Layer.provide(FetchHttpClient.layer)), agentDefaultOutputFormat, + ...(stackRootCommand ? { stackRootCommand } : {}), afterSuccess: upgradeNoticeHook, ...(selectionCause ? { beforeParse: Effect.failCause(selectionCause) } : {}), }), diff --git a/apps/cli/src/cli/stack-flag-opt-in-hint.integration.test.ts b/apps/cli/src/cli/stack-flag-opt-in-hint.integration.test.ts new file mode 100644 index 0000000000..047cb31bd6 --- /dev/null +++ b/apps/cli/src/cli/stack-flag-opt-in-hint.integration.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, it } from "@effect/vitest"; +import { Console, Effect, Exit, Layer } from "effect"; +import { CliOutput, Command } from "effect/cli"; +import { emptyEnv, fakeConsole, mockOutput } from "../../tests/helpers/mocks.ts"; +import { CliArgs } from "../shared/cli/cli-args.service.ts"; +import { withoutParseErrorHelpDump } from "../shared/cli/run.ts"; +import { normalizeCause } from "../shared/output/normalize-error.ts"; +import { textCliOutputFormatter } from "../shared/output/text-formatter.ts"; +import { rootCommandForFeatures } from "./root.ts"; + +const legacyRoot = rootCommandForFeatures({ stackBackend: "legacy" }); +const stackRoot = rootCommandForFeatures({ stackBackend: "stack" }); + +type Root = typeof legacyRoot; + +const optInAdvice = + "Set SUPABASE_EXPERIMENTAL_STACK=1, or set stack = true under [experimental] in your project config and leave SUPABASE_EXPERIMENTAL_STACK unset."; + +/** Parses `args` against `root` and returns the normalized failure message `runCli` reports. */ +const parse = ( + root: Root, + args: ReadonlyArray, + options: { readonly stackRoot?: Root } = {}, +) => + Effect.gen(function* () { + const context = { + rootCommand: root, + args, + ...(options.stackRoot ? { stackRootCommand: options.stackRoot } : {}), + }; + const exit = yield* withoutParseErrorHelpDump( + Command.runWith(root, { version: "0.0.0-test" })(args), + context, + ).pipe( + Effect.provide( + Layer.mergeAll( + emptyEnv(), + CliOutput.layer(textCliOutputFormatter(context)), + Layer.succeed(CliArgs, { args }), + Layer.succeed(Console.Console, fakeConsole().console), + mockOutput({ format: "text" }).layer, + ), + ), + Effect.exit, + ); + if (Exit.isSuccess(exit)) return { failed: false, message: "" }; + return { failed: true, message: normalizeCause(exit.cause, context).message }; + }); + +describe("stack-only flags rejected by the legacy backend", () => { + const stackOnlyInvocations: ReadonlyArray> = [ + ["start", "--runtime", "native"], + ["start", "--stack", "feature-a"], + ["start", "--stack-id", "feature-a"], + ["start", "--preparation", "frozen"], + ["start", "--frozen"], + ["start", "--eager"], + ["stop", "--stack", "feature-a"], + ["status", "--stack", "feature-a"], + ]; + + for (const args of stackOnlyInvocations) { + const [command, flag] = args; + it.effect(`\`${command} ${flag}\` names the stack opt-in`, () => + Effect.gen(function* () { + const result = yield* parse(legacyRoot, args, { stackRoot }); + expect(result.failed).toBe(true); + expect(result.message).toContain(`Unrecognized flag: ${flag}`); + expect(result.message).toContain(`Hint: ${flag} needs the stack backend. ${optInAdvice}`); + }), + ); + } + + it.effect("adds no hint for a flag neither backend accepts", () => + Effect.gen(function* () { + const { message } = yield* parse(legacyRoot, ["start", "--bogus"], { stackRoot }); + expect(message).toContain("Unrecognized flag: --bogus"); + expect(message).not.toContain("Hint:"); + }), + ); + + it.effect("adds no hint when the stack opt-in is not offered", () => + Effect.gen(function* () { + const { message } = yield* parse(legacyRoot, ["start", "--runtime", "native"]); + expect(message).toContain("Unrecognized flag: --runtime"); + expect(message).not.toContain("Hint:"); + }), + ); + + it.effect("the stack backend's own start recognizes the flag", () => + Effect.gen(function* () { + const result = yield* parse(stackRoot, ["start", "--runtime", "bogus"]); + expect(result.failed).toBe(true); + expect(result.message).toContain('Invalid value for flag --runtime: "bogus"'); + }), + ); +}); diff --git a/apps/cli/src/command-internal/config-validate.parity.unit.test.ts b/apps/cli/src/command-internal/config-validate.parity.unit.test.ts index 0a8ea60460..26b1b2b95b 100644 --- a/apps/cli/src/command-internal/config-validate.parity.unit.test.ts +++ b/apps/cli/src/command-internal/config-validate.parity.unit.test.ts @@ -139,6 +139,13 @@ const scenarios: ReadonlyArray = [ overrides: { db: { major_version: 0 } }, message: "Missing required field in config: db.major_version", }, + { + name: "db.major_version unsupported (13)", + toml: ["[db]", "major_version = 13"], + overrides: { db: { major_version: 13 } }, + message: + "Postgres version 13.x is unsupported. To use the CLI, upgrade your project to Postgres 17, then set db.major_version = 17 in your project config: https://supabase.com/docs/guides/platform/upgrading.", + }, { name: "db.major_version unsupported (16)", toml: ["[db]", "major_version = 16"], diff --git a/apps/cli/src/command-internal/config-validate.ts b/apps/cli/src/command-internal/config-validate.ts index a525f82a81..cf0e39a20a 100644 --- a/apps/cli/src/command-internal/config-validate.ts +++ b/apps/cli/src/command-internal/config-validate.ts @@ -289,7 +289,12 @@ export function validateResolvedConfig(input: ConfigValidationInput): void { "Postgres version 12.x is unsupported. To use the CLI, either start a new project or follow project migration steps here: https://supabase.com/docs/guides/database#migrating-between-projects.", ); } - if (![13, 14, 15, 17].includes(input.db.majorVersion)) { + if (input.db.majorVersion === 13) { + throw new ConfigValidateError( + "Postgres version 13.x is unsupported. To use the CLI, upgrade your project to Postgres 17, then set db.major_version = 17 in your project config: https://supabase.com/docs/guides/platform/upgrading.", + ); + } + if (![14, 15, 17].includes(input.db.majorVersion)) { throw new ConfigValidateError( `Failed reading config: Invalid db.major_version: ${input.db.majorVersion}.`, ); @@ -738,6 +743,11 @@ export function apiTlsKeyReadErrorMessage(cause: unknown): string { return `failed to read TLS key: ${messageOf(cause)}`; } +/** `Invalid config for api.tls: failed to load TLS key pair from ${cert} and ${key}: ${msg(cause)}` */ +export function apiTlsPairErrorMessage(certPath: string, keyPath: string, cause: unknown): string { + return `Invalid config for api.tls: failed to load TLS key pair from ${certPath} and ${keyPath}: ${messageOf(cause)}`; +} + /** * Validates only the first enabled provider in the fixed priority order; a later * enabled-but-incomplete provider is never checked. diff --git a/apps/cli/src/command-internal/config-validate.unit.test.ts b/apps/cli/src/command-internal/config-validate.unit.test.ts index 405a13d0e3..60f0ae0e27 100644 --- a/apps/cli/src/command-internal/config-validate.unit.test.ts +++ b/apps/cli/src/command-internal/config-validate.unit.test.ts @@ -550,7 +550,13 @@ describe("validateResolvedConfig", () => { ).toThrow("Postgres version 12.x is unsupported."); }); - it.each([13, 14, 15, 17])("accepts the supported major_version %d", (majorVersion) => { + it("rejects the unsupported Postgres 13.x major_version with its dedicated message", () => { + expect(() => + validateResolvedConfig(minimalInput({ db: { port: 5432, majorVersion: 13 } })), + ).toThrow("Postgres version 13.x is unsupported."); + }); + + it.each([14, 15, 17])("accepts the supported major_version %d", (majorVersion) => { expect(() => validateResolvedConfig(minimalInput({ db: { port: 5432, majorVersion } })), ).not.toThrow(); diff --git a/apps/cli/src/command-internal/db-bootstrap/db-setup.ts b/apps/cli/src/command-internal/db-bootstrap/db-setup.ts index b3f5fccbe1..860d221030 100644 --- a/apps/cli/src/command-internal/db-bootstrap/db-setup.ts +++ b/apps/cli/src/command-internal/db-bootstrap/db-setup.ts @@ -45,7 +45,6 @@ import { resolvePinnedImage } from "./pinned-image.ts"; import { COMPOSE_PROJECT_LABEL } from "./container-lifecycle.ts"; import { REALTIME_TENANT_ID, buildRealtimeEnv } from "./realtime-env.ts"; import { START_DB_GLOBALS_SQL } from "./templates/db-globals.sql.ts"; -import { START_DB_INITIAL_SCHEMA_13_SQL } from "./templates/db-initial-schema-13.sql.ts"; import { START_DB_INITIAL_SCHEMA_14_SQL } from "./templates/db-initial-schema-14.sql.ts"; import { STACK_DB_WEBHOOK_SQL } from "./templates/db-webhook.sql.ts"; import { startInternalDbPassword, startInternalDbUrl } from "./internal-db-connection.ts"; @@ -169,7 +168,7 @@ function resolveDbSetupImages( * * The banner prints before `jwks` resolves, so a JWKS failure (an unreachable `third_party` * provider) surfaces after the banner instead of before it. The `majorVersion >= 15` gate means - * JWKS's potential live HTTP request never runs at all on PG13/14, even with realtime enabled. + * JWKS's potential live HTTP request never runs at all on PG14, even with realtime enabled. */ export const resolveDbSetupPrelude = (setup: { readonly majorVersion: number; @@ -207,7 +206,7 @@ export interface SetupDatabaseInput { readonly config: CliConfig; /** Effective `[experimental.webhooks].enabled`, including supported environment overrides. */ readonly webhooksEnabled: boolean; - /** `db.major_version` (13-17), resolved by the caller once, ahead of the `db` container's own image tag selection. */ + /** `db.major_version` (14-17), resolved by the caller once, ahead of the `db` container's own image tag selection. */ readonly majorVersion: number; /** * The internal Docker-network address the PG15+ one-shot jobs connect through. The real local @@ -338,11 +337,15 @@ export const initSchema14 = Effect.fnUntraced(function* ( fs: FileSystem.FileSystem, path: Path.Path, tmpDir: string, - majorVersion: number, ) { - const schemaSql = - majorVersion === 13 ? START_DB_INITIAL_SCHEMA_13_SQL : START_DB_INITIAL_SCHEMA_14_SQL; - yield* execSqlConstant(session, fs, path, tmpDir, "initial-schema.sql", schemaSql); + yield* execSqlConstant( + session, + fs, + path, + tmpDir, + "initial-schema.sql", + START_DB_INITIAL_SCHEMA_14_SQL, + ); }); /** @@ -355,10 +358,9 @@ const startInitSchemaPre15 = Effect.fnUntraced(function* ( fs: FileSystem.FileSystem, path: Path.Path, tmpDir: string, - majorVersion: number, ) { yield* execSqlConstant(session, fs, path, tmpDir, "globals.sql", START_DB_GLOBALS_SQL); - yield* initSchema14(session, fs, path, tmpDir, majorVersion); + yield* initSchema14(session, fs, path, tmpDir); }); /** @@ -581,7 +583,7 @@ const startInitSchema = Effect.fn("DbSetup.initSchema")(function* ( ) { yield* Effect.annotateCurrentSpan("db.major_version", input.majorVersion); if (input.majorVersion <= 14) { - yield* startInitSchemaPre15(input.session, input.fs, input.path, tmpDir, input.majorVersion); + yield* startInitSchemaPre15(input.session, input.fs, input.path, tmpDir); return; } yield* startInitSchema15(spawner, input); diff --git a/apps/cli/src/command-internal/db-bootstrap/db-setup.unit.test.ts b/apps/cli/src/command-internal/db-bootstrap/db-setup.unit.test.ts index f785d197b3..ae53ffefe0 100644 --- a/apps/cli/src/command-internal/db-bootstrap/db-setup.unit.test.ts +++ b/apps/cli/src/command-internal/db-bootstrap/db-setup.unit.test.ts @@ -39,13 +39,11 @@ const decodeConfig = Schema.decodeUnknownSync(CliConfigSchema); * Fingerprints unique to each transcribed SQL constant, with no trailing `;` (`splitAndTrim` * strips it before `session.exec` sees it). * - * `GLOBALS`/`SCHEMA_13`/`REVOKE_PRIVILEGES` are checked as substrings, since each is embedded in + * `GLOBALS`/`REVOKE_PRIVILEGES` are checked as substrings, since each is embedded in * a larger executed block. `SCHEMA_14` is checked with `.endsWith` instead: a substring check * would also match 14.sql's unrelated `graphql_public` schema statement. */ const GLOBALS_FINGERPRINT = "CREATE ROLE anon"; -const SCHEMA_13_FINGERPRINT = - "CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION"; const SCHEMA_14_FINGERPRINT_SUFFIX = "CREATE SCHEMA IF NOT EXISTS graphql"; const REVOKE_PRIVILEGES_FINGERPRINT = "revoke execute on functions from anon, authenticated, service_role"; @@ -249,24 +247,6 @@ describe("startSetupLocalDatabase", () => { const execSql = calls.filter((c) => c.kind === "exec").map((c) => c.sql); expect(execSql.some((sql) => sql.includes(GLOBALS_FINGERPRINT))).toBe(true); expect(execSql.some((sql) => sql.endsWith(SCHEMA_14_FINGERPRINT_SUFFIX))).toBe(true); - expect(execSql.some((sql) => sql.includes(SCHEMA_13_FINGERPRINT))).toBe(false); - expect(docker.runs.length).toBe(0); - yield* fs.remove(workdir, { recursive: true, force: true }); - }).pipe(Effect.provide(BunServices.layer)); - }); - - it.effect("PG13: execs globals + the PG13 initial schema, not the PG14 one", () => { - return Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const workdir = yield* makeWorkdir(); - const { session, calls } = fakeSession(); - const out = mockOutput(); - const docker = mockDockerRun(); - yield* run(baseInput(workdir, session, { majorVersion: 13 }), out, docker); - const execSql = calls.filter((c) => c.kind === "exec").map((c) => c.sql); - expect(execSql.some((sql) => sql.includes(GLOBALS_FINGERPRINT))).toBe(true); - expect(execSql.some((sql) => sql.includes(SCHEMA_13_FINGERPRINT))).toBe(true); - expect(execSql.some((sql) => sql.endsWith(SCHEMA_14_FINGERPRINT_SUFFIX))).toBe(false); expect(docker.runs.length).toBe(0); yield* fs.remove(workdir, { recursive: true, force: true }); }).pipe(Effect.provide(BunServices.layer)); @@ -282,7 +262,6 @@ describe("startSetupLocalDatabase", () => { yield* run(baseInput(workdir, session, { majorVersion: 17 }), out, docker); const execSql = calls.filter((c) => c.kind === "exec").map((c) => c.sql); expect(execSql.some((sql) => sql.includes(GLOBALS_FINGERPRINT))).toBe(false); - expect(execSql.some((sql) => sql.includes(SCHEMA_13_FINGERPRINT))).toBe(false); expect(execSql.some((sql) => sql.endsWith(SCHEMA_14_FINGERPRINT_SUFFIX))).toBe(false); // Default config: realtime, storage, and auth are all enabled. expect(docker.runs.length).toBe(3); diff --git a/apps/cli/src/command-internal/db-bootstrap/recreate-local-database.ts b/apps/cli/src/command-internal/db-bootstrap/recreate-local-database.ts index 6d18a459c3..fa5111678c 100644 --- a/apps/cli/src/command-internal/db-bootstrap/recreate-local-database.ts +++ b/apps/cli/src/command-internal/db-bootstrap/recreate-local-database.ts @@ -407,7 +407,7 @@ const recreateLocalDatabase14 = ( }), ), ); - yield* initSchema14(session, fs, path, tmpDir, setup.majorVersion); + yield* initSchema14(session, fs, path, tmpDir); // Same drop-then-conditionally-recreate sequence fresh setup runs // (`db-setup.ts`'s `requiresPg14WebhooksCleanup`): the PG14 dump installs pg_net // unconditionally, so without this drop a reset with webhooks disabled would leave diff --git a/apps/cli/src/command-internal/db-bootstrap/start-local-database.ts b/apps/cli/src/command-internal/db-bootstrap/start-local-database.ts index 082fdb4ea6..0fb4803991 100644 --- a/apps/cli/src/command-internal/db-bootstrap/start-local-database.ts +++ b/apps/cli/src/command-internal/db-bootstrap/start-local-database.ts @@ -35,6 +35,7 @@ import { buildLocalDbContainerInputs } from "./local-container-inputs.ts"; import { removeContainer } from "./container-lifecycle.ts"; import { awaitDockerHealthSettled } from "./health-check.ts"; import { localDbState } from "./local-db-running.ts"; +import { warnIfPostgres14Deprecated } from "../db-image.ts"; import { rollbackDatabaseStart } from "./rollback.ts"; import { backupVolumeExistsError, startDatabase } from "./start-database.ts"; @@ -119,6 +120,7 @@ const startLocalDatabaseInScope = Effect.fn("DbBootstrap.startLocalDatabase")(fu ) { yield* output.raw("WARN: no SMS provider is enabled. Disabling phone login\n", "stderr"); } + yield* warnIfPostgres14Deprecated(config.db.major_version); const { timebox, inactivity_timeout: inactivityTimeout } = config.auth.sessions ?? {}; if (timebox !== undefined) { yield* wrapDbConfigParse("auth.sessions.timebox", () => parseDuration(timebox)); diff --git a/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-13.sql.ts b/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-13.sql.ts deleted file mode 100644 index 513bfe0054..0000000000 --- a/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-13.sql.ts +++ /dev/null @@ -1,3099 +0,0 @@ -/** - * Baseline SQL run via `ExecBatch` against a fresh `db.major_version == 13` local database, - * right after {@link START_DB_GLOBALS_SQL}. - */ -export const START_DB_INITIAL_SCHEMA_13_SQL = `-- --- PostgreSQL database dump --- - --- Dumped from database version 13.3 (Debian 13.3-1.pgdg100+1) --- Dumped by pg_dump version 15.3 - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - --- --- Name: _analytics; Type: SCHEMA; Schema: -; Owner: postgres --- - -CREATE SCHEMA IF NOT EXISTS _analytics; - - -ALTER SCHEMA _analytics OWNER TO postgres; - --- --- Name: _realtime; Type: SCHEMA; Schema: -; Owner: postgres --- - -CREATE SCHEMA IF NOT EXISTS _realtime; - - -ALTER SCHEMA _realtime OWNER TO postgres; - --- --- Name: auth; Type: SCHEMA; Schema: -; Owner: supabase_admin --- - -CREATE SCHEMA IF NOT EXISTS auth; - - -ALTER SCHEMA auth OWNER TO supabase_admin; - --- --- Name: extensions; Type: SCHEMA; Schema: -; Owner: postgres --- - -CREATE SCHEMA IF NOT EXISTS extensions; - - -ALTER SCHEMA extensions OWNER TO postgres; - --- --- Name: graphql_public; Type: SCHEMA; Schema: -; Owner: supabase_admin --- - -CREATE SCHEMA IF NOT EXISTS graphql_public; - - -ALTER SCHEMA graphql_public OWNER TO supabase_admin; - --- --- Name: public; Type: SCHEMA; Schema: -; Owner: postgres --- - --- *not* creating schema, since initdb creates it - - -ALTER SCHEMA public OWNER TO postgres; - --- --- Name: realtime; Type: SCHEMA; Schema: -; Owner: supabase_admin --- - -CREATE SCHEMA IF NOT EXISTS realtime; - - -ALTER SCHEMA realtime OWNER TO supabase_admin; - --- --- Name: storage; Type: SCHEMA; Schema: -; Owner: supabase_admin --- - -CREATE SCHEMA IF NOT EXISTS storage; - - -ALTER SCHEMA storage OWNER TO supabase_admin; - --- --- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions; - - --- --- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions'; - - --- --- Name: pgjwt; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS pgjwt WITH SCHEMA extensions; - - --- --- Name: EXTENSION pgjwt; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION pgjwt IS 'JSON Web Token API for Postgresql'; - - --- --- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: - --- - -CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA extensions; - - --- --- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: --- - -COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)'; - - --- --- Name: aal_level; Type: TYPE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TYPE auth.aal_level AS ENUM ( - 'aal1', - 'aal2', - 'aal3' -); - - -ALTER TYPE auth.aal_level OWNER TO supabase_auth_admin; - --- --- Name: code_challenge_method; Type: TYPE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TYPE auth.code_challenge_method AS ENUM ( - 's256', - 'plain' -); - - -ALTER TYPE auth.code_challenge_method OWNER TO supabase_auth_admin; - --- --- Name: factor_status; Type: TYPE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TYPE auth.factor_status AS ENUM ( - 'unverified', - 'verified' -); - - -ALTER TYPE auth.factor_status OWNER TO supabase_auth_admin; - --- --- Name: factor_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TYPE auth.factor_type AS ENUM ( - 'totp', - 'webauthn' -); - - -ALTER TYPE auth.factor_type OWNER TO supabase_auth_admin; - --- --- Name: email(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin --- - -CREATE OR REPLACE FUNCTION auth.email() RETURNS text - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim.email', true), ''), - (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email') - )::text -$$; - - -ALTER FUNCTION auth.email() OWNER TO supabase_auth_admin; - --- --- Name: FUNCTION email(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON FUNCTION auth.email() IS 'Deprecated. Use auth.jwt() -> ''email'' instead.'; - - --- --- Name: jwt(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin --- - -CREATE OR REPLACE FUNCTION auth.jwt() RETURNS jsonb - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim', true), ''), - nullif(current_setting('request.jwt.claims', true), '') - )::jsonb -$$; - - -ALTER FUNCTION auth.jwt() OWNER TO supabase_auth_admin; - --- --- Name: role(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin --- - -CREATE OR REPLACE FUNCTION auth.role() RETURNS text - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim.role', true), ''), - (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'role') - )::text -$$; - - -ALTER FUNCTION auth.role() OWNER TO supabase_auth_admin; - --- --- Name: FUNCTION role(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON FUNCTION auth.role() IS 'Deprecated. Use auth.jwt() -> ''role'' instead.'; - - --- --- Name: uid(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin --- - -CREATE OR REPLACE FUNCTION auth.uid() RETURNS uuid - LANGUAGE sql STABLE - AS $$ - select - coalesce( - nullif(current_setting('request.jwt.claim.sub', true), ''), - (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub') - )::uuid -$$; - - -ALTER FUNCTION auth.uid() OWNER TO supabase_auth_admin; - --- --- Name: FUNCTION uid(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON FUNCTION auth.uid() IS 'Deprecated. Use auth.jwt() -> ''sub'' instead.'; - - --- --- Name: grant_pg_cron_access(); Type: FUNCTION; Schema: extensions; Owner: postgres --- - -CREATE OR REPLACE FUNCTION extensions.grant_pg_cron_access() RETURNS event_trigger - LANGUAGE plpgsql - AS $$ -DECLARE - schema_is_cron bool; -BEGIN - schema_is_cron = ( - SELECT n.nspname = 'cron' - FROM pg_event_trigger_ddl_commands() AS ev - LEFT JOIN pg_catalog.pg_namespace AS n - ON ev.objid = n.oid - ); - - IF schema_is_cron - THEN - grant usage on schema cron to postgres with grant option; - - alter default privileges in schema cron grant all on tables to postgres with grant option; - alter default privileges in schema cron grant all on functions to postgres with grant option; - alter default privileges in schema cron grant all on sequences to postgres with grant option; - - alter default privileges for user supabase_admin in schema cron grant all - on sequences to postgres with grant option; - alter default privileges for user supabase_admin in schema cron grant all - on tables to postgres with grant option; - alter default privileges for user supabase_admin in schema cron grant all - on functions to postgres with grant option; - - grant all privileges on all tables in schema cron to postgres with grant option; - - END IF; - -END; -$$; - - -ALTER FUNCTION extensions.grant_pg_cron_access() OWNER TO postgres; - --- --- Name: FUNCTION grant_pg_cron_access(); Type: COMMENT; Schema: extensions; Owner: postgres --- - -COMMENT ON FUNCTION extensions.grant_pg_cron_access() IS 'Grants access to pg_cron'; - - --- --- Name: grant_pg_graphql_access(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin --- - -CREATE OR REPLACE FUNCTION extensions.grant_pg_graphql_access() RETURNS event_trigger - LANGUAGE plpgsql - AS $_$ -DECLARE - func_is_graphql_resolve bool; -BEGIN - func_is_graphql_resolve = ( - SELECT n.proname = 'resolve' - FROM pg_event_trigger_ddl_commands() AS ev - LEFT JOIN pg_catalog.pg_proc AS n - ON ev.objid = n.oid - ); - - IF func_is_graphql_resolve - THEN - - -- Update public wrapper to pass all arguments through to the pg_graphql resolve func - create or replace function graphql_public.graphql( - "operationName" text default null, - query text default null, - variables jsonb default null, - extensions jsonb default null - ) - returns jsonb - language sql - as $$ - select graphql.resolve( - query := query, - variables := coalesce(variables, '{}'), - "operationName" := "operationName", - extensions := extensions - ); - $$; - - -- This hook executes when \`graphql.resolve\` is created. That is not necessarily the last - -- function in the extension so we need to grant permissions on existing entities AND - -- update default permissions to any others that are created after \`graphql.resolve\` - grant usage on schema graphql to postgres, anon, authenticated, service_role; - grant select on all tables in schema graphql to postgres, anon, authenticated, service_role; - grant execute on all functions in schema graphql to postgres, anon, authenticated, service_role; - grant all on all sequences in schema graphql to postgres, anon, authenticated, service_role; - alter default privileges in schema graphql grant all on tables to postgres, anon, authenticated, service_role; - alter default privileges in schema graphql grant all on functions to postgres, anon, authenticated, service_role; - alter default privileges in schema graphql grant all on sequences to postgres, anon, authenticated, service_role; - END IF; - -END; -$_$; - - -ALTER FUNCTION extensions.grant_pg_graphql_access() OWNER TO supabase_admin; - --- --- Name: FUNCTION grant_pg_graphql_access(); Type: COMMENT; Schema: extensions; Owner: supabase_admin --- - -COMMENT ON FUNCTION extensions.grant_pg_graphql_access() IS 'Grants access to pg_graphql'; - - --- --- Name: grant_pg_net_access(); Type: FUNCTION; Schema: extensions; Owner: postgres --- - -CREATE OR REPLACE FUNCTION extensions.grant_pg_net_access() RETURNS event_trigger - LANGUAGE plpgsql - AS $$ -BEGIN - IF EXISTS ( - SELECT 1 - FROM pg_event_trigger_ddl_commands() AS ev - JOIN pg_extension AS ext - ON ev.objid = ext.oid - WHERE ext.extname = 'pg_net' - ) - THEN - IF NOT EXISTS ( - SELECT 1 - FROM pg_roles - WHERE rolname = 'supabase_functions_admin' - ) - THEN - CREATE USER supabase_functions_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION; - END IF; - - GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role; - - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER; - ALTER function net.http_collect_response(request_id bigint, async boolean) SECURITY DEFINER; - - ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net; - ALTER function net.http_collect_response(request_id bigint, async boolean) SET search_path = net; - - REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC; - REVOKE ALL ON FUNCTION net.http_collect_response(request_id bigint, async boolean) FROM PUBLIC; - - GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - GRANT EXECUTE ON FUNCTION net.http_collect_response(request_id bigint, async boolean) TO supabase_functions_admin, postgres, anon, authenticated, service_role; - END IF; -END; -$$; - - -ALTER FUNCTION extensions.grant_pg_net_access() OWNER TO postgres; - --- --- Name: FUNCTION grant_pg_net_access(); Type: COMMENT; Schema: extensions; Owner: postgres --- - -COMMENT ON FUNCTION extensions.grant_pg_net_access() IS 'Grants access to pg_net'; - - --- --- Name: pgrst_ddl_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin --- - -CREATE OR REPLACE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger - LANGUAGE plpgsql - AS $$ -DECLARE - cmd record; -BEGIN - FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands() - LOOP - IF cmd.command_tag IN ( - 'CREATE SCHEMA', 'ALTER SCHEMA' - , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE' - , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE' - , 'CREATE VIEW', 'ALTER VIEW' - , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW' - , 'CREATE FUNCTION', 'ALTER FUNCTION' - , 'CREATE TRIGGER' - , 'CREATE TYPE', 'ALTER TYPE' - , 'CREATE RULE' - , 'COMMENT' - ) - -- don't notify in case of CREATE TEMP table or other objects created on pg_temp - AND cmd.schema_name is distinct from 'pg_temp' - THEN - NOTIFY pgrst, 'reload schema'; - END IF; - END LOOP; -END; $$; - - -ALTER FUNCTION extensions.pgrst_ddl_watch() OWNER TO supabase_admin; - --- --- Name: pgrst_drop_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin --- - -CREATE OR REPLACE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger - LANGUAGE plpgsql - AS $$ -DECLARE - obj record; -BEGIN - FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() - LOOP - IF obj.object_type IN ( - 'schema' - , 'table' - , 'foreign table' - , 'view' - , 'materialized view' - , 'function' - , 'trigger' - , 'type' - , 'rule' - ) - AND obj.is_temporary IS false -- no pg_temp objects - THEN - NOTIFY pgrst, 'reload schema'; - END IF; - END LOOP; -END; $$; - - -ALTER FUNCTION extensions.pgrst_drop_watch() OWNER TO supabase_admin; - --- --- Name: set_graphql_placeholder(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin --- - -CREATE OR REPLACE FUNCTION extensions.set_graphql_placeholder() RETURNS event_trigger - LANGUAGE plpgsql - AS $_$ - DECLARE - graphql_is_dropped bool; - BEGIN - graphql_is_dropped = ( - SELECT ev.schema_name = 'graphql_public' - FROM pg_event_trigger_dropped_objects() AS ev - WHERE ev.schema_name = 'graphql_public' - ); - - IF graphql_is_dropped - THEN - create or replace function graphql_public.graphql( - "operationName" text default null, - query text default null, - variables jsonb default null, - extensions jsonb default null - ) - returns jsonb - language plpgsql - as $$ - DECLARE - server_version float; - BEGIN - server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); - - IF server_version >= 14 THEN - RETURN jsonb_build_object( - 'errors', jsonb_build_array( - jsonb_build_object( - 'message', 'pg_graphql extension is not enabled.' - ) - ) - ); - ELSE - RETURN jsonb_build_object( - 'errors', jsonb_build_array( - jsonb_build_object( - 'message', 'pg_graphql is only available on projects running Postgres 14 onwards.' - ) - ) - ); - END IF; - END; - $$; - END IF; - - END; -$_$; - - -ALTER FUNCTION extensions.set_graphql_placeholder() OWNER TO supabase_admin; - --- --- Name: FUNCTION set_graphql_placeholder(); Type: COMMENT; Schema: extensions; Owner: supabase_admin --- - -COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeholder function for graphql_public.graphql'; - - --- --- Name: graphql(text, text, jsonb, jsonb); Type: FUNCTION; Schema: graphql_public; Owner: supabase_admin --- - -CREATE OR REPLACE FUNCTION graphql_public.graphql("operationName" text DEFAULT NULL::text, query text DEFAULT NULL::text, variables jsonb DEFAULT NULL::jsonb, extensions jsonb DEFAULT NULL::jsonb) RETURNS jsonb - LANGUAGE plpgsql - AS $$ - DECLARE - server_version float; - BEGIN - server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float); - - IF server_version >= 14 THEN - RETURN jsonb_build_object( - 'errors', jsonb_build_array( - jsonb_build_object( - 'message', 'pg_graphql extension is not enabled.' - ) - ) - ); - ELSE - RETURN jsonb_build_object( - 'errors', jsonb_build_array( - jsonb_build_object( - 'message', 'pg_graphql is only available on projects running Postgres 14 onwards.' - ) - ) - ); - END IF; - END; -$$; - - -ALTER FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) OWNER TO supabase_admin; - --- --- Name: can_insert_object(text, text, uuid, jsonb); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) RETURNS void - LANGUAGE plpgsql - AS $$ -BEGIN - INSERT INTO "storage"."objects" ("bucket_id", "name", "owner", "metadata") VALUES (bucketid, name, owner, metadata); - -- hack to rollback the successful insert - RAISE sqlstate 'PT200' using - message = 'ROLLBACK', - detail = 'rollback successful insert'; -END -$$; - - -ALTER FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) OWNER TO supabase_storage_admin; - --- --- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.extension(name text) RETURNS text - LANGUAGE plpgsql - AS $$ -DECLARE -_parts text[]; -_filename text; -BEGIN - select string_to_array(name, '/') into _parts; - select _parts[array_length(_parts,1)] into _filename; - -- @todo return the last part instead of 2 - return split_part(_filename, '.', 2); -END -$$; - - -ALTER FUNCTION storage.extension(name text) OWNER TO supabase_storage_admin; - --- --- Name: filename(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.filename(name text) RETURNS text - LANGUAGE plpgsql - AS $$ -DECLARE -_parts text[]; -BEGIN - select string_to_array(name, '/') into _parts; - return _parts[array_length(_parts,1)]; -END -$$; - - -ALTER FUNCTION storage.filename(name text) OWNER TO supabase_storage_admin; - --- --- Name: foldername(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.foldername(name text) RETURNS text[] - LANGUAGE plpgsql - AS $$ -DECLARE -_parts text[]; -BEGIN - select string_to_array(name, '/') into _parts; - return _parts[1:array_length(_parts,1)-1]; -END -$$; - - -ALTER FUNCTION storage.foldername(name text) OWNER TO supabase_storage_admin; - --- --- Name: get_size_by_bucket(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.get_size_by_bucket() RETURNS TABLE(size bigint, bucket_id text) - LANGUAGE plpgsql - AS $$ -BEGIN - return query - select sum((metadata->>'size')::int) as size, obj.bucket_id - from "storage".objects as obj - group by obj.bucket_id; -END -$$; - - -ALTER FUNCTION storage.get_size_by_bucket() OWNER TO supabase_storage_admin; - --- --- Name: search(text, text, integer, integer, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.search(prefix text, bucketname text, limits integer DEFAULT 100, levels integer DEFAULT 1, offsets integer DEFAULT 0, search text DEFAULT ''::text, sortcolumn text DEFAULT 'name'::text, sortorder text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb) - LANGUAGE plpgsql STABLE - AS $_$ -declare - v_order_by text; - v_sort_order text; -begin - case - when sortcolumn = 'name' then - v_order_by = 'name'; - when sortcolumn = 'updated_at' then - v_order_by = 'updated_at'; - when sortcolumn = 'created_at' then - v_order_by = 'created_at'; - when sortcolumn = 'last_accessed_at' then - v_order_by = 'last_accessed_at'; - else - v_order_by = 'name'; - end case; - - case - when sortorder = 'asc' then - v_sort_order = 'asc'; - when sortorder = 'desc' then - v_sort_order = 'desc'; - else - v_sort_order = 'asc'; - end case; - - v_order_by = v_order_by || ' ' || v_sort_order; - - return query execute - 'with folders as ( - select path_tokens[$1] as folder - from storage.objects - where objects.name ilike $2 || $3 || ''%'' - and bucket_id = $4 - and array_length(regexp_split_to_array(objects.name, ''/''), 1) <> $1 - group by folder - order by folder ' || v_sort_order || ' - ) - (select folder as "name", - null as id, - null as updated_at, - null as created_at, - null as last_accessed_at, - null as metadata from folders) - union all - (select path_tokens[$1] as "name", - id, - updated_at, - created_at, - last_accessed_at, - metadata - from storage.objects - where objects.name ilike $2 || $3 || ''%'' - and bucket_id = $4 - and array_length(regexp_split_to_array(objects.name, ''/''), 1) = $1 - order by ' || v_order_by || ') - limit $5 - offset $6' using levels, prefix, search, bucketname, limits, offsets; -end; -$_$; - - -ALTER FUNCTION storage.search(prefix text, bucketname text, limits integer, levels integer, offsets integer, search text, sortcolumn text, sortorder text) OWNER TO supabase_storage_admin; - --- --- Name: update_updated_at_column(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin --- - -CREATE OR REPLACE FUNCTION storage.update_updated_at_column() RETURNS trigger - LANGUAGE plpgsql - AS $$ -BEGIN - NEW.updated_at = now(); - RETURN NEW; -END; -$$; - - -ALTER FUNCTION storage.update_updated_at_column() OWNER TO supabase_storage_admin; - -SET default_tablespace = ''; - -SET default_table_access_method = heap; - --- --- Name: extensions; Type: TABLE; Schema: _realtime; Owner: postgres --- - -CREATE TABLE IF NOT EXISTS _realtime.extensions ( - id uuid NOT NULL, - type text, - settings jsonb, - tenant_external_id text, - inserted_at timestamp(0) without time zone NOT NULL, - updated_at timestamp(0) without time zone NOT NULL -); - - -ALTER TABLE _realtime.extensions OWNER TO postgres; - --- --- Name: schema_migrations; Type: TABLE; Schema: _realtime; Owner: postgres --- - -CREATE TABLE IF NOT EXISTS _realtime.schema_migrations ( - version bigint NOT NULL, - inserted_at timestamp(0) without time zone -); - - -ALTER TABLE _realtime.schema_migrations OWNER TO postgres; - --- --- Name: tenants; Type: TABLE; Schema: _realtime; Owner: postgres --- - -CREATE TABLE IF NOT EXISTS _realtime.tenants ( - id uuid NOT NULL, - name text, - external_id text, - jwt_secret text, - max_concurrent_users integer DEFAULT 200 NOT NULL, - inserted_at timestamp(0) without time zone NOT NULL, - updated_at timestamp(0) without time zone NOT NULL, - max_events_per_second integer DEFAULT 100 NOT NULL, - postgres_cdc_default text DEFAULT 'postgres_cdc_rls'::text, - max_bytes_per_second integer DEFAULT 100000 NOT NULL, - max_channels_per_client integer DEFAULT 100 NOT NULL, - max_joins_per_second integer DEFAULT 500 NOT NULL, - suspend boolean DEFAULT false -); - - -ALTER TABLE _realtime.tenants OWNER TO postgres; - --- --- Name: audit_log_entries; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.audit_log_entries ( - instance_id uuid, - id uuid NOT NULL, - payload json, - created_at timestamp with time zone, - ip_address character varying(64) DEFAULT ''::character varying NOT NULL -); - - -ALTER TABLE auth.audit_log_entries OWNER TO supabase_auth_admin; - --- --- Name: TABLE audit_log_entries; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.audit_log_entries IS 'Auth: Audit trail for user actions.'; - - --- --- Name: flow_state; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.flow_state ( - id uuid NOT NULL, - user_id uuid, - auth_code text NOT NULL, - code_challenge_method auth.code_challenge_method NOT NULL, - code_challenge text NOT NULL, - provider_type text NOT NULL, - provider_access_token text, - provider_refresh_token text, - created_at timestamp with time zone, - updated_at timestamp with time zone, - authentication_method text NOT NULL -); - - -ALTER TABLE auth.flow_state OWNER TO supabase_auth_admin; - --- --- Name: TABLE flow_state; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.flow_state IS 'stores metadata for pkce logins'; - - --- --- Name: identities; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.identities ( - provider_id text NOT NULL, - user_id uuid NOT NULL, - identity_data jsonb NOT NULL, - provider text NOT NULL, - last_sign_in_at timestamp with time zone, - created_at timestamp with time zone, - updated_at timestamp with time zone, - email text GENERATED ALWAYS AS (lower((identity_data ->> 'email'::text))) STORED, - id uuid DEFAULT gen_random_uuid() NOT NULL -); - - -ALTER TABLE auth.identities OWNER TO supabase_auth_admin; - --- --- Name: TABLE identities; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.identities IS 'Auth: Stores identities associated to a user.'; - - --- --- Name: COLUMN identities.email; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON COLUMN auth.identities.email IS 'Auth: Email is a generated column that references the optional email property in the identity_data'; - - --- --- Name: instances; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.instances ( - id uuid NOT NULL, - uuid uuid, - raw_base_config text, - created_at timestamp with time zone, - updated_at timestamp with time zone -); - - -ALTER TABLE auth.instances OWNER TO supabase_auth_admin; - --- --- Name: TABLE instances; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.instances IS 'Auth: Manages users across multiple sites.'; - - --- --- Name: mfa_amr_claims; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.mfa_amr_claims ( - session_id uuid NOT NULL, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL, - authentication_method text NOT NULL, - id uuid NOT NULL -); - - -ALTER TABLE auth.mfa_amr_claims OWNER TO supabase_auth_admin; - --- --- Name: TABLE mfa_amr_claims; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.mfa_amr_claims IS 'auth: stores authenticator method reference claims for multi factor authentication'; - - --- --- Name: mfa_challenges; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.mfa_challenges ( - id uuid NOT NULL, - factor_id uuid NOT NULL, - created_at timestamp with time zone NOT NULL, - verified_at timestamp with time zone, - ip_address inet NOT NULL -); - - -ALTER TABLE auth.mfa_challenges OWNER TO supabase_auth_admin; - --- --- Name: TABLE mfa_challenges; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.mfa_challenges IS 'auth: stores metadata about challenge requests made'; - - --- --- Name: mfa_factors; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.mfa_factors ( - id uuid NOT NULL, - user_id uuid NOT NULL, - friendly_name text, - factor_type auth.factor_type NOT NULL, - status auth.factor_status NOT NULL, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL, - secret text -); - - -ALTER TABLE auth.mfa_factors OWNER TO supabase_auth_admin; - --- --- Name: TABLE mfa_factors; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.mfa_factors IS 'auth: stores metadata about factors'; - - --- --- Name: refresh_tokens; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.refresh_tokens ( - instance_id uuid, - id bigint NOT NULL, - token character varying(255), - user_id character varying(255), - revoked boolean, - created_at timestamp with time zone, - updated_at timestamp with time zone, - parent character varying(255), - session_id uuid -); - - -ALTER TABLE auth.refresh_tokens OWNER TO supabase_auth_admin; - --- --- Name: TABLE refresh_tokens; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.refresh_tokens IS 'Auth: Store of tokens used to refresh JWT tokens once they expire.'; - - --- --- Name: refresh_tokens_id_seq; Type: SEQUENCE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE SEQUENCE IF NOT EXISTS auth.refresh_tokens_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE auth.refresh_tokens_id_seq OWNER TO supabase_auth_admin; - --- --- Name: refresh_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: auth; Owner: supabase_auth_admin --- - -ALTER SEQUENCE auth.refresh_tokens_id_seq OWNED BY auth.refresh_tokens.id; - - --- --- Name: saml_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.saml_providers ( - id uuid NOT NULL, - sso_provider_id uuid NOT NULL, - entity_id text NOT NULL, - metadata_xml text NOT NULL, - metadata_url text, - attribute_mapping jsonb, - created_at timestamp with time zone, - updated_at timestamp with time zone, - CONSTRAINT "entity_id not empty" CHECK ((char_length(entity_id) > 0)), - CONSTRAINT "metadata_url not empty" CHECK (((metadata_url = NULL::text) OR (char_length(metadata_url) > 0))), - CONSTRAINT "metadata_xml not empty" CHECK ((char_length(metadata_xml) > 0)) -); - - -ALTER TABLE auth.saml_providers OWNER TO supabase_auth_admin; - --- --- Name: TABLE saml_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.saml_providers IS 'Auth: Manages SAML Identity Provider connections.'; - - --- --- Name: saml_relay_states; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.saml_relay_states ( - id uuid NOT NULL, - sso_provider_id uuid NOT NULL, - request_id text NOT NULL, - for_email text, - redirect_to text, - from_ip_address inet, - created_at timestamp with time zone, - updated_at timestamp with time zone, - flow_state_id uuid, - CONSTRAINT "request_id not empty" CHECK ((char_length(request_id) > 0)) -); - - -ALTER TABLE auth.saml_relay_states OWNER TO supabase_auth_admin; - --- --- Name: TABLE saml_relay_states; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.saml_relay_states IS 'Auth: Contains SAML Relay State information for each Service Provider initiated login.'; - - --- --- Name: schema_migrations; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.schema_migrations ( - version character varying(255) NOT NULL -); - - -ALTER TABLE auth.schema_migrations OWNER TO supabase_auth_admin; - --- --- Name: TABLE schema_migrations; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.schema_migrations IS 'Auth: Manages updates to the auth system.'; - - --- --- Name: sessions; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.sessions ( - id uuid NOT NULL, - user_id uuid NOT NULL, - created_at timestamp with time zone, - updated_at timestamp with time zone, - factor_id uuid, - aal auth.aal_level, - not_after timestamp with time zone, - refreshed_at timestamp without time zone, - user_agent text, - ip inet, - tag text -); - - -ALTER TABLE auth.sessions OWNER TO supabase_auth_admin; - --- --- Name: TABLE sessions; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.sessions IS 'Auth: Stores session data associated to a user.'; - - --- --- Name: COLUMN sessions.not_after; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON COLUMN auth.sessions.not_after IS 'Auth: Not after is a nullable column that contains a timestamp after which the session should be regarded as expired.'; - - --- --- Name: sso_domains; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.sso_domains ( - id uuid NOT NULL, - sso_provider_id uuid NOT NULL, - domain text NOT NULL, - created_at timestamp with time zone, - updated_at timestamp with time zone, - CONSTRAINT "domain not empty" CHECK ((char_length(domain) > 0)) -); - - -ALTER TABLE auth.sso_domains OWNER TO supabase_auth_admin; - --- --- Name: TABLE sso_domains; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.sso_domains IS 'Auth: Manages SSO email address domain mapping to an SSO Identity Provider.'; - - --- --- Name: sso_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.sso_providers ( - id uuid NOT NULL, - resource_id text, - created_at timestamp with time zone, - updated_at timestamp with time zone, - CONSTRAINT "resource_id not empty" CHECK (((resource_id = NULL::text) OR (char_length(resource_id) > 0))) -); - - -ALTER TABLE auth.sso_providers OWNER TO supabase_auth_admin; - --- --- Name: TABLE sso_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.sso_providers IS 'Auth: Manages SSO identity provider information; see saml_providers for SAML.'; - - --- --- Name: COLUMN sso_providers.resource_id; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON COLUMN auth.sso_providers.resource_id IS 'Auth: Uniquely identifies a SSO provider according to a user-chosen resource ID (case insensitive), useful in infrastructure as code.'; - - --- --- Name: users; Type: TABLE; Schema: auth; Owner: supabase_auth_admin --- - -CREATE TABLE IF NOT EXISTS auth.users ( - instance_id uuid, - id uuid NOT NULL, - aud character varying(255), - role character varying(255), - email character varying(255), - encrypted_password character varying(255), - email_confirmed_at timestamp with time zone, - invited_at timestamp with time zone, - confirmation_token character varying(255), - confirmation_sent_at timestamp with time zone, - recovery_token character varying(255), - recovery_sent_at timestamp with time zone, - email_change_token_new character varying(255), - email_change character varying(255), - email_change_sent_at timestamp with time zone, - last_sign_in_at timestamp with time zone, - raw_app_meta_data jsonb, - raw_user_meta_data jsonb, - is_super_admin boolean, - created_at timestamp with time zone, - updated_at timestamp with time zone, - phone text DEFAULT NULL::character varying, - phone_confirmed_at timestamp with time zone, - phone_change text DEFAULT ''::character varying, - phone_change_token character varying(255) DEFAULT ''::character varying, - phone_change_sent_at timestamp with time zone, - confirmed_at timestamp with time zone GENERATED ALWAYS AS (LEAST(email_confirmed_at, phone_confirmed_at)) STORED, - email_change_token_current character varying(255) DEFAULT ''::character varying, - email_change_confirm_status smallint DEFAULT 0, - banned_until timestamp with time zone, - reauthentication_token character varying(255) DEFAULT ''::character varying, - reauthentication_sent_at timestamp with time zone, - is_sso_user boolean DEFAULT false NOT NULL, - deleted_at timestamp with time zone, - CONSTRAINT users_email_change_confirm_status_check CHECK (((email_change_confirm_status >= 0) AND (email_change_confirm_status <= 2))) -); - - -ALTER TABLE auth.users OWNER TO supabase_auth_admin; - --- --- Name: TABLE users; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON TABLE auth.users IS 'Auth: Stores user login data within a secure schema.'; - - --- --- Name: COLUMN users.is_sso_user; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON COLUMN auth.users.is_sso_user IS 'Auth: Set this column to true when the account comes from SSO. These accounts can have duplicate emails.'; - - --- --- Name: buckets; Type: TABLE; Schema: storage; Owner: supabase_storage_admin --- - -CREATE TABLE IF NOT EXISTS storage.buckets ( - id text NOT NULL, - name text NOT NULL, - owner uuid, - created_at timestamp with time zone DEFAULT now(), - updated_at timestamp with time zone DEFAULT now(), - public boolean DEFAULT false, - avif_autodetection boolean DEFAULT false, - file_size_limit bigint, - allowed_mime_types text[], - owner_id text -); - - -ALTER TABLE storage.buckets OWNER TO supabase_storage_admin; - --- --- Name: COLUMN buckets.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin --- - -COMMENT ON COLUMN storage.buckets.owner IS 'Field is deprecated, use owner_id instead'; - - --- --- Name: migrations; Type: TABLE; Schema: storage; Owner: supabase_storage_admin --- - -CREATE TABLE IF NOT EXISTS storage.migrations ( - id integer NOT NULL, - name character varying(100) NOT NULL, - hash character varying(40) NOT NULL, - executed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP -); - - -ALTER TABLE storage.migrations OWNER TO supabase_storage_admin; - --- --- Name: objects; Type: TABLE; Schema: storage; Owner: supabase_storage_admin --- - -CREATE TABLE IF NOT EXISTS storage.objects ( - id uuid DEFAULT extensions.uuid_generate_v4() NOT NULL, - bucket_id text, - name text, - owner uuid, - created_at timestamp with time zone DEFAULT now(), - updated_at timestamp with time zone DEFAULT now(), - last_accessed_at timestamp with time zone DEFAULT now(), - metadata jsonb, - path_tokens text[] GENERATED ALWAYS AS (string_to_array(name, '/'::text)) STORED, - version text, - owner_id text -); - - -ALTER TABLE storage.objects OWNER TO supabase_storage_admin; - --- --- Name: COLUMN objects.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin --- - -COMMENT ON COLUMN storage.objects.owner IS 'Field is deprecated, use owner_id instead'; - - --- --- Name: refresh_tokens id; Type: DEFAULT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.refresh_tokens ALTER COLUMN id SET DEFAULT nextval('auth.refresh_tokens_id_seq'::regclass); - - --- --- Data for Name: extensions; Type: TABLE DATA; Schema: _realtime; Owner: postgres --- - -INSERT INTO _realtime.extensions (id, type, settings, tenant_external_id, inserted_at, updated_at) VALUES ('5518e2da-548e-499c-ab1c-664fd6446714', 'postgres_cdc_rls', '{"region": "us-east-1", "db_host": "ABK7kBu27y/PVdL10i/b+A==", "db_name": "sWBpZNdjggEPTQVlI52Zfw==", "db_port": "+enMDFi1J/3IrrquHHwUmA==", "db_user": "uxbEq/zz8DXVD53TOI1zmw==", "slot_name": "supabase_realtime_replication_slot", "ip_version": 4, "db_password": "sWBpZNdjggEPTQVlI52Zfw==", "publication": "supabase_realtime", "ssl_enforced": false, "poll_interval_ms": 100, "poll_max_changes": 100, "poll_max_record_bytes": 1048576}', 'realtime-dev', '2023-12-12 15:25:21', '2023-12-12 15:25:21'); - - --- --- Data for Name: schema_migrations; Type: TABLE DATA; Schema: _realtime; Owner: postgres --- - -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20210706140551, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220329161857, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220410212326, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220506102948, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220527210857, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220815211129, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220815215024, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20220818141501, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20221018173709, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20221102172703, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20221223010058, '2023-01-09 07:15:13'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20230110180046, '2023-04-06 09:25:28'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20230810220907, '2023-12-12 15:25:19'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20230810220924, '2023-12-12 15:25:19'); -INSERT INTO _realtime.schema_migrations (version, inserted_at) VALUES (20231024094642, '2023-12-12 15:25:19'); - - --- --- Data for Name: tenants; Type: TABLE DATA; Schema: _realtime; Owner: postgres --- - -INSERT INTO _realtime.tenants (id, name, external_id, jwt_secret, max_concurrent_users, inserted_at, updated_at, max_events_per_second, postgres_cdc_default, max_bytes_per_second, max_channels_per_client, max_joins_per_second, suspend) VALUES ('e6edd492-6586-4c5d-9c2e-4e4de2e5c64d', 'realtime-dev', 'realtime-dev', 'iNjicxc4+llvc9wovDvqymwfnj9teWMlyOIbJ8Fh6j2WNU8CIJ2ZgjR6MUIKqSmeDmvpsKLsZ9jgXJmQPpwL8w==', 200, '2023-12-12 15:25:21', '2023-12-12 15:25:21', 100, 'postgres_cdc_rls', 100000, 100, 100, false); - - --- --- Data for Name: audit_log_entries; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: flow_state; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: identities; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: instances; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: mfa_amr_claims; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: mfa_challenges; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: mfa_factors; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: refresh_tokens; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: saml_providers; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: saml_relay_states; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: schema_migrations; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - -INSERT INTO auth.schema_migrations (version) VALUES ('20171026211738'); -INSERT INTO auth.schema_migrations (version) VALUES ('20171026211808'); -INSERT INTO auth.schema_migrations (version) VALUES ('20171026211834'); -INSERT INTO auth.schema_migrations (version) VALUES ('20180103212743'); -INSERT INTO auth.schema_migrations (version) VALUES ('20180108183307'); -INSERT INTO auth.schema_migrations (version) VALUES ('20180119214651'); -INSERT INTO auth.schema_migrations (version) VALUES ('20180125194653'); -INSERT INTO auth.schema_migrations (version) VALUES ('00'); -INSERT INTO auth.schema_migrations (version) VALUES ('20210710035447'); -INSERT INTO auth.schema_migrations (version) VALUES ('20210722035447'); -INSERT INTO auth.schema_migrations (version) VALUES ('20210730183235'); -INSERT INTO auth.schema_migrations (version) VALUES ('20210909172000'); -INSERT INTO auth.schema_migrations (version) VALUES ('20210927181326'); -INSERT INTO auth.schema_migrations (version) VALUES ('20211122151130'); -INSERT INTO auth.schema_migrations (version) VALUES ('20211124214934'); -INSERT INTO auth.schema_migrations (version) VALUES ('20211202183645'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220114185221'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220114185340'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220224000811'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220323170000'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220429102000'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220531120530'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220614074223'); -INSERT INTO auth.schema_migrations (version) VALUES ('20220811173540'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221003041349'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221003041400'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221011041400'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221020193600'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221021073300'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221021082433'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221027105023'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221114143122'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221114143410'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221125140132'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221208132122'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221215195500'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221215195800'); -INSERT INTO auth.schema_migrations (version) VALUES ('20221215195900'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230116124310'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230116124412'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230131181311'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230322519590'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230402418590'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230411005111'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230508135423'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230523124323'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230818113222'); -INSERT INTO auth.schema_migrations (version) VALUES ('20230914180801'); -INSERT INTO auth.schema_migrations (version) VALUES ('20231027141322'); -INSERT INTO auth.schema_migrations (version) VALUES ('20231114161723'); -INSERT INTO auth.schema_migrations (version) VALUES ('20231117164230'); - - --- --- Data for Name: sessions; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: sso_domains; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: sso_providers; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: users; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin --- - - - --- --- Data for Name: buckets; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin --- - - - --- --- Data for Name: migrations; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin --- - -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (0, 'create-migrations-table', 'e18db593bcde2aca2a408c4d1100f6abba2195df', '2022-04-14 09:52:39.214681'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (1, 'initialmigration', '6ab16121fbaa08bbd11b712d05f358f9b555d777', '2022-04-14 09:52:39.255149'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (2, 'pathtoken-column', '49756be03be4c17bb85fe70d4a861f27de7e49ad', '2022-04-14 09:52:39.276667'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (3, 'add-migrations-rls', 'bb5d124c53d68635a883e399426c6a5a25fc893d', '2022-04-14 09:52:39.587158'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (4, 'add-size-functions', '6d79007d04f5acd288c9c250c42d2d5fd286c54d', '2022-04-14 09:52:39.621747'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (5, 'change-column-name-in-get-size', 'fd65688505d2ffa9fbdc58a944348dd8604d688c', '2022-04-14 09:52:39.658796'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (6, 'add-rls-to-buckets', '63e2bab75a2040fee8e3fb3f15a0d26f3380e9b6', '2022-04-14 09:52:39.702011'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (7, 'add-public-to-buckets', '82568934f8a4d9e0a85f126f6fb483ad8214c418', '2022-04-14 09:52:39.739731'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (8, 'fix-search-function', '1a43a40eddb525f2e2f26efd709e6c06e58e059c', '2022-04-14 09:52:39.781062'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (9, 'search-files-search-function', '34c096597eb8b9d077fdfdde9878c88501b2fafc', '2022-08-23 04:48:07.728336'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (10, 'add-trigger-to-auto-update-updated_at-column', '37d6bb964a70a822e6d37f22f457b9bca7885928', '2022-08-23 04:48:07.736527'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (11, 'add-automatic-avif-detection-flag', 'bd76c53a9c564c80d98d119c1b3a28e16c8152db', '2023-04-06 09:25:29.356743'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (12, 'add-bucket-custom-limits', 'cbe0a4c32a0e891554a21020433b7a4423c07ee7', '2023-04-06 09:25:29.390303'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (13, 'use-bytes-for-max-size', '7a158ebce8a0c2801c9c65b7e9b2f98f68b3874e', '2023-04-06 09:25:29.402124'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (14, 'add-can-insert-object-function', '273193826bca7e0990b458d1ba72f8aa27c0d825', '2023-04-06 09:25:29.426206'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (15, 'add-version', 'e821a779d26612899b8c2dfe20245f904a327c4f', '2023-04-06 09:25:29.439561'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (16, 'drop-owner-foreign-key', '536b33f8878eed09d0144219777dcac96bdb25da', '2023-12-12 15:25:21.258059'); -INSERT INTO storage.migrations (id, name, hash, executed_at) VALUES (17, 'add_owner_id_column_deprecate_owner', '7545f216a39358b5487df75d941d05dbcd75eb46', '2023-12-12 15:25:21.271667'); - - --- --- Data for Name: objects; Type: TABLE DATA; Schema: storage; Owner: supabase_storage_admin --- - - - --- --- Name: refresh_tokens_id_seq; Type: SEQUENCE SET; Schema: auth; Owner: supabase_auth_admin --- - -SELECT pg_catalog.setval('auth.refresh_tokens_id_seq', 1, false); - - --- --- Name: extensions extensions_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: postgres --- - -ALTER TABLE ONLY _realtime.extensions - ADD CONSTRAINT extensions_pkey PRIMARY KEY (id); - - --- --- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: postgres --- - -ALTER TABLE ONLY _realtime.schema_migrations - ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); - - --- --- Name: tenants tenants_pkey; Type: CONSTRAINT; Schema: _realtime; Owner: postgres --- - -ALTER TABLE ONLY _realtime.tenants - ADD CONSTRAINT tenants_pkey PRIMARY KEY (id); - - --- --- Name: mfa_amr_claims amr_id_pk; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_amr_claims - ADD CONSTRAINT amr_id_pk PRIMARY KEY (id); - - --- --- Name: audit_log_entries audit_log_entries_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.audit_log_entries - ADD CONSTRAINT audit_log_entries_pkey PRIMARY KEY (id); - - --- --- Name: flow_state flow_state_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.flow_state - ADD CONSTRAINT flow_state_pkey PRIMARY KEY (id); - - --- --- Name: identities identities_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.identities - ADD CONSTRAINT identities_pkey PRIMARY KEY (id); - - --- --- Name: identities identities_provider_id_provider_unique; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.identities - ADD CONSTRAINT identities_provider_id_provider_unique UNIQUE (provider_id, provider); - - --- --- Name: instances instances_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.instances - ADD CONSTRAINT instances_pkey PRIMARY KEY (id); - - --- --- Name: mfa_amr_claims mfa_amr_claims_session_id_authentication_method_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_amr_claims - ADD CONSTRAINT mfa_amr_claims_session_id_authentication_method_pkey UNIQUE (session_id, authentication_method); - - --- --- Name: mfa_challenges mfa_challenges_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_challenges - ADD CONSTRAINT mfa_challenges_pkey PRIMARY KEY (id); - - --- --- Name: mfa_factors mfa_factors_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_factors - ADD CONSTRAINT mfa_factors_pkey PRIMARY KEY (id); - - --- --- Name: refresh_tokens refresh_tokens_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.refresh_tokens - ADD CONSTRAINT refresh_tokens_pkey PRIMARY KEY (id); - - --- --- Name: refresh_tokens refresh_tokens_token_unique; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.refresh_tokens - ADD CONSTRAINT refresh_tokens_token_unique UNIQUE (token); - - --- --- Name: saml_providers saml_providers_entity_id_key; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_providers - ADD CONSTRAINT saml_providers_entity_id_key UNIQUE (entity_id); - - --- --- Name: saml_providers saml_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_providers - ADD CONSTRAINT saml_providers_pkey PRIMARY KEY (id); - - --- --- Name: saml_relay_states saml_relay_states_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_relay_states - ADD CONSTRAINT saml_relay_states_pkey PRIMARY KEY (id); - - --- --- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.schema_migrations - ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); - - --- --- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.sessions - ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); - - --- --- Name: sso_domains sso_domains_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.sso_domains - ADD CONSTRAINT sso_domains_pkey PRIMARY KEY (id); - - --- --- Name: sso_providers sso_providers_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.sso_providers - ADD CONSTRAINT sso_providers_pkey PRIMARY KEY (id); - - --- --- Name: users users_phone_key; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.users - ADD CONSTRAINT users_phone_key UNIQUE (phone); - - --- --- Name: users users_pkey; Type: CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.users - ADD CONSTRAINT users_pkey PRIMARY KEY (id); - - --- --- Name: buckets buckets_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE ONLY storage.buckets - ADD CONSTRAINT buckets_pkey PRIMARY KEY (id); - - --- --- Name: migrations migrations_name_key; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE ONLY storage.migrations - ADD CONSTRAINT migrations_name_key UNIQUE (name); - - --- --- Name: migrations migrations_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE ONLY storage.migrations - ADD CONSTRAINT migrations_pkey PRIMARY KEY (id); - - --- --- Name: objects objects_pkey; Type: CONSTRAINT; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE ONLY storage.objects - ADD CONSTRAINT objects_pkey PRIMARY KEY (id); - - --- --- Name: extensions_tenant_external_id_type_index; Type: INDEX; Schema: _realtime; Owner: postgres --- - -CREATE UNIQUE INDEX extensions_tenant_external_id_type_index ON _realtime.extensions USING btree (tenant_external_id, type); - - --- --- Name: tenants_external_id_index; Type: INDEX; Schema: _realtime; Owner: postgres --- - -CREATE UNIQUE INDEX tenants_external_id_index ON _realtime.tenants USING btree (external_id); - - --- --- Name: audit_logs_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX audit_logs_instance_id_idx ON auth.audit_log_entries USING btree (instance_id); - - --- --- Name: confirmation_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX confirmation_token_idx ON auth.users USING btree (confirmation_token) WHERE ((confirmation_token)::text !~ '^[0-9 ]*$'::text); - - --- --- Name: email_change_token_current_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX email_change_token_current_idx ON auth.users USING btree (email_change_token_current) WHERE ((email_change_token_current)::text !~ '^[0-9 ]*$'::text); - - --- --- Name: email_change_token_new_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX email_change_token_new_idx ON auth.users USING btree (email_change_token_new) WHERE ((email_change_token_new)::text !~ '^[0-9 ]*$'::text); - - --- --- Name: factor_id_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX factor_id_created_at_idx ON auth.mfa_factors USING btree (user_id, created_at); - - --- --- Name: flow_state_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX flow_state_created_at_idx ON auth.flow_state USING btree (created_at DESC); - - --- --- Name: identities_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX identities_email_idx ON auth.identities USING btree (email text_pattern_ops); - - --- --- Name: INDEX identities_email_idx; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON INDEX auth.identities_email_idx IS 'Auth: Ensures indexed queries on the email column'; - - --- --- Name: identities_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX identities_user_id_idx ON auth.identities USING btree (user_id); - - --- --- Name: idx_auth_code; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX idx_auth_code ON auth.flow_state USING btree (auth_code); - - --- --- Name: idx_user_id_auth_method; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX idx_user_id_auth_method ON auth.flow_state USING btree (user_id, authentication_method); - - --- --- Name: mfa_challenge_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX mfa_challenge_created_at_idx ON auth.mfa_challenges USING btree (created_at DESC); - - --- --- Name: mfa_factors_user_friendly_name_unique; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX mfa_factors_user_friendly_name_unique ON auth.mfa_factors USING btree (friendly_name, user_id) WHERE (btrim(friendly_name) <> ''::text); - - --- --- Name: mfa_factors_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX mfa_factors_user_id_idx ON auth.mfa_factors USING btree (user_id); - - --- --- Name: reauthentication_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX reauthentication_token_idx ON auth.users USING btree (reauthentication_token) WHERE ((reauthentication_token)::text !~ '^[0-9 ]*$'::text); - - --- --- Name: recovery_token_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX recovery_token_idx ON auth.users USING btree (recovery_token) WHERE ((recovery_token)::text !~ '^[0-9 ]*$'::text); - - --- --- Name: refresh_tokens_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX refresh_tokens_instance_id_idx ON auth.refresh_tokens USING btree (instance_id); - - --- --- Name: refresh_tokens_instance_id_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX refresh_tokens_instance_id_user_id_idx ON auth.refresh_tokens USING btree (instance_id, user_id); - - --- --- Name: refresh_tokens_parent_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX refresh_tokens_parent_idx ON auth.refresh_tokens USING btree (parent); - - --- --- Name: refresh_tokens_session_id_revoked_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX refresh_tokens_session_id_revoked_idx ON auth.refresh_tokens USING btree (session_id, revoked); - - --- --- Name: refresh_tokens_updated_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX refresh_tokens_updated_at_idx ON auth.refresh_tokens USING btree (updated_at DESC); - - --- --- Name: saml_providers_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX saml_providers_sso_provider_id_idx ON auth.saml_providers USING btree (sso_provider_id); - - --- --- Name: saml_relay_states_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX saml_relay_states_created_at_idx ON auth.saml_relay_states USING btree (created_at DESC); - - --- --- Name: saml_relay_states_for_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX saml_relay_states_for_email_idx ON auth.saml_relay_states USING btree (for_email); - - --- --- Name: saml_relay_states_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX saml_relay_states_sso_provider_id_idx ON auth.saml_relay_states USING btree (sso_provider_id); - - --- --- Name: sessions_not_after_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX sessions_not_after_idx ON auth.sessions USING btree (not_after DESC); - - --- --- Name: sessions_user_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX sessions_user_id_idx ON auth.sessions USING btree (user_id); - - --- --- Name: sso_domains_domain_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX sso_domains_domain_idx ON auth.sso_domains USING btree (lower(domain)); - - --- --- Name: sso_domains_sso_provider_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX sso_domains_sso_provider_id_idx ON auth.sso_domains USING btree (sso_provider_id); - - --- --- Name: sso_providers_resource_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX sso_providers_resource_id_idx ON auth.sso_providers USING btree (lower(resource_id)); - - --- --- Name: user_id_created_at_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX user_id_created_at_idx ON auth.sessions USING btree (user_id, created_at); - - --- --- Name: users_email_partial_key; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE UNIQUE INDEX users_email_partial_key ON auth.users USING btree (email) WHERE (is_sso_user = false); - - --- --- Name: INDEX users_email_partial_key; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin --- - -COMMENT ON INDEX auth.users_email_partial_key IS 'Auth: A partial unique index that applies only when is_sso_user is false'; - - --- --- Name: users_instance_id_email_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX users_instance_id_email_idx ON auth.users USING btree (instance_id, lower((email)::text)); - - --- --- Name: users_instance_id_idx; Type: INDEX; Schema: auth; Owner: supabase_auth_admin --- - -CREATE INDEX users_instance_id_idx ON auth.users USING btree (instance_id); - - --- --- Name: bname; Type: INDEX; Schema: storage; Owner: supabase_storage_admin --- - -CREATE UNIQUE INDEX bname ON storage.buckets USING btree (name); - - --- --- Name: bucketid_objname; Type: INDEX; Schema: storage; Owner: supabase_storage_admin --- - -CREATE UNIQUE INDEX bucketid_objname ON storage.objects USING btree (bucket_id, name); - - --- --- Name: name_prefix_search; Type: INDEX; Schema: storage; Owner: supabase_storage_admin --- - -CREATE INDEX name_prefix_search ON storage.objects USING btree (name text_pattern_ops); - - --- --- Name: objects update_objects_updated_at; Type: TRIGGER; Schema: storage; Owner: supabase_storage_admin --- - -CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON storage.objects FOR EACH ROW EXECUTE FUNCTION storage.update_updated_at_column(); - - --- --- Name: extensions extensions_tenant_external_id_fkey; Type: FK CONSTRAINT; Schema: _realtime; Owner: postgres --- - -ALTER TABLE ONLY _realtime.extensions - ADD CONSTRAINT extensions_tenant_external_id_fkey FOREIGN KEY (tenant_external_id) REFERENCES _realtime.tenants(external_id) ON DELETE CASCADE; - - --- --- Name: identities identities_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.identities - ADD CONSTRAINT identities_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE; - - --- --- Name: mfa_amr_claims mfa_amr_claims_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_amr_claims - ADD CONSTRAINT mfa_amr_claims_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE; - - --- --- Name: mfa_challenges mfa_challenges_auth_factor_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_challenges - ADD CONSTRAINT mfa_challenges_auth_factor_id_fkey FOREIGN KEY (factor_id) REFERENCES auth.mfa_factors(id) ON DELETE CASCADE; - - --- --- Name: mfa_factors mfa_factors_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.mfa_factors - ADD CONSTRAINT mfa_factors_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE; - - --- --- Name: refresh_tokens refresh_tokens_session_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.refresh_tokens - ADD CONSTRAINT refresh_tokens_session_id_fkey FOREIGN KEY (session_id) REFERENCES auth.sessions(id) ON DELETE CASCADE; - - --- --- Name: saml_providers saml_providers_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_providers - ADD CONSTRAINT saml_providers_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE; - - --- --- Name: saml_relay_states saml_relay_states_flow_state_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_relay_states - ADD CONSTRAINT saml_relay_states_flow_state_id_fkey FOREIGN KEY (flow_state_id) REFERENCES auth.flow_state(id) ON DELETE CASCADE; - - --- --- Name: saml_relay_states saml_relay_states_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.saml_relay_states - ADD CONSTRAINT saml_relay_states_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE; - - --- --- Name: sessions sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.sessions - ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE; - - --- --- Name: sso_domains sso_domains_sso_provider_id_fkey; Type: FK CONSTRAINT; Schema: auth; Owner: supabase_auth_admin --- - -ALTER TABLE ONLY auth.sso_domains - ADD CONSTRAINT sso_domains_sso_provider_id_fkey FOREIGN KEY (sso_provider_id) REFERENCES auth.sso_providers(id) ON DELETE CASCADE; - - --- --- Name: objects objects_bucketId_fkey; Type: FK CONSTRAINT; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE ONLY storage.objects - ADD CONSTRAINT "objects_bucketId_fkey" FOREIGN KEY (bucket_id) REFERENCES storage.buckets(id); - - --- --- Name: buckets; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE storage.buckets ENABLE ROW LEVEL SECURITY; - --- --- Name: migrations; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE storage.migrations ENABLE ROW LEVEL SECURITY; - --- --- Name: objects; Type: ROW SECURITY; Schema: storage; Owner: supabase_storage_admin --- - -ALTER TABLE storage.objects ENABLE ROW LEVEL SECURITY; - --- --- Name: supabase_realtime; Type: PUBLICATION; Schema: -; Owner: postgres --- - -CREATE PUBLICATION supabase_realtime WITH (publish = 'insert, update, delete, truncate'); - - -ALTER PUBLICATION supabase_realtime OWNER TO postgres; - --- --- Name: SCHEMA auth; Type: ACL; Schema: -; Owner: supabase_admin --- - -GRANT USAGE ON SCHEMA auth TO anon; -GRANT USAGE ON SCHEMA auth TO authenticated; -GRANT USAGE ON SCHEMA auth TO service_role; -GRANT ALL ON SCHEMA auth TO supabase_auth_admin; -GRANT ALL ON SCHEMA auth TO dashboard_user; -GRANT ALL ON SCHEMA auth TO postgres; - - --- --- Name: SCHEMA extensions; Type: ACL; Schema: -; Owner: postgres --- - -GRANT USAGE ON SCHEMA extensions TO anon; -GRANT USAGE ON SCHEMA extensions TO authenticated; -GRANT USAGE ON SCHEMA extensions TO service_role; -GRANT ALL ON SCHEMA extensions TO dashboard_user; - - --- --- Name: SCHEMA graphql_public; Type: ACL; Schema: -; Owner: supabase_admin --- - -GRANT USAGE ON SCHEMA graphql_public TO postgres; -GRANT USAGE ON SCHEMA graphql_public TO anon; -GRANT USAGE ON SCHEMA graphql_public TO authenticated; -GRANT USAGE ON SCHEMA graphql_public TO service_role; - - --- --- Name: SCHEMA public; Type: ACL; Schema: -; Owner: postgres --- - -REVOKE USAGE ON SCHEMA public FROM PUBLIC; -GRANT ALL ON SCHEMA public TO PUBLIC; -GRANT USAGE ON SCHEMA public TO anon; -GRANT USAGE ON SCHEMA public TO authenticated; -GRANT USAGE ON SCHEMA public TO service_role; - - --- --- Name: SCHEMA realtime; Type: ACL; Schema: -; Owner: supabase_admin --- - -GRANT USAGE ON SCHEMA realtime TO postgres; - - --- --- Name: SCHEMA storage; Type: ACL; Schema: -; Owner: supabase_admin --- - -GRANT ALL ON SCHEMA storage TO postgres; -GRANT USAGE ON SCHEMA storage TO anon; -GRANT USAGE ON SCHEMA storage TO authenticated; -GRANT USAGE ON SCHEMA storage TO service_role; -GRANT ALL ON SCHEMA storage TO supabase_storage_admin; -GRANT ALL ON SCHEMA storage TO dashboard_user; - - --- --- Name: FUNCTION email(); Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON FUNCTION auth.email() TO dashboard_user; - - --- --- Name: FUNCTION jwt(); Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON FUNCTION auth.jwt() TO postgres; -GRANT ALL ON FUNCTION auth.jwt() TO dashboard_user; - - --- --- Name: FUNCTION role(); Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON FUNCTION auth.role() TO dashboard_user; - - --- --- Name: FUNCTION uid(); Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON FUNCTION auth.uid() TO dashboard_user; - - --- --- Name: FUNCTION algorithm_sign(signables text, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.algorithm_sign(signables text, secret text, algorithm text) TO dashboard_user; - - --- --- Name: FUNCTION armor(bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.armor(bytea) TO dashboard_user; - - --- --- Name: FUNCTION armor(bytea, text[], text[]); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.armor(bytea, text[], text[]) TO dashboard_user; - - --- --- Name: FUNCTION crypt(text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.crypt(text, text) TO dashboard_user; - - --- --- Name: FUNCTION dearmor(text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.dearmor(text) TO dashboard_user; - - --- --- Name: FUNCTION decrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.decrypt(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION decrypt_iv(bytea, bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.decrypt_iv(bytea, bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION digest(bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.digest(bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION digest(text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.digest(text, text) TO dashboard_user; - - --- --- Name: FUNCTION encrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.encrypt(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION encrypt_iv(bytea, bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.encrypt_iv(bytea, bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION gen_random_bytes(integer); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.gen_random_bytes(integer) TO dashboard_user; - - --- --- Name: FUNCTION gen_random_uuid(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.gen_random_uuid() TO dashboard_user; - - --- --- Name: FUNCTION gen_salt(text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.gen_salt(text) TO dashboard_user; - - --- --- Name: FUNCTION gen_salt(text, integer); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.gen_salt(text, integer) TO dashboard_user; - - --- --- Name: FUNCTION grant_pg_cron_access(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.grant_pg_cron_access() TO dashboard_user; - - --- --- Name: FUNCTION grant_pg_net_access(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.grant_pg_net_access() TO dashboard_user; - - --- --- Name: FUNCTION hmac(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.hmac(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION hmac(text, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.hmac(text, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_armor_headers(text, OUT key text, OUT value text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_armor_headers(text, OUT key text, OUT value text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_key_id(bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_key_id(bytea) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt(bytea, bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt(bytea, bytea, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt(bytea, bytea, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_decrypt_bytea(bytea, bytea, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_encrypt(text, bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_encrypt(text, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt(text, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_encrypt_bytea(bytea, bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea) TO dashboard_user; - - --- --- Name: FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_pub_encrypt_bytea(bytea, bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_decrypt(bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_decrypt(bytea, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt(bytea, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_decrypt_bytea(bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_decrypt_bytea(bytea, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_decrypt_bytea(bytea, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_encrypt(text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_encrypt(text, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt(text, text, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_encrypt_bytea(bytea, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text) TO dashboard_user; - - --- --- Name: FUNCTION pgp_sym_encrypt_bytea(bytea, text, text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.pgp_sym_encrypt_bytea(bytea, text, text) TO dashboard_user; - - --- --- Name: FUNCTION sign(payload json, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.sign(payload json, secret text, algorithm text) TO dashboard_user; - - --- --- Name: FUNCTION url_decode(data text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.url_decode(data text) TO dashboard_user; - - --- --- Name: FUNCTION url_encode(data bytea); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.url_encode(data bytea) TO dashboard_user; - - --- --- Name: FUNCTION uuid_generate_v1(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_generate_v1() TO dashboard_user; - - --- --- Name: FUNCTION uuid_generate_v1mc(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_generate_v1mc() TO dashboard_user; - - --- --- Name: FUNCTION uuid_generate_v3(namespace uuid, name text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_generate_v3(namespace uuid, name text) TO dashboard_user; - - --- --- Name: FUNCTION uuid_generate_v4(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_generate_v4() TO dashboard_user; - - --- --- Name: FUNCTION uuid_generate_v5(namespace uuid, name text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_generate_v5(namespace uuid, name text) TO dashboard_user; - - --- --- Name: FUNCTION uuid_nil(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_nil() TO dashboard_user; - - --- --- Name: FUNCTION uuid_ns_dns(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_ns_dns() TO dashboard_user; - - --- --- Name: FUNCTION uuid_ns_oid(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_ns_oid() TO dashboard_user; - - --- --- Name: FUNCTION uuid_ns_url(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_ns_url() TO dashboard_user; - - --- --- Name: FUNCTION uuid_ns_x500(); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.uuid_ns_x500() TO dashboard_user; - - --- --- Name: FUNCTION verify(token text, secret text, algorithm text); Type: ACL; Schema: extensions; Owner: postgres --- - -GRANT ALL ON FUNCTION extensions.verify(token text, secret text, algorithm text) TO dashboard_user; - - --- --- Name: FUNCTION extension(name text); Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON FUNCTION storage.extension(name text) TO anon; -GRANT ALL ON FUNCTION storage.extension(name text) TO authenticated; -GRANT ALL ON FUNCTION storage.extension(name text) TO service_role; -GRANT ALL ON FUNCTION storage.extension(name text) TO dashboard_user; -GRANT ALL ON FUNCTION storage.extension(name text) TO postgres; - - --- --- Name: FUNCTION filename(name text); Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON FUNCTION storage.filename(name text) TO anon; -GRANT ALL ON FUNCTION storage.filename(name text) TO authenticated; -GRANT ALL ON FUNCTION storage.filename(name text) TO service_role; -GRANT ALL ON FUNCTION storage.filename(name text) TO dashboard_user; -GRANT ALL ON FUNCTION storage.filename(name text) TO postgres; - - --- --- Name: FUNCTION foldername(name text); Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON FUNCTION storage.foldername(name text) TO anon; -GRANT ALL ON FUNCTION storage.foldername(name text) TO authenticated; -GRANT ALL ON FUNCTION storage.foldername(name text) TO service_role; -GRANT ALL ON FUNCTION storage.foldername(name text) TO dashboard_user; -GRANT ALL ON FUNCTION storage.foldername(name text) TO postgres; - - --- --- Name: TABLE audit_log_entries; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.audit_log_entries TO dashboard_user; -GRANT ALL ON TABLE auth.audit_log_entries TO postgres; - - --- --- Name: TABLE flow_state; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.flow_state TO postgres; -GRANT ALL ON TABLE auth.flow_state TO dashboard_user; - - --- --- Name: TABLE identities; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.identities TO postgres; -GRANT ALL ON TABLE auth.identities TO dashboard_user; - - --- --- Name: TABLE instances; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.instances TO dashboard_user; -GRANT ALL ON TABLE auth.instances TO postgres; - - --- --- Name: TABLE mfa_amr_claims; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.mfa_amr_claims TO postgres; -GRANT ALL ON TABLE auth.mfa_amr_claims TO dashboard_user; - - --- --- Name: TABLE mfa_challenges; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.mfa_challenges TO postgres; -GRANT ALL ON TABLE auth.mfa_challenges TO dashboard_user; - - --- --- Name: TABLE mfa_factors; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.mfa_factors TO postgres; -GRANT ALL ON TABLE auth.mfa_factors TO dashboard_user; - - --- --- Name: TABLE refresh_tokens; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.refresh_tokens TO dashboard_user; -GRANT ALL ON TABLE auth.refresh_tokens TO postgres; - - --- --- Name: SEQUENCE refresh_tokens_id_seq; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON SEQUENCE auth.refresh_tokens_id_seq TO dashboard_user; -GRANT ALL ON SEQUENCE auth.refresh_tokens_id_seq TO postgres; - - --- --- Name: TABLE saml_providers; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.saml_providers TO postgres; -GRANT ALL ON TABLE auth.saml_providers TO dashboard_user; - - --- --- Name: TABLE saml_relay_states; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.saml_relay_states TO postgres; -GRANT ALL ON TABLE auth.saml_relay_states TO dashboard_user; - - --- --- Name: TABLE schema_migrations; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.schema_migrations TO dashboard_user; -GRANT ALL ON TABLE auth.schema_migrations TO postgres; - - --- --- Name: TABLE sessions; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.sessions TO postgres; -GRANT ALL ON TABLE auth.sessions TO dashboard_user; - - --- --- Name: TABLE sso_domains; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.sso_domains TO postgres; -GRANT ALL ON TABLE auth.sso_domains TO dashboard_user; - - --- --- Name: TABLE sso_providers; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.sso_providers TO postgres; -GRANT ALL ON TABLE auth.sso_providers TO dashboard_user; - - --- --- Name: TABLE users; Type: ACL; Schema: auth; Owner: supabase_auth_admin --- - -GRANT ALL ON TABLE auth.users TO dashboard_user; -GRANT ALL ON TABLE auth.users TO postgres; - - --- --- Name: TABLE buckets; Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON TABLE storage.buckets TO anon; -GRANT ALL ON TABLE storage.buckets TO authenticated; -GRANT ALL ON TABLE storage.buckets TO service_role; -GRANT ALL ON TABLE storage.buckets TO postgres; - - --- --- Name: TABLE migrations; Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON TABLE storage.migrations TO anon; -GRANT ALL ON TABLE storage.migrations TO authenticated; -GRANT ALL ON TABLE storage.migrations TO service_role; -GRANT ALL ON TABLE storage.migrations TO postgres; - - --- --- Name: TABLE objects; Type: ACL; Schema: storage; Owner: supabase_storage_admin --- - -GRANT ALL ON TABLE storage.objects TO anon; -GRANT ALL ON TABLE storage.objects TO authenticated; -GRANT ALL ON TABLE storage.objects TO service_role; -GRANT ALL ON TABLE storage.objects TO postgres; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON SEQUENCES TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON FUNCTIONS TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: auth; Owner: supabase_auth_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_auth_admin IN SCHEMA auth GRANT ALL ON TABLES TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON SEQUENCES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON FUNCTIONS TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: graphql_public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA graphql_public GRANT ALL ON TABLES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: public; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON SEQUENCES TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON FUNCTIONS TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: realtime; Owner: supabase_admin --- - -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA realtime GRANT ALL ON TABLES TO dashboard_user; - - --- --- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: storage; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON SEQUENCES TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR FUNCTIONS; Type: DEFAULT ACL; Schema: storage; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON FUNCTIONS TO service_role; - - --- --- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: storage; Owner: postgres --- - -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES TO postgres; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES TO anon; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES TO authenticated; -ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA storage GRANT ALL ON TABLES TO service_role; - - --- --- Name: issue_graphql_placeholder; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER issue_graphql_placeholder ON sql_drop - WHEN TAG IN ('DROP EXTENSION') - EXECUTE FUNCTION extensions.set_graphql_placeholder(); - - -ALTER EVENT TRIGGER issue_graphql_placeholder OWNER TO supabase_admin; - --- --- Name: issue_pg_cron_access; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER issue_pg_cron_access ON ddl_command_end - WHEN TAG IN ('CREATE SCHEMA') - EXECUTE FUNCTION extensions.grant_pg_cron_access(); - - -ALTER EVENT TRIGGER issue_pg_cron_access OWNER TO supabase_admin; - --- --- Name: issue_pg_graphql_access; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER issue_pg_graphql_access ON ddl_command_end - WHEN TAG IN ('CREATE FUNCTION') - EXECUTE FUNCTION extensions.grant_pg_graphql_access(); - - -ALTER EVENT TRIGGER issue_pg_graphql_access OWNER TO supabase_admin; - --- --- Name: issue_pg_net_access; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER issue_pg_net_access ON ddl_command_end - WHEN TAG IN ('CREATE EXTENSION') - EXECUTE FUNCTION extensions.grant_pg_net_access(); - - -ALTER EVENT TRIGGER issue_pg_net_access OWNER TO supabase_admin; - --- --- Name: pgrst_ddl_watch; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER pgrst_ddl_watch ON ddl_command_end - EXECUTE FUNCTION extensions.pgrst_ddl_watch(); - - -ALTER EVENT TRIGGER pgrst_ddl_watch OWNER TO supabase_admin; - --- --- Name: pgrst_drop_watch; Type: EVENT TRIGGER; Schema: -; Owner: supabase_admin --- - -CREATE EVENT TRIGGER pgrst_drop_watch ON sql_drop - EXECUTE FUNCTION extensions.pgrst_drop_watch(); - - -ALTER EVENT TRIGGER pgrst_drop_watch OWNER TO supabase_admin; - --- --- PostgreSQL database dump complete --- - -RESET ALL; -`; diff --git a/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-14.sql.ts b/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-14.sql.ts index 4c6135a66a..8af0892b29 100644 --- a/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-14.sql.ts +++ b/apps/cli/src/command-internal/db-bootstrap/templates/db-initial-schema-14.sql.ts @@ -1,5 +1,5 @@ /** - * Baseline SQL run via `ExecBatch` against a fresh PG14 (`db.major_version != 13`, `<= 14`) local + * Baseline SQL run via `ExecBatch` against a fresh PG14 local * database, right after {@link START_DB_GLOBALS_SQL}. */ export const START_DB_INITIAL_SCHEMA_14_SQL = `-- diff --git a/apps/cli/src/command-internal/db-config.integration.test.ts b/apps/cli/src/command-internal/db-config.integration.test.ts index a972f6e8f2..24697dc0da 100644 --- a/apps/cli/src/command-internal/db-config.integration.test.ts +++ b/apps/cli/src/command-internal/db-config.integration.test.ts @@ -689,6 +689,7 @@ describe("dbConfigResolver (db-url under the stack backend)", () => { const stack: Stack = { id: "b".repeat(64), services: { create: () => unused, get: () => Effect.succeed(database), list: unused }, + apiTls: { get: Effect.undefined }, credentials: { get: unused }, composition: { plan: () => unused, diff --git a/apps/cli/src/command-internal/db-config.read.unit.test.ts b/apps/cli/src/command-internal/db-config.read.unit.test.ts index 00da986f48..6a50261ce5 100644 --- a/apps/cli/src/command-internal/db-config.read.unit.test.ts +++ b/apps/cli/src/command-internal/db-config.read.unit.test.ts @@ -2488,7 +2488,7 @@ describe("readDbConfig auth.Enabled validation", () => { it.effect("rejects the removed linkedin provider, naming linkedin_oidc", () => failsWith( ["[auth.external.linkedin]", "enabled = true"], - "[auth.external.linkedin] in supabase/config.toml is no longer supported. Use [auth.external.linkedin_oidc] instead.", + "auth.external.linkedin in supabase/config.toml is no longer supported. Use auth.external.linkedin_oidc instead.", ), ); diff --git a/apps/cli/src/command-internal/db-image.ts b/apps/cli/src/command-internal/db-image.ts index aa663df918..28751bdfa5 100644 --- a/apps/cli/src/command-internal/db-image.ts +++ b/apps/cli/src/command-internal/db-image.ts @@ -1,6 +1,8 @@ import { legacyProjectStatePaths } from "../shared/config/legacy-project-state.paths.ts"; import { usesStackState } from "./stack-backend.ts"; import { Effect, type FileSystem, type Path } from "effect"; +import { Output } from "../shared/output/output.service.ts"; +import { yellow } from "./colors.ts"; import { dockerfileServiceImageRaw } from "../shared/services/dockerfile-images.ts"; import { postgresImageForDbMajorVersion } from "../shared/services/services.shared.ts"; import { @@ -56,6 +58,20 @@ function compareSemver(a: string, b: string): number { return 0; } +/** Warns on stderr when the local project runs Postgres 14, which is end of life and soon unsupported. */ +export const warnIfPostgres14Deprecated = Effect.fn("DbImage.warnIfPostgres14Deprecated")( + function* (majorVersion: number) { + if (majorVersion !== 14) return; + const output = yield* Output; + yield* output.raw( + `${yellow("WARNING:")} Postgres 14 reached end of life on November 12, 2026, and the Supabase CLI will drop support for it soon. ` + + "Upgrade your project to Postgres 17, then set db.major_version = 17 in your project config: " + + "https://supabase.com/docs/guides/platform/upgrading\n", + "stderr", + ); + }, +); + /** OrioleDB replaces the Postgres image only on 15/17 projects with a version set. */ export const selectsOrioleDb = ( orioledbVersion: string | undefined, diff --git a/apps/cli/src/command-internal/db-image.unit.test.ts b/apps/cli/src/command-internal/db-image.unit.test.ts index 19eef68a28..8551642733 100644 --- a/apps/cli/src/command-internal/db-image.unit.test.ts +++ b/apps/cli/src/command-internal/db-image.unit.test.ts @@ -14,7 +14,7 @@ import { resolveDbImage } from "./db-image.ts"; const currentPostgres = dockerfileServiceImageRaw("pg"); const currentPostgresTag = imageTag(currentPostgres) ?? ""; -// PG13/15 and PG14 now come from the Dockerfile's generated `pg15`/hand-pinned `pg14` stages +// PG15 and PG14 now come from the Dockerfile's generated `pg15`/hand-pinned `pg14` stages // (the single version table), not hardcoded fallback constants. const pg15Image = dockerfileServiceImageRaw("pg15"); const pg15Tag = imageTag(pg15Image) ?? ""; @@ -52,10 +52,6 @@ describe("resolveDbImage", () => { it.effect("resolves the default Postgres image per major version", () => Effect.gen(function* () { const dir = yield* withTemp; - expect(yield* resolve(dir, 13)).toEqual({ - image: pg15Image, - configImage: pg15Image, - }); expect(yield* resolve(dir, 14)).toEqual({ image: pg14Image, configImage: pg14Image, @@ -140,10 +136,6 @@ describe("resolveDbImage", () => { image: pinned, configImage: pg15Image, }); - expect(yield* resolve(dir, 13)).toEqual({ - image: pinned, - configImage: pg15Image, - }); }).pipe(Effect.scoped, Effect.provide(BunServices.layer)); }); diff --git a/apps/cli/src/command-internal/resolved-config-context.ts b/apps/cli/src/command-internal/resolved-config-context.ts index bffb5a5ba5..80be9d0106 100644 --- a/apps/cli/src/command-internal/resolved-config-context.ts +++ b/apps/cli/src/command-internal/resolved-config-context.ts @@ -1,4 +1,4 @@ -import type { CliConfig } from "@supabase/config"; +import { CliConfigRemovedKeyError, type CliConfig } from "@supabase/config"; import { Effect, Option, Predicate } from "effect"; import { CliConfigKeys } from "../config/cli-config-keys.ts"; @@ -68,6 +68,10 @@ export const resolvePasskeyWebauthn = Effect.fn("ResolvedConfigContext.passkeyWe return { passkeyEnabled, webauthn }; }); +/** The remediation a config load failure carries, when it has one. */ +export const configLoadFailureSuggestion = (cause: unknown): string | undefined => + cause instanceof CliConfigRemovedKeyError ? cause.suggestion : undefined; + /** The failure text commands report when the resolved config cannot be loaded. */ export const describeConfigLoadFailure = (cause: unknown): string => Predicate.isTagged(cause, "CliConfigParseError") && "cause" in cause diff --git a/apps/cli/src/command-internal/stack-bootstrap.ts b/apps/cli/src/command-internal/stack-bootstrap.ts index efb82990b2..ae1d450bbe 100644 --- a/apps/cli/src/command-internal/stack-bootstrap.ts +++ b/apps/cli/src/command-internal/stack-bootstrap.ts @@ -126,7 +126,7 @@ const applyStackMigrateAndSeed = ( export const projectCatalogOverlay = ( toml: Pick, workdir: string, -): StackCatalogSetupInput["overlay"] => ({ +): NonNullable => ({ webhooks: "config", webhooksEnabled: toml.webhooksEnabled, apiAutoExposeNewTables: toml.baseline.apiAutoExposeNewTables, diff --git a/apps/cli/src/command-internal/stack-catalog-setup.integration.test.ts b/apps/cli/src/command-internal/stack-catalog-setup.integration.test.ts index a750f7389b..c5ad4cff40 100644 --- a/apps/cli/src/command-internal/stack-catalog-setup.integration.test.ts +++ b/apps/cli/src/command-internal/stack-catalog-setup.integration.test.ts @@ -128,7 +128,7 @@ describe("stack catalog setup", { timeout: 180_000 }, () => { args: ["--dbname", databaseUrl, "-At"], stdin: Stream.make( new TextEncoder().encode( - "select coalesce(to_regclass('auth.users')::text,'missing'), coalesce(to_regclass('auth.sessions')::text,'missing'), coalesce(to_regclass('storage.objects')::text,'missing'), coalesce(to_regclass('storage.s3_multipart_uploads')::text,'missing'), coalesce(to_regclass('realtime.messages')::text,'missing'), coalesce(to_regclass('realtime.subscription')::text,'missing'), coalesce(to_regclass('public.catalog_overlay')::text,'missing'), coalesce(to_regprocedure('supabase_functions.http_request()')::text,'missing');", + "select coalesce(to_regclass('auth.users')::text,'missing'), coalesce(to_regclass('auth.sessions')::text,'missing'), coalesce(to_regclass('storage.objects')::text,'missing'), coalesce(to_regclass('storage.s3_multipart_uploads')::text,'missing'), coalesce(to_regclass('realtime.messages')::text,'missing'), coalesce(to_regclass('realtime.subscription')::text,'missing'), coalesce(to_regclass('public.catalog_overlay')::text,'missing'), coalesce(to_regprocedure('supabase_functions.http_request()')::text,'missing'), (select tableowner from pg_tables where tablename = 'catalog_overlay');", ), ), stdout: (bytes) => @@ -139,7 +139,7 @@ describe("stack catalog setup", { timeout: 180_000 }, () => { ); expect(query.exitCode, errors.join("")).toBe(0); expect(rows.join("").trim()).toBe( - "users|sessions|storage.objects|storage.s3_multipart_uploads|realtime.messages|realtime.subscription|catalog_overlay|supabase_functions.http_request()", + "users|sessions|storage.objects|storage.s3_multipart_uploads|realtime.messages|realtime.subscription|catalog_overlay|supabase_functions.http_request()|postgres", ); // pg_net queues webhook requests under the image's function policy. const pgNet: Array = []; diff --git a/apps/cli/src/command-internal/stack-catalog-setup.ts b/apps/cli/src/command-internal/stack-catalog-setup.ts index a55c0a0a3c..42d39fe090 100644 --- a/apps/cli/src/command-internal/stack-catalog-setup.ts +++ b/apps/cli/src/command-internal/stack-catalog-setup.ts @@ -64,7 +64,8 @@ export interface StackCatalogSetupInput { readonly databaseServices: ReadonlyArray; readonly selection: ArtifactSelection; }; - readonly overlay: StackCatalogOverlay; + /** Project SQL for a first setup; omitted when only the catalog changes. */ + readonly overlay?: StackCatalogOverlay; } const catalogError = (cause: unknown): StackCatalogSetupError => @@ -185,12 +186,18 @@ const applyCatalog = Effect.fn("StackCatalogSetup.apply")(function* ( .makeTempDirectoryScoped({ prefix: "supabase-stack-catalog-sql-" }) .pipe(Effect.mapError(catalogError)); yield* ensureStackWebhookSchema(session, fs, path, sqlPath); - yield* applyDatabaseOverlay(session, fs, path, input.overlay.workdir, { - webhooksEnabled: input.overlay.webhooksEnabled, - apiAutoExposeNewTables: input.overlay.apiAutoExposeNewTables, - vault: input.overlay.vault, - webhooks: input.overlay.webhooks, - announceRoles: input.overlay.announceRoles, + const { overlay } = input; + if (overlay === undefined) return; + const projectSession = yield* dbConn.connect( + { ...connection, user: "postgres" }, + { isLocal: true, dnsResolver: "native" }, + ); + yield* applyDatabaseOverlay(projectSession, fs, path, overlay.workdir, { + webhooksEnabled: overlay.webhooksEnabled, + apiAutoExposeNewTables: overlay.apiAutoExposeNewTables, + vault: overlay.vault, + webhooks: overlay.webhooks, + announceRoles: overlay.announceRoles, }).pipe(Effect.withSpan("StackCatalogSetup.applyOverlay")); }), ); diff --git a/apps/cli/src/command-internal/stack-config.ts b/apps/cli/src/command-internal/stack-config.ts index 23c8f839e7..785df05877 100644 --- a/apps/cli/src/command-internal/stack-config.ts +++ b/apps/cli/src/command-internal/stack-config.ts @@ -6,7 +6,10 @@ import { DEFAULT_LOCAL_S3_SECRET_ACCESS_KEY, DEFAULT_SIGNING_KEY, } from "@supabase/stack/defaults"; -import { type ServiceCreationInput as ServiceCreationType } from "@supabase/stack/effect"; +import { + apiTlsContext, + type ServiceCreationInput as ServiceCreationType, +} from "@supabase/stack/effect"; import { type ArtifactSelection } from "@supabase/stack/internal/artifacts"; import { Effect, Data, FileSystem, Option, Path, Redacted, Schema } from "effect"; import { SecureRandom } from "effect/crypto"; @@ -23,6 +26,7 @@ import { CLI_VERSION } from "../shared/cli/version.ts"; import { decryptSecretMap } from "../shared/config/vault-decrypt.ts"; import { toEdgeRuntimeSecretsEnv } from "../shared/functions/functions-config.ts"; import { + configLoadFailureSuggestion, describeConfigLoadFailure, loadResolvedConfigContext, resolvePasskeyWebauthn, @@ -44,7 +48,18 @@ import { resolveAuthExternalProviders, } from "./local-config-values.ts"; import { generateAsymmetricLocalJwt } from "./local-jwt.ts"; -import { resolveEmailTemplatePaths } from "./config-validate.ts"; +import { + apiTlsCertReadErrorMessage, + apiTlsKeyReadErrorMessage, + apiTlsPairErrorMessage, + resolveApiTlsPath, + resolveEmailTemplatePaths, + validateApiTlsPresence, +} from "./config-validate.ts"; +import { + KONG_LOCAL_TLS_CERT, + KONG_LOCAL_TLS_KEY, +} from "../commands/start/templates/kong-local-tls.ts"; import { recordOrioleDbTelemetry } from "./db-image.ts"; import { resolveRemoteJwks, @@ -61,12 +76,17 @@ import { /** A config error suitable for a stack command's user-facing boundary. */ export class StackConfigError extends Data.TaggedError("StackConfigError")<{ readonly message: string; + readonly suggestion?: string; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { return actionability.invalidConfig; } } +/** The remediation a stack config failure carries, for the command error that reports it. */ +export const stackConfigSuggestion = (error: unknown): string | undefined => + error instanceof StackConfigError ? error.suggestion : undefined; + interface StackStartConfig { /** The artifact pins every creation of this command carries. */ readonly selection: ArtifactSelection; @@ -74,6 +94,11 @@ interface StackStartConfig { stackId: string, ) => Effect.Effect, StackConfigError>; readonly source: CliConfig; + /** Reads the PEM pair the API listener serves HTTPS with, when `[api.tls]` is enabled. */ + readonly apiTls: Effect.Effect< + { readonly cert: string; readonly key: string } | undefined, + StackConfigError + >; readonly projectEnvValues: Readonly>; readonly originAt: CliConfigMaterialized["originAt"]; readonly remoteJwks: Effect.Effect; @@ -169,7 +194,6 @@ export const stackEndpointKey = (service: string, endpoint: string): StackEndpoi export const stackMajorVersionKey: StackEndpointKey = CliConfigKeys.db.majorVersion; const unsupportedConfigPaths = [ - { path: "api.tls", active: (config: CliConfig) => config.api.enabled }, { path: "analytics.gcp_project_id", active: (config: CliConfig) => config.analytics.enabled }, { path: "analytics.gcp_project_number", @@ -177,7 +201,6 @@ const unsupportedConfigPaths = [ }, { path: "analytics.gcp_jwt_path", active: (config: CliConfig) => config.analytics.enabled }, { path: "edge_runtime.deno_version", active: (config: CliConfig) => config.edge_runtime.enabled }, - { path: "storage.analytics", active: (config: CliConfig) => config.storage.enabled }, ...(["s3_host", "s3_region", "s3_access_key", "s3_secret_key"] as const).map((key) => ({ path: `experimental.${key}`, // Legacy Compose forwards these to OrioleDB; the stack does not, so fail rather than drop them. @@ -243,12 +266,6 @@ const configValidationError = (config: CliConfig): string | undefined => { } if (config.analytics.enabled && config.analytics.backend !== "postgres") return "analytics.backend must be postgres for the experimental stack"; - if ( - config.storage.enabled && - config.storage.vector.enabled && - Object.keys(config.storage.vector.buckets).length > 0 - ) - return "storage.vector settings are unsupported by the experimental stack"; if (config.db.major_version !== 15 && config.db.major_version !== 17) return "db.major_version must be 15 or 17 for the experimental stack"; @@ -279,7 +296,11 @@ export const loadStackConfig = Effect.fn("StackConfig.load")( Option.fromNullishOr(opts?.projectRef), ).pipe( Effect.mapError( - (cause) => new StackConfigError({ message: describeConfigLoadFailure(cause) }), + (cause) => + new StackConfigError({ + message: describeConfigLoadFailure(cause), + suggestion: configLoadFailureSuggestion(cause), + }), ), ); const { originAt } = resolvedConfig.materialized; @@ -320,6 +341,52 @@ export const loadStackConfig = Effect.fn("StackConfig.load")( ); const path = yield* Path.Path; const { supabaseHome } = yield* CommandSettings; + /* Like legacy: both configured paths, joined to `supabase/`, else the embedded local pair. */ + const tls = validatedConfig.api.tls; + const certPath = tls.cert_path ?? ""; + const keyPath = tls.key_path ?? ""; + const fs = yield* FileSystem.FileSystem; + const readTls = (file: string, message: (cause: unknown) => string) => + fs + .readFileString(resolveApiTlsPath(path, projectRoot, file)) + .pipe( + Effect.mapError( + (cause) => new StackConfigError({ message: message(cause.reason.cause ?? cause) }), + ), + ); + /* Read only by the start that applies TLS; other commands use the pair saved at start. */ + const apiTls = Effect.gen(function* () { + if (!tls.enabled) return undefined; + /* Like legacy, a disabled `[api]` still serves https, on the embedded pair. */ + if (!validatedConfig.api.enabled) + return { cert: KONG_LOCAL_TLS_CERT, key: KONG_LOCAL_TLS_KEY }; + yield* Effect.try({ + try: () => validateApiTlsPresence(tls.cert_path, tls.key_path), + catch: (cause) => + new StackConfigError({ + message: cause instanceof Error ? cause.message : String(cause), + }), + }); + if (certPath === "") return { cert: KONG_LOCAL_TLS_CERT, key: KONG_LOCAL_TLS_KEY }; + const pair = { + cert: yield* readTls(certPath, apiTlsCertReadErrorMessage), + key: yield* readTls(keyPath, apiTlsKeyReadErrorMessage), + }; + /* Proven usable here, so start never fails on it after binding. */ + yield* apiTlsContext(pair).pipe( + Effect.mapError( + (error) => + new StackConfigError({ + message: apiTlsPairErrorMessage( + resolveApiTlsPath(path, projectRoot, certPath), + resolveApiTlsPath(path, projectRoot, keyPath), + error.cause, + ), + }), + ), + ); + return pair; + }); const auth = validatedConfig.auth; const issuer = yield* Effect.try({ try: () => { @@ -573,7 +640,7 @@ export const loadStackConfig = Effect.fn("StackConfig.load")( ), ).pipe( Effect.map((templates) => templates.flat()), - Effect.provideService(FileSystem.FileSystem, yield* FileSystem.FileSystem), + Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path), Effect.mapError(toStackConfigError), ); @@ -633,6 +700,9 @@ export const loadStackConfig = Effect.fn("StackConfig.load")( schemas: validatedConfig.api.schemas.join(","), extraSearchPath: validatedConfig.api.extra_search_path.join(","), maxRows: validatedConfig.api.max_rows, + ...(validatedConfig.api.db_pool === undefined + ? {} + : { dbPool: validatedConfig.api.db_pool }), ...(validatedConfig.api.external_url === undefined ? {} : { externalApiUrl: validatedConfig.api.external_url }), @@ -776,6 +846,7 @@ export const loadStackConfig = Effect.fn("StackConfig.load")( selection, creations: createCreations, source: validatedConfig, + apiTls, projectEnvValues, originAt, remoteJwks, diff --git a/apps/cli/src/command-internal/stack-shadow-cache.ts b/apps/cli/src/command-internal/stack-shadow-cache.ts index 6c49ddfddd..39dcdfbe83 100644 --- a/apps/cli/src/command-internal/stack-shadow-cache.ts +++ b/apps/cli/src/command-internal/stack-shadow-cache.ts @@ -52,7 +52,7 @@ export const stackShadowCacheEntry = Effect.fn("StackShadowCache.entry")(functio enabled ? pinKey(pin) : Effect.succeed(""); const keyInputs: ShadowCacheKeyInputs = { postgresImage: yield* encodeKeyParts([ - "stack-v3", + "stack-v4", runtime, platform, arch, diff --git a/apps/cli/src/command-internal/stack-storage.ts b/apps/cli/src/command-internal/stack-storage.ts index 3b0cec84c5..6460f718a3 100644 --- a/apps/cli/src/command-internal/stack-storage.ts +++ b/apps/cli/src/command-internal/stack-storage.ts @@ -3,6 +3,7 @@ * endpoint; lazy Storage members may be woken by the first gateway request. */ +import { X509Certificate } from "node:crypto"; import { Data, Effect, FileSystem, Match, Option, Path } from "effect"; import type { Observation, ServiceInstance, Stack } from "@supabase/stack/effect"; import { @@ -63,10 +64,14 @@ const capabilityState = (observation: Observation | undefined) => { return observation.lifecycle; }; -/** Resolves bucket-seeding credentials from a configured Storage instance. */ +/** + * Resolves bucket-seeding credentials from a configured Storage instance; `apiCert` is the + * certificate the stack saved at start, trusted while its API serves HTTPS. + */ export const stackStorageCredentialsFor = ( storage: ServiceInstance<"storage">, serviceRoleKey: string, + apiCert: string | undefined, ): Effect.Effect => storage.status.pipe( Effect.mapError((cause) => new StackStorageUnavailableError({ message: cause.message })), @@ -81,7 +86,7 @@ export const stackStorageCredentialsFor = ( return Effect.fail( new StackStorageUnavailableError({ message: describeStorageCapability(observation) }), ); - return storageCredentialsFrom(observation, serviceRoleKey); + return storageCredentialsFrom(observation, serviceRoleKey, apiCert); }, ), ); @@ -128,20 +133,42 @@ const notRunningSuggestion = (lifecycle: "starting" | "stopping" | "stopped"): s Match.exhaustive, ); +/* Self-signed means it is its own issuer and verifies under its own key; unparsable is not. */ +const selfSigned = (pem: string): Effect.Effect => + Effect.try(() => { + const cert = new X509Certificate(pem); + return cert.subject === cert.issuer && cert.verify(cert.publicKey); + }).pipe(Effect.orElseSucceed(() => false)); + +/* A saved cert with a self-signed root becomes the only trusted CA; a CA-issued one is verified + against the default trust store and `NODE_EXTRA_CA_CERTS`. */ +const savedApiCa = (apiCert: string): Effect.Effect => + Effect.forEach( + apiCert.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/gu) ?? [], + selfSigned, + ).pipe(Effect.map((results) => (results.includes(true) ? apiCert : undefined))); + +/* An HTTPS endpoint never uses `config.toml`'s current cert; trust follows the saved one. */ const storageCredentialsFrom = ( observation: Observation, serviceRoleKey: string, + apiCert: string | undefined, ): Effect.Effect => { const endpoint = observation.endpoints.find(({ name }) => name === "http"); return endpoint === undefined ? Effect.fail( new StackStorageCapabilityError({ message: "The stack exposes no Storage endpoint." }), ) - : Effect.succeed({ - baseUrl: `http://${endpoint.host}:${endpoint.port}`, - apiKey: serviceRoleKey, - localKongCa: undefined, - }); + : (endpoint.scheme === "https" && apiCert !== undefined + ? savedApiCa(apiCert) + : Effect.undefined + ).pipe( + Effect.map((localKongCa) => ({ + baseUrl: `${endpoint.scheme ?? "http"}://${endpoint.host}:${endpoint.port}`, + apiKey: serviceRoleKey, + localKongCa, + })), + ); }; /** Resolves the composition Storage endpoint without launching the owner or any member. */ @@ -204,7 +231,10 @@ export const stackStorageEndpointFor = ( message: "The stack has no saved credentials.", suggestion: INSPECT_OR_RESTART_SUGGESTION, }); - return yield* storageCredentialsFrom(storageObservation, identity.serviceRoleKey); + const apiTls = yield* stack.apiTls.get.pipe( + Effect.mapError((cause) => new StackStorageUnavailableError({ message: cause.message })), + ); + return yield* storageCredentialsFrom(storageObservation, identity.serviceRoleKey, apiTls?.cert); }); /** Storage credentials for the project stack, opening it without launching the owner. */ diff --git a/apps/cli/src/command-internal/upgrade-suggest.ts b/apps/cli/src/command-internal/upgrade-suggest.ts index 23202f3593..7322fe59a5 100644 --- a/apps/cli/src/command-internal/upgrade-suggest.ts +++ b/apps/cli/src/command-internal/upgrade-suggest.ts @@ -1,6 +1,3 @@ -import { styleText } from "node:util"; - -import type { SupabaseApiError } from "@supabase/api/effect"; import { Effect, Option, type Redacted } from "effect"; import * as HttpClientError from "effect/http/HttpClientError"; import type * as HttpClientResponse from "effect/http/HttpClientResponse"; @@ -13,6 +10,7 @@ import { PropFeatureKey, PropOrgSlug, } from "../shared/telemetry/event-catalog.ts"; +import { upgradeHint } from "../shared/output/normalize-error.ts"; import { Output } from "../shared/output/output.service.ts"; import { parsePlanGateEnvelope } from "./http-errors.ts"; import { billingUrl } from "./profile.ts"; @@ -34,32 +32,10 @@ export const upgradeSuggestion = block("upgrade-suggest", [ }, ]); -function orgSlugFromUpgradeUrl(upgradeUrl: string): string { - const match = /\/org\/([^/]+)/.exec(upgradeUrl); - return match?.[1] ?? ""; -} - export function gateResponse(cause: unknown): HttpClientResponse.HttpClientResponse | undefined { return HttpClientError.isHttpClientError(cause) ? cause.response : undefined; } -export const gateMapError = - ( - opts: { readonly projectRef: string; readonly featureKey?: string }, - mapError: (cause: SupabaseApiError, upgradeSuggested: boolean) => Effect.Effect, - ) => - (cause: SupabaseApiError) => - Effect.gen(function* () { - const response = gateResponse(cause); - const upgradeSuggested = yield* suggestUpgrade({ - projectRef: opts.projectRef, - featureKey: opts.featureKey, - statusCode: response?.status ?? 0, - response, - }); - return yield* mapError(cause, upgradeSuggested); - }); - /** * Suggests an upgrade when a request fails with a plan-gate error. Never * fails the caller. @@ -91,8 +67,6 @@ export const suggestUpgrade = Effect.fn("UpgradeSuggest.check")(function* (opts: * an unauthenticated request), `undefined` uses the client's own token. */ readonly accessToken?: Option.Option>; - /** Set false for call sites that must not fire `EventUpgradeSuggested` (vanity check-availability). */ - readonly trackAnalytics?: boolean; }) { if (opts.statusCode < 400 || opts.statusCode >= 500) { return false; @@ -103,81 +77,64 @@ export const suggestUpgrade = Effect.fn("UpgradeSuggest.check")(function* (opts: const cliSettings = yield* CommandSettings; yield* Effect.annotateCurrentSpan("upgrade.gated", false); - let gate: - | { readonly billingUrl: string; readonly feature: string; readonly orgSlug: string } - | undefined; - if (opts.response !== undefined) { const body = yield* opts.response.json.pipe(Effect.option); const envelope = Option.isSome(body) ? parsePlanGateEnvelope(body.value) : undefined; if (envelope !== undefined) { - gate = { - billingUrl: envelope.upgrade_url, - feature: envelope.feature, - orgSlug: orgSlugFromUpgradeUrl(envelope.upgrade_url), - }; + // The error carries `entitlement`, so the command wrapper prints the hint and fires the event. + yield* Effect.annotateCurrentSpan("upgrade.gated", true); + return true; } } - if (gate === undefined) { - if (opts.featureKey === undefined || opts.featureKey === "") { - return false; - } - - if (opts.accessToken !== undefined && Option.isNone(opts.accessToken)) { - return false; - } + if (opts.featureKey === undefined || opts.featureKey === "") { + return false; + } - const api = yield* CommandPlatformApi; - const requestOptions = { - baseUrl: opts.apiUrl, - accessToken: opts.accessToken === undefined ? undefined : opts.accessToken.value, - }; - const project = yield* api.v1 - .getProject({ ref: opts.projectRef }, requestOptions) - .pipe(Effect.option); - if (Option.isNone(project)) { - return false; - } - const orgSlug = project.value.organization_slug; - if (orgSlug.length === 0) { - return false; - } + if (opts.accessToken !== undefined && Option.isNone(opts.accessToken)) { + return false; + } - const entitlements = yield* api.v1 - .getOrganizationEntitlements({ slug: orgSlug }, requestOptions) - .pipe(Effect.option); - if (Option.isNone(entitlements)) { - return false; - } + const api = yield* CommandPlatformApi; + const requestOptions = { + baseUrl: opts.apiUrl, + accessToken: opts.accessToken === undefined ? undefined : opts.accessToken.value, + }; + const project = yield* api.v1 + .getProject({ ref: opts.projectRef }, requestOptions) + .pipe(Effect.option); + if (Option.isNone(project)) { + return false; + } + const orgSlug = project.value.organization_slug; + if (orgSlug.length === 0) { + return false; + } - const gated = entitlements.value.entitlements.some( - (entry) => entry.feature.key === opts.featureKey && entry.hasAccess === false, - ); - if (!gated) { - return false; - } + const entitlements = yield* api.v1 + .getOrganizationEntitlements({ slug: orgSlug }, requestOptions) + .pipe(Effect.option); + if (Option.isNone(entitlements)) { + return false; + } - gate = { - billingUrl: billingUrl(cliSettings.profile, orgSlug), - feature: opts.featureKey, - orgSlug, - }; + const gated = entitlements.value.entitlements.some( + (entry) => entry.feature.key === opts.featureKey && entry.hasAccess === false, + ); + if (!gated) { + return false; } yield* Effect.annotateCurrentSpan("upgrade.gated", true); - const suggestion = `Your organization does not have access to this feature. Upgrade your plan: ${styleText("bold", gate.billingUrl)}`; if (output.format === "text") { - yield* output.raw(suggestion + "\n", "stderr"); + yield* output.raw(upgradeHint(billingUrl(cliSettings.profile, orgSlug)) + "\n", "stderr"); } - if (opts.trackAnalytics !== false) { - yield* analytics.capture(EventUpgradeSuggested, { - [PropFeatureKey]: gate.feature, - [PropOrgSlug]: gate.orgSlug, - }); - } + yield* analytics.capture(EventUpgradeSuggested, { + [PropFeatureKey]: opts.featureKey, + [PropOrgSlug]: orgSlug, + }); return true; }); diff --git a/apps/cli/src/command-internal/upgrade-suggest.unit.test.ts b/apps/cli/src/command-internal/upgrade-suggest.unit.test.ts index 4da09f494e..186c27c06b 100644 --- a/apps/cli/src/command-internal/upgrade-suggest.unit.test.ts +++ b/apps/cli/src/command-internal/upgrade-suggest.unit.test.ts @@ -258,20 +258,6 @@ describe("suggestUpgrade", () => { }).pipe(Effect.provide(layer)); }); - it.live("skips cli_upgrade_suggested analytics when trackAnalytics=false", () => { - const { layer, analytics, out } = setup(); - return Effect.gen(function* () { - yield* suggestUpgrade({ - projectRef: VALID_REF, - featureKey: "branching_limit", - statusCode: 402, - trackAnalytics: false, - }); - expect(analytics.captured).toHaveLength(0); - expect(out.stderrText).toContain("Upgrade your plan:"); - }).pipe(Effect.provide(layer)); - }); - const ENVELOPE_BODY = { message: "Branching is supported only on the Pro plan or above", error: { @@ -286,31 +272,29 @@ describe("suggestUpgrade", () => { return jsonResponse(request, status, body); } - it.live("envelope path suggests with zero API calls and envelope-derived telemetry", () => { - const { layer, out, analytics, api } = setup(); - return Effect.gen(function* () { - yield* suggestUpgrade({ - projectRef: VALID_REF, - featureKey: "branching_limit", - statusCode: 402, - response: gateResponse(402, ENVELOPE_BODY), - }); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "branching_persistent", org_slug: "env-org" }, - }, - ]); - expect(api.requests).toHaveLength(0); - }).pipe(Effect.provide(layer)); - }); + it.live( + "envelope path confirms the gate with zero API calls and leaves the hint and event to the command wrapper", + () => { + const { layer, out, analytics, api } = setup(); + return Effect.gen(function* () { + const suggested = yield* suggestUpgrade({ + projectRef: VALID_REF, + featureKey: "branching_limit", + statusCode: 402, + response: gateResponse(402, ENVELOPE_BODY), + }); + expect(suggested).toBe(true); + expect(out.stderrText).toBe(""); + expect(analytics.captured).toHaveLength(0); + expect(api.requests).toHaveLength(0); + }).pipe(Effect.provide(layer)); + }, + ); it.live("envelope path works without a featureKey (envelope-only sites)", () => { const { layer, out, analytics, api } = setup(); return Effect.gen(function* () { - yield* suggestUpgrade({ + const suggested = yield* suggestUpgrade({ projectRef: VALID_REF, statusCode: 400, response: gateResponse(400, { @@ -322,14 +306,10 @@ describe("suggestUpgrade", () => { }, }), }); + expect(suggested).toBe(true); expect(api.requests).toHaveLength(0); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "custom_domain", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).toBe(""); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); @@ -436,31 +416,4 @@ describe("suggestUpgrade", () => { expect(out.stderrText).toContain("/org/test-org/billing"); }).pipe(Effect.provide(layer)); }); - - it.live("envelope path respects json output mode (no stderr, telemetry fires)", () => { - const { layer, out, analytics } = setup({ format: "json" }); - return Effect.gen(function* () { - yield* suggestUpgrade({ - projectRef: VALID_REF, - statusCode: 402, - response: gateResponse(402, ENVELOPE_BODY), - }); - expect(out.stderrText).toBe(""); - expect(analytics.captured).toHaveLength(1); - }).pipe(Effect.provide(layer)); - }); - - it.live("envelope path respects trackAnalytics=false", () => { - const { layer, out, analytics } = setup(); - return Effect.gen(function* () { - yield* suggestUpgrade({ - projectRef: VALID_REF, - statusCode: 402, - response: gateResponse(402, ENVELOPE_BODY), - trackAnalytics: false, - }); - expect(analytics.captured).toHaveLength(0); - expect(out.stderrText).toContain("Upgrade your plan:"); - }).pipe(Effect.provide(layer)); - }); }); diff --git a/apps/cli/src/commands/branches/branches.errors.ts b/apps/cli/src/commands/branches/branches.errors.ts index 3b50c50be4..be68eb94e7 100644 --- a/apps/cli/src/commands/branches/branches.errors.ts +++ b/apps/cli/src/commands/branches/branches.errors.ts @@ -48,19 +48,14 @@ export class BranchesCreateUnexpectedStatusError extends Data.TaggedError( readonly status: number; readonly body: string; readonly message: string; - readonly upgradeSuggested?: boolean; readonly entitlement?: PlanGateEntitlement; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { - // A non-gated 409 means the branch name already exists (user input, not a raw API status); - // the gate check stays ahead so a plan-limited 409 still classifies as plan_limit. - if (this.upgradeSuggested !== true && this.status === 409) { + // A 409 means the branch name already exists (user input, not a raw API status). + if (this.status === 409) { return { ...actionability.invalidInput, fingerprint_suffix: "conflict" }; } - return statusCodeActionability(this.status, { - upgradeSuggested: this.upgradeSuggested, - notFoundIsInvalidInput: true, - }); + return statusCodeActionability(this.status, { notFoundIsInvalidInput: true }); } } @@ -185,12 +180,10 @@ export class BranchesUpdateUnexpectedStatusError extends Data.TaggedError( readonly status: number; readonly body: string; readonly message: string; - readonly upgradeSuggested?: boolean; readonly entitlement?: PlanGateEntitlement; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { return statusCodeActionability(this.status, { - upgradeSuggested: this.upgradeSuggested, notFoundIsInvalidInput: true, }); } diff --git a/apps/cli/src/commands/branches/branches.errors.unit.test.ts b/apps/cli/src/commands/branches/branches.errors.unit.test.ts index 999ae05c5a..93de74ad4c 100644 --- a/apps/cli/src/commands/branches/branches.errors.unit.test.ts +++ b/apps/cli/src/commands/branches/branches.errors.unit.test.ts @@ -10,6 +10,10 @@ import { } from "./branches.errors.ts"; const body = { body: "not found", message: "boom" }; +const gatedEntitlement = { + feature: "branching_limit", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", +}; describe("branch operation 404s classify as invalid input", () => { it("pause 404 → invalid input", () => { @@ -67,7 +71,7 @@ describe("gated branch operation 404s", () => { new BranchesUpdateUnexpectedStatusError({ status: 404, ...body, - upgradeSuggested: true, + entitlement: gatedEntitlement, }), ); expect(result.error_category).toBe("plan_limit"); @@ -79,7 +83,7 @@ describe("gated branch operation 404s", () => { new BranchesCreateUnexpectedStatusError({ status: 404, ...body, - upgradeSuggested: true, + entitlement: gatedEntitlement, }), ); expect(result.error_category).toBe("plan_limit"); @@ -102,7 +106,7 @@ describe("branches create 409 = duplicate branch name", () => { new BranchesCreateUnexpectedStatusError({ status: 409, ...body, - upgradeSuggested: true, + entitlement: gatedEntitlement, }), ); expect(result.error_category).toBe("plan_limit"); diff --git a/apps/cli/src/commands/branches/create/SIDE_EFFECTS.md b/apps/cli/src/commands/branches/create/SIDE_EFFECTS.md index a4b49f9ea3..08ed73bf36 100644 --- a/apps/cli/src/commands/branches/create/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/branches/create/SIDE_EFFECTS.md @@ -52,10 +52,10 @@ Target: hosted, consent default Yes — see [Command target](../../../../docs/co ## Telemetry Events Fired -| Event | When | Notable properties / groups | -| ----------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` (`--remote=` → the ref, a bare `--remote` → `true`; `--project-ref` whitelisted when ref-shaped, otherwise redacted) | -| `cli_upgrade_suggested` | on a 4xx whose body is the `entitlement_required` envelope | `{feature_key: "branching_limit", org_slug}` | +| Event | When | Notable properties / groups | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` (`--remote=` → the ref, a bare `--remote` → `true`; `--project-ref` whitelisted when ref-shaped, otherwise redacted) | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a 4xx whose body is the `entitlement_required` envelope | `{feature_key: "branching_limit", org_slug}` | ## Output diff --git a/apps/cli/src/commands/branches/create/create.handler.ts b/apps/cli/src/commands/branches/create/create.handler.ts index 3294498b62..1c3e939a34 100644 --- a/apps/cli/src/commands/branches/create/create.handler.ts +++ b/apps/cli/src/commands/branches/create/create.handler.ts @@ -15,7 +15,6 @@ import { } from "../../../command-internal/struct-output.encoders.ts"; import { mapHttpError } from "../../../command-internal/http-errors.ts"; import { resolveProjectTarget } from "../../../command-internal/target/resolve-project-target.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import { BRANCH_RESPONSE_SHAPE } from "../branches.response-shape.ts"; import { BranchesBranchNameEmptyError, @@ -27,7 +26,7 @@ import type { BranchesCreateFlags } from "./create.command.ts"; type CreatedBranch = typeof V1CreateABranchOutput.Type; -const mapCreateErrorRaw = mapHttpError({ +const mapCreateError = mapHttpError({ networkError: BranchesCreateNetworkError, statusError: BranchesCreateUnexpectedStatusError, networkMessage: (cause) => `failed to create preview branch: ${cause}`, @@ -102,24 +101,7 @@ export const branchesCreate = Effect.fn("branches.create")(function* (flags: Bra }) .pipe( Effect.tapError(() => creating?.fail() ?? Effect.void), - // Runs the plan-gate check before mapping the error, even for a gated 4xx. - Effect.catch( - gateMapError({ projectRef: ref }, (cause, upgradeSuggested) => - mapCreateErrorRaw(cause).pipe( - Effect.catchTag("BranchesCreateUnexpectedStatusError", (mapped) => - Effect.fail( - new BranchesCreateUnexpectedStatusError({ - status: mapped.status, - body: mapped.body, - message: mapped.message, - upgradeSuggested, - entitlement: mapped.entitlement, - }), - ), - ), - ), - ), - ), + Effect.catch(mapCreateError), ); yield* creating?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/branches/create/create.integration.test.ts b/apps/cli/src/commands/branches/create/create.integration.test.ts index 21bca71f14..cf66f0fd53 100644 --- a/apps/cli/src/commands/branches/create/create.integration.test.ts +++ b/apps/cli/src/commands/branches/create/create.integration.test.ts @@ -409,7 +409,7 @@ describe("branches create integration", () => { }).pipe(Effect.provide(layer)); }); - it.effect("envelope on 402 suggests upgrade with no extra API calls", () => { + it.effect("fails a 402 envelope with its entitlement and no extra API calls", () => { const { layer, out, analytics, api } = setup({ status: 402, response: { @@ -422,20 +422,20 @@ describe("branches create integration", () => { }, }); return Effect.gen(function* () { - const exit = yield* Effect.exit( + const error = yield* Effect.flip( branchesCreate({ ...baseFlags, name: Option.some("feat-x") }), ); - expect(Exit.isFailure(exit)).toBe(true); + expect(error).toMatchObject({ + entitlement: { + feature: "branching_limit", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); expect(api.requests).toHaveLength(1); expect(api.requests[0]?.url).toContain("/branches"); assertPermissionDrift({ command: "branches create", requests: api.requests, exact: true }); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "branching_limit", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); diff --git a/apps/cli/src/commands/branches/unpause/SIDE_EFFECTS.md b/apps/cli/src/commands/branches/unpause/SIDE_EFFECTS.md index 2398ff13d3..20cfe44ac9 100644 --- a/apps/cli/src/commands/branches/unpause/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/branches/unpause/SIDE_EFFECTS.md @@ -43,14 +43,17 @@ Same auth fallback chain as every Management-API command. Project-ref discovery ## Telemetry Events Fired -| Event | When | Notable properties | -| ---------------------- | ------------------------------------------ | ----------------------------------- | -| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` | +| Event | When | Notable properties | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a restore 4xx whose body is the `entitlement_required` envelope | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`) | ## Output Silent on success in every mode (the handler writes nothing itself; the target banner and any `Confirmed by --yes` line go to stderr). +A restore denied with the `entitlement_required` envelope prints the upgrade hint on stderr before the error in text mode. + ## Notes - `--remote=` names the parent project; with no selector or a bare `--remote` the parent comes from the chain above. A branch name or UUID is rejected with `` `supabase branches unpause` acts on a parent project, so --remote takes its project ref, not a branch name. Use --remote=. `` The branch itself stays a positional argument. diff --git a/apps/cli/src/commands/branches/update/SIDE_EFFECTS.md b/apps/cli/src/commands/branches/update/SIDE_EFFECTS.md index 3cff71b826..0e649d9dfb 100644 --- a/apps/cli/src/commands/branches/update/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/branches/update/SIDE_EFFECTS.md @@ -15,16 +15,14 @@ Same auth fallback chain as every Management-API command. Project-ref discovery ## API Routes -| Method | Path | Auth | When | Request body | Response | -| ------- | ----------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------- | -| `GET` | `/v1/projects/{ref}/branches/{name}` | Bearer token | branch input is not a UUID and not a `^[a-z]{20}$` ref pattern | none | `{project_ref}` | -| `GET` | `/v1/branches/{branch_id_or_ref}` | Bearer token | branch input is a UUID | none | `{ref}` | -| `PATCH` | `/v1/branches/{branch_id_or_ref}` | Bearer token | always | `{branch_name?, git_branch?, persistent?, status?, notify_url?}` (only set flags emitted) | full `BranchResponse` | -| `GET` | `/v1/projects/{ref}` (on 4xx gated) | Bearer token | upgrade-suggest path | none | `{organization_slug}` | -| `GET` | `/v1/organizations/{slug}/entitlements` (gated) | Bearer token | upgrade-suggest path | none | `[{feature: {key}, hasAccess, ...}]` | -| `GET` | `/v1/projects/{ref}/branches` | Bearer token | branch argument omitted or empty and stdin is a TTY (branch picker) | none | `[{name, project_ref, …}]` | -| `GET` | `/v1/projects` | Bearer token | no project ref from `--remote=`, `SUPABASE_PROJECT_ID` or `.temp/project-ref`, with stdin and stdout TTYs and a non-JSON output format (project picker) | none | `[{id, name, organization_slug, region, …}]` | -| `GET` | `/v1/projects/{ref}` | Bearer token | linked-project cache miss only (best-effort, after the command) | none | `{ref, name, organization_id, organization_slug}` | +| Method | Path | Auth | When | Request body | Response | +| ------- | ------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------------------------------------------------- | +| `GET` | `/v1/projects/{ref}/branches/{name}` | Bearer token | branch input is not a UUID and not a `^[a-z]{20}$` ref pattern | none | `{project_ref}` | +| `GET` | `/v1/branches/{branch_id_or_ref}` | Bearer token | branch input is a UUID | none | `{ref}` | +| `PATCH` | `/v1/branches/{branch_id_or_ref}` | Bearer token | always | `{branch_name?, git_branch?, persistent?, status?, notify_url?}` (only set flags emitted) | full `BranchResponse` | +| `GET` | `/v1/projects/{ref}/branches` | Bearer token | branch argument omitted or empty and stdin is a TTY (branch picker) | none | `[{name, project_ref, …}]` | +| `GET` | `/v1/projects` | Bearer token | no project ref from `--remote=`, `SUPABASE_PROJECT_ID` or `.temp/project-ref`, with stdin and stdout TTYs and a non-JSON output format (project picker) | none | `[{id, name, organization_slug, region, …}]` | +| `GET` | `/v1/projects/{ref}` | Bearer token | linked-project cache miss only (best-effort, after the command) | none | `{ref, name, organization_id, organization_slug}` | ## Environment Variables @@ -45,10 +43,10 @@ Same auth fallback chain as every Management-API command. Project-ref discovery ## Telemetry Events Fired -| Event | When | Notable properties | -| ----------------------- | ---------------------------------------------------- | ------------------------------------------------- | -| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` | -| `cli_upgrade_suggested` | on 4xx with `branching_persistent` entitlement gated | `{feature_key: "branching_persistent", org_slug}` | +| Event | When | Notable properties | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a 4xx whose body is the `entitlement_required` envelope | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`) | ## Output @@ -61,5 +59,4 @@ For `--output {json,yaml,toml,env}`, the header goes to stderr followed by the e ## Notes - `--remote=` names the parent project; with no selector or a bare `--remote` the parent comes from the chain above. A branch name or UUID is rejected with `` `supabase branches update` acts on a parent project, so --remote takes its project ref, not a branch name. Use --remote=. `` The branch itself stays a positional argument. -- The upgrade-suggest call uses the branch's own resolved project ref (`resolveBranchProjectRef`) — not the parent `--remote=` value — so the entitlements check is scoped to the branch's org. - **Consent.** Asks once, after the branch name or ID is resolved to its ref and before the PATCH, with default No: `Update preview branch `. The question also shows the branch project ref and each change that was requested (`--name`, `--git-branch`, `--persistent`, `--status`, `--notify-url`). diff --git a/apps/cli/src/commands/branches/update/update.command.ts b/apps/cli/src/commands/branches/update/update.command.ts index e7dae7809a..c6a1f6dba3 100644 --- a/apps/cli/src/commands/branches/update/update.command.ts +++ b/apps/cli/src/commands/branches/update/update.command.ts @@ -6,7 +6,6 @@ import { compose } from "../../../command-internal/command-permissions/model.ts" import { projectRefPicker } from "../../../config/project-ref.layer.ts"; import { branchPrompt } from "../branches.prompt.ts"; import { branchRef } from "../../../command-internal/branch-ref.resolver.ts"; -import { upgradeSuggestion } from "../../../command-internal/upgrade-suggest.ts"; import { linkedProjectCache } from "../../../telemetry/linked-project-cache.layer.ts"; import { withJsonErrorHandling } from "../../../shared/output/json-error-handling.ts"; import { managementApiRuntimeLayer } from "../../../command-internal/management-api-runtime.layer.ts"; @@ -66,7 +65,6 @@ export const branchesUpdateCommand = Command.make("update", config).pipe( projectRefPicker, branchPrompt, branchRef, - upgradeSuggestion, linkedProjectCache, ), ), diff --git a/apps/cli/src/commands/branches/update/update.handler.ts b/apps/cli/src/commands/branches/update/update.handler.ts index 947600a118..b403645fea 100644 --- a/apps/cli/src/commands/branches/update/update.handler.ts +++ b/apps/cli/src/commands/branches/update/update.handler.ts @@ -14,7 +14,6 @@ import { import { requireHostedMutationConsent } from "../../../command-internal/hosted-consent/hosted-consent.ts"; import { mapHttpError } from "../../../command-internal/http-errors.ts"; import { resolveProjectTarget } from "../../../command-internal/target/resolve-project-target.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import { BRANCH_RESPONSE_SHAPE } from "../branches.response-shape.ts"; import { BranchesUpdateNetworkError, @@ -79,26 +78,7 @@ export const branchesUpdate = Effect.fn("branches.update")(function* (flags: Bra }) .pipe( Effect.tapError(() => patching?.fail() ?? Effect.void), - // Scopes the entitlements check to the branch's own org via its resolved project ref. - Effect.catch( - gateMapError( - { projectRef: branchRef, featureKey: "branching_persistent" }, - (cause, upgradeSuggested) => - mapUpdateError(cause).pipe( - Effect.catchTag("BranchesUpdateUnexpectedStatusError", (mapped) => - Effect.fail( - new BranchesUpdateUnexpectedStatusError({ - status: mapped.status, - body: mapped.body, - message: mapped.message, - upgradeSuggested, - entitlement: mapped.entitlement, - }), - ), - ), - ), - ), - ), + Effect.catch(mapUpdateError), ); yield* patching?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/branches/update/update.integration.test.ts b/apps/cli/src/commands/branches/update/update.integration.test.ts index 3dabc2fecc..08afde478d 100644 --- a/apps/cli/src/commands/branches/update/update.integration.test.ts +++ b/apps/cli/src/commands/branches/update/update.integration.test.ts @@ -24,6 +24,7 @@ import type { BranchesUpdateFlags } from "./update.command.ts"; import { branchesUpdate } from "./update.handler.ts"; import { YesFlag } from "../../../command-internal/global-flags.ts"; import { TargetPolicy } from "../../../command-internal/target/target-policy.ts"; +import { classifyCliCauseActionability } from "../../../shared/telemetry/error-actionability.ts"; type UpdatedBranch = typeof V1UpdateABranchConfigOutput.Type; @@ -45,35 +46,6 @@ const UPDATED: UpdatedBranch = { with_data: false, }; -const ORG_SLUG = "test-org"; - -function projectResponse(ref: string = BRANCH_REF) { - return { - id: ref, - ref, - organization_id: "org", - organization_slug: ORG_SLUG, - name: "Test", - region: "us-east-1", - created_at: "2026-01-01T00:00:00Z", - status: "ACTIVE_HEALTHY" as const, - database: { host: "h", version: "15", postgres_engine: "15", release_channel: "ga" }, - }; -} - -function entitlementResponse(opts: { readonly featureKey: string; readonly hasAccess: boolean }) { - return { - entitlements: [ - { - feature: { key: opts.featureKey, type: "boolean" as const }, - hasAccess: opts.hasAccess, - type: "boolean" as const, - config: { enabled: !opts.hasAccess }, - }, - ], - }; -} - // Resolver's UUID-path response; its `ref` feeds the PATCH's branch_id_or_ref, so it must // stay UUID-shaped to satisfy the oneOf union. const BRANCH_CONFIG = { @@ -316,87 +288,88 @@ describe("branches update integration", () => { }).pipe(Effect.provide(layer)); }); - // Exercises the production-shape branchRef end-to-end; the upgrade-suggest helper must - // receive the resolved branch's project ref, not the parent ref. it.effect( - "fires cli_upgrade_suggested with the branch ref + branching_persistent on 4xx gated", + "fails a persistent-branch 402 envelope with its entitlement and no extra API calls", () => { const out = mockOutput({ format: "text" }); const analytics = mockAnalytics(); - const cliSettings = mockCommandSettings({ workdir: tempRoot.current }); - - // The gate's follow-up project and entitlements GETs share the PATCH's - // mockCommandPlatformApi handler. - const apiMock = mockCommandPlatformApi({ + const upgradeUrl = "https://supabase.com/dashboard/org/env-org/billing"; + const api = mockCommandPlatformApi({ handler: (request) => - Effect.sync(() => { - if (request.method === "PATCH" && request.url.includes("/v1/branches/")) { - return jsonResponse(request, 402, { message: "upgrade required" }); - } - if (request.method === "GET" && request.url.endsWith(`/v1/projects/${BRANCH_REF}`)) { - return jsonResponse(request, 200, projectResponse(BRANCH_REF)); - } - if ( - request.method === "GET" && - request.url.endsWith(`/v1/organizations/${ORG_SLUG}/entitlements`) - ) { - return jsonResponse( - request, - 200, - entitlementResponse({ - featureKey: "branching_persistent", - hasAccess: false, - }), - ); - } - return jsonResponse(request, 200, null); - }), + Effect.sync(() => + jsonResponse(request, 402, { + message: "Persistent branches are not available on your plan.", + error: { + code: "entitlement_required", + feature: "branching_persistent", + upgrade_url: upgradeUrl, + }, + }), + ), }); - const layer = buildRuntime({ out, - api: apiMock, - cliSettings, + api, + cliSettings: mockCommandSettings({ workdir: tempRoot.current }), analytics, }); return Effect.gen(function* () { - yield* Effect.exit( + const error = yield* Effect.flip( branchesUpdate({ ...baseFlags, branchId: Option.some(BRANCH_REF), persistent: Option.some(true), }), ); - const projectCall = apiMock.requests.find( - (r) => r.method === "GET" && r.url.endsWith(`/v1/projects/${BRANCH_REF}`), - ); - expect(projectCall).toBeDefined(); - const entitlementsCall = apiMock.requests.find((r) => - r.url.endsWith(`/v1/organizations/${ORG_SLUG}/entitlements`), - ); - expect(entitlementsCall).toBeDefined(); - expect(sequence(apiMock.requests)).toEqual([ - `PATCH ${API}/v1/branches/${BRANCH_REF}`, - `GET ${API}/v1/projects/${BRANCH_REF}`, - `GET ${API}/v1/organizations/${ORG_SLUG}/entitlements`, - ]); + expect(error).toMatchObject({ + entitlement: { feature: "branching_persistent", upgrade_url: upgradeUrl }, + }); + expect(sequence(api.requests)).toEqual([`PATCH ${API}/v1/branches/${BRANCH_REF}`]); assertPermissionDrift({ command: "branches update", activeFlags: { persistent: true }, - requests: apiMock.requests, + requests: api.requests, + exact: true, }); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "branching_persistent", org_slug: ORG_SLUG }, - }, - ]); - expect(out.stderrText).toContain("Upgrade your plan:"); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }, ); + it.effect("makes one request and suggests no upgrade on a 4xx without the envelope", () => { + const out = mockOutput({ format: "text" }); + const analytics = mockAnalytics(); + const api = mockCommandPlatformApi({ + handler: (request) => + Effect.sync(() => jsonResponse(request, 400, { message: "Invalid branch name" })), + }); + const layer = buildRuntime({ + out, + api, + cliSettings: mockCommandSettings({ workdir: tempRoot.current }), + analytics, + }); + + return Effect.gen(function* () { + const exit = yield* Effect.exit( + branchesUpdate({ + ...baseFlags, + branchId: Option.some(BRANCH_REF), + persistent: Option.some(true), + }), + ); + expect(Exit.isFailure(exit)).toBe(true); + if (Exit.isFailure(exit)) { + expect(classifyCliCauseActionability(exit.cause).error_category).not.toBe("plan_limit"); + } + expect(sequence(api.requests)).toEqual([`PATCH ${API}/v1/branches/${BRANCH_REF}`]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); + }).pipe(Effect.provide(layer)); + }); + it.effect( "updates the branch chosen from the pickers and fills the real linked-project cache", () => { diff --git a/apps/cli/src/commands/config/config.command.ts b/apps/cli/src/commands/config/config.command.ts index f672b6d619..b3b2856841 100644 --- a/apps/cli/src/commands/config/config.command.ts +++ b/apps/cli/src/commands/config/config.command.ts @@ -1,4 +1,5 @@ import { Command } from "effect/cli"; +import { configConvertCommand } from "./convert/convert.command.ts"; import { configDiffCommand } from "./diff/diff.command.ts"; import { configPullCommand } from "./pull/pull.command.ts"; import { configPushCommand } from "./push/push.command.ts"; @@ -6,5 +7,10 @@ import { configPushCommand } from "./push/push.command.ts"; export const configCommand = Command.make("config").pipe( Command.withDescription("Manage Supabase project configurations."), Command.withShortDescription("Manage project configurations"), - Command.withSubcommands([configDiffCommand, configPullCommand, configPushCommand]), + Command.withSubcommands([ + configConvertCommand, + configDiffCommand, + configPullCommand, + configPushCommand, + ]), ); diff --git a/apps/cli/src/commands/config/convert/SIDE_EFFECTS.md b/apps/cli/src/commands/config/convert/SIDE_EFFECTS.md new file mode 100644 index 0000000000..0c142fbce5 --- /dev/null +++ b/apps/cli/src/commands/config/convert/SIDE_EFFECTS.md @@ -0,0 +1,116 @@ +# `supabase config convert` + +## Files Read + +| Path | Format | When | +| ----------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------- | +| `/supabase/config.json[c]` | JSON/JSONC | always; parsed with the removed-key checks to detect a project already on JSON (no `.env*` file and no `[remotes.*]` read) | +| `/supabase/config.toml` | TOML | always; must be valid UTF-8; the backup is re-read after the move to detect a concurrent edit | +| `/.vscode/settings.json` | JSONC | only when it already exists; after the write, or with `--dry-run` to preview the change | +| `~/.supabase/telemetry.json` | JSON | always (telemetry state) | + +## Files Written + +| Path | Format | When | +| --------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `/supabase/config.jsonc` | JSONC | unless `--dry-run`; temp file then hard link (exclusive create without hard links), never replacing an existing file; mode of `config.toml` | +| `/supabase/config.toml` | — | moved to `supabase/config.toml.bak` (or the first free `config.toml.N.bak`) after `config.jsonc` is written | +| `/.vscode/settings.json` | JSONC | only when it already exists; after the write, or with `--dry-run` to preview the change | +| `~/.supabase/telemetry.json` | JSON | always (telemetry state) | + +## API Routes + +| Method | Path | Auth | Request body | Response (used fields) | +| ------ | ---- | ---- | ------------ | ---------------------- | +| — | — | — | — | — | + +## Environment Variables + +| Variable | Purpose | Required? | +| -------------------------------- | ---------------------------------- | --------- | +| `SUPABASE_WORKDIR` / `--workdir` | project root used exactly as given | no | +| `SUPABASE_HOME` | location of `telemetry.json` | no | + +## Exit Codes + +| Code | Condition | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `0` | converted (or `--dry-run` printed the document); warnings never change the exit code | +| `0` | only `config.json[c]` exists: nothing to convert, nothing written | +| `1` | `-o/--output` passed | +| `1` | `--workdir` is not a directory | +| `1` | no project config found, or it cannot be parsed (including malformed JSON or removed keys in `config.json[c]`) | +| `1` | `config.json` and `config.jsonc` both exist | +| `1` | `config.toml` exists next to `config.json[c]`, which takes precedence | +| `1` | conversion refused (not valid UTF-8, a TOML date, a non-finite float, failed re-parse check) | +| `1` | `config.toml` is a symbolic link, or `config.jsonc` is a dangling symbolic link; nothing is written | +| `1` | `config.jsonc` could not be written, or appeared while the command ran; an existing `config.jsonc` is never replaced and `config.toml` is kept | +| `1` | `config.toml` could not be moved to the backup; the new `config.jsonc` is removed while it still holds what the command wrote, and `config.toml` is kept | +| `1` | `config.toml` changed while the command ran; the backup holds the latest version and the message gives the restore command | +| `1` | the backup name could not be checked (nothing is written), or the backup could not be re-read after the move (`config.jsonc` and the backup are kept and the message gives the undo command) | + +## Output + +### `--output-format text` + +stdout is one report, printed after the files are written (colour only on a TTY, per `NO_COLOR`/`CLICOLOR`): + +```text +✓ Converted supabase/config.toml to supabase/config.jsonc + + Changes + + Created supabase/config.jsonc + > Moved supabase/config.toml to supabase/config.toml.bak + ~ Updated .vscode/settings.json (trusts https://supabase.com/schemas/) + + ℹ 1 comment relocated + Comments inside nested arrays or inline tables move to the line above their key. + line 13 → api.extra # first + + ⚠ Could not update .vscode/settings.json + . + Add "https://supabase.com/schemas/": true under "json.schemaDownload.trustedDomains" to trust the config schema. + + ⚠ Compatibility + Supabase CLI versions before 3.1.0 ignore config.jsonc and run with defaults. + Upgrade the Supabase CLI on every machine and CI job that uses this project. + + To undo: + mv -- supabase/config.toml.bak supabase/config.toml && rm -- supabase/config.jsonc +``` + +The `~ Updated` line appears only when the settings changed, the `ℹ` section only for comments in nested arrays or inline tables (`N comments relocated` when more than one), and the VS Code warning only when the settings file cannot be parsed, written, or edited without dropping its comments. A failed write prints no report. + +With only `config.json[c]` present, stdout is `supabase/config.jsonc is already the project config; nothing to convert.` (naming the actual file). + +With `--dry-run`, stdout is the converted JSONC only; stderr gets a blank line and the same report headed `✓ Config conversion preview` / ` Dry run. No files were changed.`, with `Planned changes`, `Create`/`Move`/`Update`, and `To undo after converting:`. + +### `--output-format json` + +`output.success("Converted supabase/config.toml to supabase/config.jsonc.", payload)` with +`path`, `converted: true`, `backup` (the backup path), `schema`, `moved_comments[{line,key,text}]`, +`vscode_settings_updated`, `min_cli_version`, `warnings[]`. With `--dry-run` the message is the +dry-run line, `converted: false`, `dry_run: true` and `content` carry the document, `would_backup` and +`would_update_vscode_settings` replace `backup` and `vscode_settings_updated`, the compatibility +warning says `To undo after converting, run:`, and nothing is written. With only `config.json[c]` present the payload is `{ converted: false, path }`. Warnings +appear only in `warnings`. + +### `--output-format stream-json` + +Same structured result as `json`, delivered as an NDJSON `result` event. + +## Notes + +- The only flag is `--dry-run`; there is no confirmation prompt and no `--force`. +- Nothing is deleted: `config.toml` is renamed next to the new file, outside `supabase/.temp` (which `unlink` and `projects delete` remove), so the user commits or deletes the backup themselves. The undo command names the backup actually used, with paths relative to the current directory (quoted when the shell would split them; on Windows a PowerShell `Move-Item`/`Remove-Item` command); every other message names files relative to the project root. +- Assumes no other process edits `supabase/` while it runs; it detects a changed `config.toml` or a `config.jsonc` that appears, but does not lock. +- The conversion parses `config.toml` only (no env resolution, no schema decode), so the JSONC + document carries the same raw values. The result is re-parsed and compared before anything is + written. +- `$schema` comes from a leading `#:schema` directive, an existing `"$schema"` key, or the current + hosted schema URL. +- Commented-out TOML examples (`# key = value`, `# [table]` plus its keys) become commented-out JSONC members, so removing the `//` prefixes of one member yields valid JSONC; other comments are copied as prose. +- Comments inside multi-line arrays of plain values stay beside their elements; comments inside nested arrays or inline tables move to the line above their key and are reported. +- Skips the VS Code trusted-domain edit when the domain is already listed, whatever its value. +- `.vscode/settings.json` is never created. +- `-o/--output` is rejected in favour of `--output-format`. diff --git a/apps/cli/src/commands/config/convert/convert.command.ts b/apps/cli/src/commands/config/convert/convert.command.ts new file mode 100644 index 0000000000..706f72a06f --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.command.ts @@ -0,0 +1,57 @@ +import type * as CliCommand from "effect/cli/Command"; +import { Layer } from "effect"; +import { Command, Flag } from "effect/cli"; + +import { withPermissions } from "../../../command-internal/command-permissions/command-permissions.annotation.ts"; +import { commandSettingsLayer } from "../../../config/command-settings.layer.ts"; +import { debugLoggerLayer } from "../../../command-internal/debug-logger.layer.ts"; +import { GLOBAL_OUTPUT_FORMATS } from "../../../command-internal/global-flags.ts"; +import { withTargetPolicy } from "../../../command-internal/target/target-policy.ts"; +import { withJsonErrorHandling } from "../../../shared/output/json-error-handling.ts"; +import { commandRuntimeLayer } from "../../../shared/runtime/command-runtime.layer.ts"; +import { withCommandTelemetry } from "../../../telemetry/command-telemetry.ts"; +import { telemetryStateLayer } from "../../../telemetry/telemetry-state.layer.ts"; +import { configConvert } from "./convert.handler.ts"; + +const config = { + dryRun: Flag.Boolean("dry-run").pipe( + Flag.withDescription("Print the converted config.jsonc to stdout without writing any file."), + Flag.withDefault(false), + ), +} as const; + +export type ConfigConvertFlags = CliCommand.Command.Config.Infer; + +const configConvertRuntimeLayer = Layer.mergeAll( + commandSettingsLayer.pipe(Layer.provide(debugLoggerLayer)), + telemetryStateLayer, + commandRuntimeLayer(["config", "convert"]), +); + +const configConvertHandler = (flags: ConfigConvertFlags) => + configConvert(flags).pipe( + // The handler rejects `-o/--output` itself with a pointer to `--output-format`. + withCommandTelemetry({ flags, outputFormats: GLOBAL_OUTPUT_FORMATS }), + withJsonErrorHandling, + ); + +export const configConvertCommand = Command.make("convert", config).pipe( + Command.withDescription( + "Converts supabase/config.toml to supabase/config.jsonc, carrying comments over, and moves the TOML file to supabase/config.toml.bak. Everyone on the project needs Supabase CLI 3.1.0 or later.", + ), + Command.withShortDescription("Convert config.toml to config.jsonc"), + Command.withExamples([ + { + command: "supabase config convert --dry-run", + description: "Preview the converted config.jsonc without writing it", + }, + { + command: "supabase config convert", + description: "Convert supabase/config.toml to supabase/config.jsonc", + }, + ]), + withPermissions({ operations: [], noApiEffectFlags: ["dry-run"] }), + Command.withHandler(configConvertHandler), + Command.provide(configConvertRuntimeLayer), + withTargetPolicy({ group: "local-only", consent: "none" }), +); diff --git a/apps/cli/src/commands/config/convert/convert.errors.ts b/apps/cli/src/commands/config/convert/convert.errors.ts new file mode 100644 index 0000000000..d8f256715e --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.errors.ts @@ -0,0 +1,69 @@ +import { Data } from "effect"; +import { + actionability, + type CliErrorActionabilityDeclaration, + ErrorActionabilityId, +} from "../../../shared/telemetry/error-actionability.ts"; + +/** The resolved `--workdir`/`SUPABASE_WORKDIR` doesn't exist or isn't a directory. */ +export class ConfigConvertWorkdirError extends Data.TaggedError("ConfigConvertWorkdirError")<{ + readonly message: string; +}> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.provideFlags; + } +} + +/** The project config is missing or cannot be parsed. */ +export class ConfigConvertLoadConfigError extends Data.TaggedError("ConfigConvertLoadConfigError")<{ + readonly message: string; +}> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.invalidConfig; + } +} + +/** `config.toml` coexists with `config.json`/`config.jsonc`, which takes precedence. */ +export class ConfigConvertAlreadyJsonError extends Data.TaggedError( + "ConfigConvertAlreadyJsonError", +)<{ readonly message: string }> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.invalidInput; + } +} + +/** The converter refused the document; `config.toml` is left untouched. */ +export class ConfigConvertUnsupportedError extends Data.TaggedError( + "ConfigConvertUnsupportedError", +)<{ readonly message: string }> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.invalidConfig; + } +} + +/** `config.toml` changed on disk between the read and the write. */ +export class ConfigConvertFileChangedError extends Data.TaggedError( + "ConfigConvertFileChangedError", +)<{ readonly message: string }> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return { ...actionability.invalidInput, fingerprint_suffix: "conflict" }; + } +} + +/** Writing `config.jsonc` or removing `config.toml` failed. */ +export class ConfigConvertWriteError extends Data.TaggedError("ConfigConvertWriteError")<{ + readonly message: string; +}> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return { ...actionability.permission, fingerprint_suffix: "filesystem" }; + } +} + +/** The `-o/--output` flag was passed; this command only supports `--output-format`. */ +export class ConfigConvertOutputFlagUnsupportedError extends Data.TaggedError( + "ConfigConvertOutputFlagUnsupportedError", +)<{ readonly message: string }> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.invalidInput; + } +} diff --git a/apps/cli/src/commands/config/convert/convert.format.ts b/apps/cli/src/commands/config/convert/convert.format.ts new file mode 100644 index 0000000000..97a955c8a0 --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.format.ts @@ -0,0 +1,265 @@ +import type { CliConfigConvertError, MovedTomlComment } from "@supabase/config/internal"; + +import { shellQuoteArgument, type ShellPlatform } from "../../../command-internal/shell-quote.ts"; + +export const CONFIG_JSONC_MIN_CLI_VERSION = "3.1.0"; + +export function dryRunMessage(vscodeWouldUpdate: boolean, backup: string): string { + return vscodeWouldUpdate + ? `Dry run: would write supabase/config.jsonc, move supabase/config.toml to ${backup}, and add the schema domain to .vscode/settings.json.` + : `Dry run: would write supabase/config.jsonc and move supabase/config.toml to ${backup}.`; +} + +export function alreadyConvertedMessage(jsonFile: string): string { + return `supabase/${jsonFile} is already the project config; nothing to convert.`; +} + +export function jsonPrecedenceMessage(jsonFile: string): string { + return `supabase/config.toml is ignored because supabase/${jsonFile} takes precedence. Delete supabase/${jsonFile} first to convert config.toml again.`; +} + +export const CONVERTED_MESSAGE = "Converted supabase/config.toml to supabase/config.jsonc."; + +/** The command that restores config.toml from `backup`, with paths prefixed by `root` (the project root relative to the cwd). */ +export function undoCommand(root: string, backup: string, platform: ShellPlatform): string { + const at = (file: string) => shellQuoteArgument(root === "" ? file : `${root}/${file}`, platform); + return platform === "windows" + ? `Move-Item -LiteralPath ${at(backup)} -Destination ${at("supabase/config.toml")}; if ($?) { Remove-Item -LiteralPath ${at("supabase/config.jsonc")} }` + : `mv -- ${at(backup)} ${at("supabase/config.toml")} && rm -- ${at("supabase/config.jsonc")}`; +} + +const COMPATIBILITY_LINES = [ + `Supabase CLI versions before ${CONFIG_JSONC_MIN_CLI_VERSION} ignore config.jsonc and run with defaults.`, + "Upgrade the Supabase CLI on every machine and CI job that uses this project.", +] as const; + +export function minVersionWarning(dryRun: boolean, undo: string): string { + return `${COMPATIBILITY_LINES.join(" ")} ${dryRun ? "To undo after converting" : "To undo"}, run: ${undo}`; +} + +const TRUSTED_DOMAIN = "https://supabase.com/schemas/"; + +const VSCODE_MANUAL_STEP = `Add "${TRUSTED_DOMAIN}": true under "json.schemaDownload.trustedDomains" to trust the config schema.`; + +function vscodeFailureWarning(detail: string): string { + return `Could not update .vscode/settings.json: ${detail}. ${VSCODE_MANUAL_STEP}`; +} + +export function refusalMessage(error: CliConfigConvertError): string { + const location = error.sourceLine === undefined ? "" : ` at line ${error.sourceLine}`; + return `cannot convert supabase/config.toml${location}: ${error.detail}. supabase/config.toml was not changed.`; +} + +export const NOT_UTF8_MESSAGE = + "cannot convert supabase/config.toml: it is not valid UTF-8, which TOML requires. Re-save it as UTF-8 and rerun the command. supabase/config.toml was not changed."; + +export const TOML_SYMLINK_MESSAGE = + "cannot convert supabase/config.toml: it is a symbolic link, and converting it would leave the file it points to behind. Replace the link with the file itself, then rerun the command. supabase/config.toml was not changed."; + +export const JSONC_SYMLINK_MESSAGE = + "supabase/config.jsonc is a symbolic link to a file that does not exist. Remove it, then rerun the command. supabase/config.toml was not changed."; + +export function writeFailureMessage(cause: string): string { + return `${cause}. supabase/config.toml was not changed.`; +} + +export const JSONC_APPEARED_MESSAGE = + "supabase/config.jsonc appeared while config convert was running, so it was left as is and supabase/config.toml is unchanged. Check which file you want to keep; another conversion may have finished first."; + +export const JSONC_REMOVED_NOTE = + "Removed supabase/config.jsonc and kept supabase/config.toml; rerun the command to convert the current file."; + +export const JSONC_CHANGED_NOTE = + "supabase/config.jsonc changed after config convert wrote it, so it was left as is alongside supabase/config.toml; supabase/config.jsonc takes precedence, so check which file you want to keep."; + +export function jsoncRemovalFailureNote(cause: string): string { + return `Could not remove the new supabase/config.jsonc (${cause}); it takes precedence over supabase/config.toml, so delete it before rerunning the command.`; +} + +export function backupCheckFailureMessage(cause: string): string { + return `Could not check for an existing backup of supabase/config.toml: ${cause}. supabase/config.toml was not changed.`; +} + +export function backupUnverifiedMessage(backup: string, cause: string, undo: string): string { + return `Converted supabase/config.toml to supabase/config.jsonc and moved it to ${backup}, but could not read the backup to confirm config.toml did not change during the run: ${cause}. Compare ${backup} with supabase/config.jsonc; to undo, run: ${undo}`; +} + +export function backupFailureMessage(backup: string, cause: string, note: string): string { + return `Could not move supabase/config.toml to ${backup}: ${cause}. ${note}`; +} + +export function tomlChangedMessage(backup: string, undo: string): string { + return `supabase/config.toml changed while config convert was running, so supabase/config.jsonc holds the earlier version. The latest config.toml is at ${backup}; to restore it, run: ${undo}, then rerun the command.`; +} + +function movedCommentsWarning(moved: ReadonlyArray): ReadonlyArray { + if (moved.length === 0) { + return []; + } + return [ + `Moved ${moved.length} comment(s) that were inside nested arrays or inline tables to the line above their key:`, + ...moved.map( + (comment) => ` line ${comment.line} → ${comment.anchor.join(".")}: ${comment.text}`, + ), + ]; +} + +export function convertWarnings(input: { + readonly dryRun: boolean; + readonly undo: string; + readonly moved: ReadonlyArray; + readonly vscodeFailure: string | undefined; +}): ReadonlyArray { + return [ + ...movedCommentsWarning(input.moved), + minVersionWarning(input.dryRun, input.undo), + ...(input.vscodeFailure === undefined ? [] : [vscodeFailureWarning(input.vscodeFailure)]), + ]; +} + +/** ANSI styling applied to the text report; the handler passes stream-gated colours. */ +export interface ReportStyle { + readonly bold: (text: string) => string; + readonly dim: (text: string) => string; + readonly green: (text: string) => string; + readonly yellow: (text: string) => string; + readonly blue: (text: string) => string; + readonly code: (text: string) => string; +} + +const plain = (text: string) => text; + +export const PLAIN_REPORT_STYLE: ReportStyle = { + bold: plain, + dim: plain, + green: plain, + yellow: plain, + blue: plain, + code: plain, +}; + +/** Renders the text-mode summary of a conversion, or of the conversion `--dry-run` previews. */ +export function convertReport( + input: { + readonly dryRun: boolean; + readonly backup: string; + readonly undo: string; + readonly moved: ReadonlyArray; + readonly vscodeUpdated: boolean; + readonly vscodeFailure: string | undefined; + }, + style: ReportStyle = PLAIN_REPORT_STYLE, +): string { + const { bold, dim, green, yellow, blue, code } = style; + const verb = (planned: string, done: string) => (input.dryRun ? planned : done); + const change = (marker: string, planned: string, done: string, target: string) => + ` ${marker} ${verb(planned, done).padEnd(input.dryRun ? 6 : 7)} ${target}`; + const lines: Array = input.dryRun + ? [ + `${green("✓")} ${bold("Config conversion preview")}`, + ` ${dim("Dry run. No files were changed.")}`, + ] + : [`${green("✓")} ${bold("Converted supabase/config.toml to supabase/config.jsonc")}`]; + + lines.push( + "", + ` ${bold(verb("Planned changes", "Changes"))}`, + change(green("+"), "Create", "Created", code("supabase/config.jsonc")), + change( + blue(">"), + "Move", + "Moved", + `${code("supabase/config.toml")} ${dim("to")} ${code(input.backup)}`, + ), + ); + if (input.vscodeUpdated) { + lines.push( + change( + yellow("~"), + "Update", + "Updated", + `${code(".vscode/settings.json")} ${dim(`(trusts ${TRUSTED_DOMAIN})`)}`, + ), + ); + } + + if (input.moved.length > 0) { + const count = input.moved.length; + lines.push( + "", + ` ${blue("ℹ")} ${bold(`${count} ${count === 1 ? "comment" : "comments"} relocated`)}`, + ` ${dim("Comments inside nested arrays or inline tables move to the line above their key.")}`, + ...input.moved.map( + (comment) => + ` line ${comment.line} → ${code(comment.anchor.join("."))} ${dim(comment.text)}`, + ), + ); + } + + if (input.vscodeFailure !== undefined) { + lines.push( + "", + ` ${yellow("⚠")} ${bold("Could not update .vscode/settings.json")}`, + ` ${input.vscodeFailure}.`, + ` ${VSCODE_MANUAL_STEP}`, + ); + } + + lines.push( + "", + ` ${yellow("⚠")} ${bold("Compatibility")}`, + ...COMPATIBILITY_LINES.map((line) => ` ${line}`), + "", + ` ${dim(verb("To undo after converting:", "To undo:"))}`, + ` ${code(input.undo)}`, + "", + ); + return lines.join("\n"); +} + +interface PayloadInput { + readonly schema: string; + readonly backup: string; + readonly moved: ReadonlyArray; + readonly warnings: ReadonlyArray; +} + +function payloadBase(input: PayloadInput) { + return { + path: "supabase/config.jsonc", + schema: input.schema, + moved_comments: input.moved.map((comment) => ({ + line: comment.line, + key: comment.anchor.join("."), + text: comment.text, + })), + min_cli_version: CONFIG_JSONC_MIN_CLI_VERSION, + warnings: input.warnings, + }; +} + +export function convertPayload(input: PayloadInput & { readonly vscodeUpdated: boolean }) { + return { + ...payloadBase(input), + converted: true, + backup: input.backup, + vscode_settings_updated: input.vscodeUpdated, + }; +} + +export function dryRunPayload( + input: PayloadInput & { readonly vscodeWouldUpdate: boolean; readonly content: string }, +) { + return { + ...payloadBase(input), + converted: false, + dry_run: true, + would_backup: input.backup, + would_update_vscode_settings: input.vscodeWouldUpdate, + content: input.content, + }; +} + +export function alreadyConvertedPayload(jsonFile: string) { + return { converted: false, path: `supabase/${jsonFile}` }; +} diff --git a/apps/cli/src/commands/config/convert/convert.format.unit.test.ts b/apps/cli/src/commands/config/convert/convert.format.unit.test.ts new file mode 100644 index 0000000000..e9b02244f2 --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.format.unit.test.ts @@ -0,0 +1,96 @@ +import { CliConfigConvertError } from "@supabase/config/internal"; +import { describe, expect, it } from "vitest"; + +import { + convertReport, + PLAIN_REPORT_STYLE, + refusalMessage, + undoCommand, +} from "./convert.format.ts"; + +describe("convert format", () => { + it("includes the line in refusals only when known", () => { + const base = { reason: "parse_error", detail: "bad" } as const; + expect(refusalMessage(new CliConfigConvertError({ ...base, sourceLine: 3 }))).toBe( + "cannot convert supabase/config.toml at line 3: bad. supabase/config.toml was not changed.", + ); + expect(refusalMessage(new CliConfigConvertError(base))).toBe( + "cannot convert supabase/config.toml: bad. supabase/config.toml was not changed.", + ); + }); + + it("quotes project roots the shell would split in the undo command", () => { + expect(undoCommand("../my app", "supabase/config.toml.bak", "posix")).toBe( + "mv -- '../my app/supabase/config.toml.bak' '../my app/supabase/config.toml' && rm -- '../my app/supabase/config.jsonc'", + ); + }); + + it("ends mv and rm options before a project root that starts with a dash", () => { + expect(undoCommand("-demo", "supabase/config.toml.bak", "posix")).toBe( + "mv -- -demo/supabase/config.toml.bak -demo/supabase/config.toml && rm -- -demo/supabase/config.jsonc", + ); + }); + + it("renders a PowerShell undo that removes config.jsonc only after the move succeeds", () => { + expect(undoCommand("", "supabase/config.toml.bak", "windows")).toBe( + "Move-Item -LiteralPath supabase/config.toml.bak -Destination supabase/config.toml; if ($?) { Remove-Item -LiteralPath supabase/config.jsonc }", + ); + }); + + it("lists relocated comments and a VS Code failure in the report", () => { + const report = convertReport({ + dryRun: true, + backup: "supabase/config.toml.bak", + undo: "mv a b", + moved: [ + { line: 3, text: "# a", anchor: ["api", "schemas"] }, + { line: 7, text: "# b", anchor: ["auth", "x"] }, + ], + vscodeUpdated: false, + vscodeFailure: "Could not parse JSON in .vscode/settings.json: bad", + }); + + expect(report).toContain( + [ + " ℹ 2 comments relocated", + " Comments inside nested arrays or inline tables move to the line above their key.", + " line 3 → api.schemas # a", + " line 7 → auth.x # b", + "", + " ⚠ Could not update .vscode/settings.json", + " Could not parse JSON in .vscode/settings.json: bad.", + ' Add "https://supabase.com/schemas/": true under "json.schemaDownload.trustedDomains" to trust the config schema.', + ].join("\n"), + ); + }); + + it("styles headings, markers and paths through the given style", () => { + const tag = (name: string) => (text: string) => `<${name}>${text}`; + const report = convertReport( + { + dryRun: false, + backup: "supabase/config.toml.bak", + undo: "mv a b", + moved: [], + vscodeUpdated: false, + vscodeFailure: undefined, + }, + { + ...PLAIN_REPORT_STYLE, + green: tag("g"), + blue: tag("u"), + code: tag("c"), + bold: tag("b"), + dim: tag("d"), + }, + ); + + expect(report.split("\n").slice(0, 5)).toEqual([ + "✓ Converted supabase/config.toml to supabase/config.jsonc", + "", + " Changes", + " + Created supabase/config.jsonc", + " > Moved supabase/config.toml to supabase/config.toml.bak", + ]); + }); +}); diff --git a/apps/cli/src/commands/config/convert/convert.handler.ts b/apps/cli/src/commands/config/convert/convert.handler.ts new file mode 100644 index 0000000000..c813b46e03 --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.handler.ts @@ -0,0 +1,362 @@ +import { + convertCliConfigTomlToJsonc, + parseCliConfigDocumentFile, + createCliConfigDocumentText, +} from "@supabase/config/internal"; +import { CliConfigParseError } from "@supabase/config/effect"; +import { Effect, FileSystem, Option, Path, Predicate } from "effect"; + +import { CommandSettings } from "../../../config/command-settings.service.ts"; +import { + aqua, + blue, + bold, + type ColorStream, + dim, + green, + yellow, +} from "../../../command-internal/colors.ts"; +import { OutputFlag } from "../../../command-internal/global-flags.ts"; +import { unsupportedOutputFlagMessage } from "../../../command-internal/output-formats.ts"; +import { validateWorkdirIsDirectory } from "../../../command-internal/workdir-validation.ts"; +import { + describeConfigParseError, + missingProjectConfigMessageEffect, +} from "../../../command-internal/workdir-project.ts"; +import { trustSupabaseSchemaDomain } from "../../../shared/init/project-init.ts"; +import { InitParseSettingsError } from "../../../shared/init/project-init.errors.ts"; +import { Output } from "../../../shared/output/output.service.ts"; +import { RuntimeInfo } from "../../../shared/runtime/runtime-info.service.ts"; +import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; +import type { ConfigConvertFlags } from "./convert.command.ts"; +import { + ConfigConvertAlreadyJsonError, + ConfigConvertFileChangedError, + ConfigConvertLoadConfigError, + ConfigConvertOutputFlagUnsupportedError, + ConfigConvertUnsupportedError, + ConfigConvertWorkdirError, + ConfigConvertWriteError, +} from "./convert.errors.ts"; +import { + alreadyConvertedMessage, + alreadyConvertedPayload, + CONVERTED_MESSAGE, + convertPayload, + convertReport, + convertWarnings, + dryRunMessage, + dryRunPayload, + jsonPrecedenceMessage, + refusalMessage, + type ReportStyle, + JSONC_APPEARED_MESSAGE, + JSONC_CHANGED_NOTE, + JSONC_REMOVED_NOTE, + JSONC_SYMLINK_MESSAGE, + NOT_UTF8_MESSAGE, + TOML_SYMLINK_MESSAGE, + backupCheckFailureMessage, + backupFailureMessage, + backupUnverifiedMessage, + jsoncRemovalFailureNote, + tomlChangedMessage, + undoCommand, + writeFailureMessage, +} from "./convert.format.ts"; + +const trustSchemaDomainInVscode = Effect.fn("config.convert.vscode")(function* ( + workdir: string, + dryRun: boolean, +) { + const result = yield* trustSupabaseSchemaDomain(workdir, { dryRun }).pipe( + Effect.match({ + onSuccess: (updated): { readonly updated: boolean; readonly failure?: string } => ({ + updated, + }), + onFailure: (error) => ({ + updated: false, + failure: error instanceof InitParseSettingsError ? error.detail : error.message, + }), + }), + ); + yield* Effect.annotateCurrentSpan("config.vscode_updated", result.updated); + return result; +}); + +const isSymlink = (fs: FileSystem.FileSystem, target: string) => + fs.readLink(target).pipe(Effect.match({ onSuccess: () => true, onFailure: () => false })); + +const refuseSymlinks = Effect.fnUntraced(function* (tomlPath: string, jsoncPath: string) { + const fs = yield* FileSystem.FileSystem; + if (yield* isSymlink(fs, tomlPath)) { + return yield* new ConfigConvertUnsupportedError({ message: TOML_SYMLINK_MESSAGE }); + } + if (yield* isSymlink(fs, jsoncPath)) { + return yield* new ConfigConvertUnsupportedError({ message: JSONC_SYMLINK_MESSAGE }); + } +}); + +const freeBackupPath = Effect.fnUntraced(function* (configDir: string) { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + for (let attempt = 1; ; attempt++) { + const candidate = path.join( + configDir, + attempt === 1 ? "config.toml.bak" : `config.toml.${attempt}.bak`, + ); + const taken = yield* fs + .exists(candidate) + .pipe( + Effect.mapError( + (cause) => + new ConfigConvertWriteError({ message: backupCheckFailureMessage(cause.message) }), + ), + ); + if (!taken) { + return candidate; + } + } +}); + +const rollbackJsonc = Effect.fnUntraced(function* (jsoncPath: string, text: string) { + const fs = yield* FileSystem.FileSystem; + return yield* fs.readFileString(jsoncPath).pipe( + Effect.flatMap((written) => + written === text + ? fs.remove(jsoncPath).pipe(Effect.as(JSONC_REMOVED_NOTE)) + : Effect.succeed(JSONC_CHANGED_NOTE), + ), + Effect.catchTag("PlatformError", (cause) => + Effect.succeed( + Predicate.isTagged(cause.reason, "NotFound") + ? JSONC_REMOVED_NOTE + : jsoncRemovalFailureNote(cause.message), + ), + ), + ); +}); + +const reportStyle = (stream: ColorStream): ReportStyle => ({ + bold: (text) => bold(text, stream), + dim: (text) => dim(text, stream), + green: (text) => green(text, stream), + yellow: (text) => yellow(text, stream), + blue: (text) => blue(text, stream), + code: (text) => aqua(text, stream), +}); + +export const configConvert = Effect.fn("config.convert")(function* (flags: ConfigConvertFlags) { + const output = yield* Output; + const telemetryState = yield* TelemetryState; + const cliSettings = yield* CommandSettings; + const outputFlag = yield* OutputFlag; + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const runtimeInfo = yield* RuntimeInfo; + + yield* Effect.gen(function* () { + if (Option.isSome(outputFlag)) { + return yield* new ConfigConvertOutputFlagUnsupportedError({ + message: unsupportedOutputFlagMessage("config convert"), + }); + } + + yield* validateWorkdirIsDirectory(cliSettings.workdir, fs).pipe( + Effect.mapError((error) => new ConfigConvertWorkdirError({ message: error.message })), + ); + + yield* Effect.annotateCurrentSpan("config.dry_run", flags.dryRun); + const parsed = yield* parseCliConfigDocumentFile(cliSettings.workdir, { search: false }).pipe( + Effect.mapError( + (cause) => + new ConfigConvertLoadConfigError({ + message: + cause instanceof CliConfigParseError + ? describeConfigParseError(cliSettings.workdir, cause) + : cause.message, + }), + ), + Effect.withSpan("config.convert.read"), + ); + if (parsed === null) { + return yield* new ConfigConvertLoadConfigError({ + message: yield* missingProjectConfigMessageEffect(cliSettings), + }); + } + const configDir = path.dirname(parsed.path); + if (parsed.format === "json") { + const jsonFile = path.basename(parsed.path); + const tomlExists = yield* fs + .exists(path.join(configDir, "config.toml")) + .pipe( + Effect.mapError((cause) => new ConfigConvertLoadConfigError({ message: cause.message })), + ); + if (tomlExists) { + return yield* new ConfigConvertAlreadyJsonError({ + message: jsonPrecedenceMessage(jsonFile), + }); + } + if (output.format === "text") { + yield* output.raw(`${alreadyConvertedMessage(jsonFile)}\n`); + } else { + yield* output.success(alreadyConvertedMessage(jsonFile), alreadyConvertedPayload(jsonFile)); + } + return; + } + + yield* fs.readFile(parsed.path).pipe( + Effect.mapError((cause) => new ConfigConvertLoadConfigError({ message: cause.message })), + Effect.flatMap((bytes) => + Effect.try({ + try: () => new TextDecoder("utf-8", { fatal: true }).decode(bytes), + catch: () => new ConfigConvertUnsupportedError({ message: NOT_UTF8_MESSAGE }), + }), + ), + ); + const outcome = yield* convertCliConfigTomlToJsonc(parsed.rawText).pipe( + Effect.catchTag( + "CliConfigConvertError", + (error) => new ConfigConvertUnsupportedError({ message: refusalMessage(error) }), + ), + Effect.withSpan("config.convert.render"), + ); + yield* Effect.annotateCurrentSpan({ + "config.schema_source": outcome.schemaSource, + "config.comment_count": outcome.commentCount, + "config.moved_comment_count": outcome.movedComments.length, + }); + + const jsoncPath = path.join(configDir, "config.jsonc"); + yield* refuseSymlinks(parsed.path, jsoncPath); + const backupPath = yield* freeBackupPath(configDir); + const backup = `supabase/${path.basename(backupPath)}`; + const windows = runtimeInfo.platform === "win32"; + const root = path.relative(runtimeInfo.cwd, cliSettings.workdir); + const undo = undoCommand( + windows ? root.replaceAll("\\", "/") : root, + backup, + windows ? "windows" : "posix", + ); + + if (flags.dryRun) { + const vscode = yield* trustSchemaDomainInVscode(cliSettings.workdir, true); + const warnings = convertWarnings({ + dryRun: true, + undo, + moved: outcome.movedComments, + vscodeFailure: vscode.failure, + }); + const message = dryRunMessage(vscode.updated, backup); + if (output.format === "text") { + yield* output.raw(outcome.text); + yield* output.raw( + `\n${convertReport( + { + dryRun: true, + backup, + undo, + moved: outcome.movedComments, + vscodeUpdated: vscode.updated, + vscodeFailure: vscode.failure, + }, + reportStyle(process.stderr), + )}`, + "stderr", + ); + } else { + yield* output.success( + message, + dryRunPayload({ + schema: outcome.schemaRef, + backup, + moved: outcome.movedComments, + vscodeWouldUpdate: vscode.updated, + warnings, + content: outcome.text, + }), + ); + } + return; + } + + yield* Effect.gen(function* () { + const tomlMode = yield* fs.stat(parsed.path).pipe( + Effect.map((info) => info.mode & 0o7777), + Effect.mapError( + (cause) => + new ConfigConvertWriteError({ + message: `Could not read the permissions of supabase/config.toml: ${cause.message}. Nothing was converted.`, + }), + ), + ); + const created = yield* createCliConfigDocumentText(jsoncPath, outcome.text, tomlMode).pipe( + Effect.catchTag( + "CliConfigWriteError", + (cause) => new ConfigConvertWriteError({ message: writeFailureMessage(cause.message) }), + ), + ); + if (!created) { + return yield* new ConfigConvertFileChangedError({ message: JSONC_APPEARED_MESSAGE }); + } + yield* fs.rename(parsed.path, backupPath).pipe( + Effect.catchTag("PlatformError", (cause) => + Effect.flatMap(rollbackJsonc(jsoncPath, outcome.text), (note) => + Effect.fail( + new ConfigConvertWriteError({ + message: backupFailureMessage(backup, cause.message, note), + }), + ), + ), + ), + ); + const moved = yield* fs.readFileString(backupPath).pipe( + Effect.mapError( + (cause) => + new ConfigConvertWriteError({ + message: backupUnverifiedMessage(backup, cause.message, undo), + }), + ), + ); + if (moved !== parsed.rawText) { + return yield* new ConfigConvertFileChangedError({ + message: tomlChangedMessage(backup, undo), + }); + } + }).pipe(Effect.withSpan("config.convert.write")); + + const vscode = yield* trustSchemaDomainInVscode(cliSettings.workdir, false); + + if (output.format === "text") { + yield* output.raw( + convertReport( + { + dryRun: false, + backup, + undo, + moved: outcome.movedComments, + vscodeUpdated: vscode.updated, + vscodeFailure: vscode.failure, + }, + reportStyle(process.stdout), + ), + ); + } else { + yield* output.success( + CONVERTED_MESSAGE, + convertPayload({ + schema: outcome.schemaRef, + backup, + moved: outcome.movedComments, + vscodeUpdated: vscode.updated, + warnings: convertWarnings({ + dryRun: false, + undo, + moved: outcome.movedComments, + vscodeFailure: vscode.failure, + }), + }), + ); + } + }).pipe(Effect.ensuring(telemetryState.flush)); +}); diff --git a/apps/cli/src/commands/config/convert/convert.integration.test.ts b/apps/cli/src/commands/config/convert/convert.integration.test.ts new file mode 100644 index 0000000000..07b64e3e4e --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.integration.test.ts @@ -0,0 +1,777 @@ +import { BunServices } from "@effect/platform-bun"; +import { describe, expect, it } from "@effect/vitest"; +import { parseJsonc } from "@supabase/config/internal"; +import { Effect, FileSystem, Layer, Option, Path, PlatformError } from "effect"; + +import { configValuesLayer } from "../../../../tests/helpers/config-values-layer.ts"; +import { + mockCommandSettings, + mockTelemetryStateTracked, + useTempWorkdir, +} from "../../../../tests/helpers/command-mocks.ts"; +import { mockOutput, mockRuntimeInfo } from "../../../../tests/helpers/mocks.ts"; +import { OutputFlag } from "../../../command-internal/global-flags.ts"; +import { CliConfigValues } from "../../../config/cli-config-values.service.ts"; +import { renderCliConfigTemplate } from "../../../shared/init/project-init.templates.ts"; +import type { OutputFormat } from "../../../shared/output/types.ts"; +import { configConvert } from "./convert.handler.ts"; +import { + CONFIG_JSONC_MIN_CLI_VERSION, + JSONC_APPEARED_MESSAGE, + JSONC_REMOVED_NOTE, + JSONC_SYMLINK_MESSAGE, + minVersionWarning, + NOT_UTF8_MESSAGE, + TOML_SYMLINK_MESSAGE, + tomlChangedMessage, + undoCommand, +} from "./convert.format.ts"; + +const BACKUP = "supabase/config.toml.bak"; +const UNDO = undoCommand("", BACKUP, "posix"); + +const tempRoot = useTempWorkdir("supabase-config-convert-"); + +interface SetupOpts { + readonly format?: OutputFormat; + readonly explicitWorkdir?: boolean; + readonly outputFlag?: "json"; + readonly cwd?: string; +} + +function setup(opts: SetupOpts = {}) { + const out = mockOutput({ format: opts.format ?? "text" }); + const telemetry = mockTelemetryStateTracked(); + const layer = Layer.mergeAll( + out.layer, + telemetry.layer, + mockCommandSettings({ + workdir: tempRoot.current, + explicitWorkdir: opts.explicitWorkdir ?? false, + }), + Layer.succeed( + OutputFlag, + opts.outputFlag === undefined ? Option.none() : Option.some(opts.outputFlag), + ), + mockRuntimeInfo({ cwd: opts.cwd ?? tempRoot.current }), + BunServices.layer, + ); + return { layer, out, telemetry }; +} + +const projectPath = (...segments: ReadonlyArray) => + Effect.gen(function* () { + const path = yield* Path.Path; + return path.join(tempRoot.current, ...segments); + }); + +const writeFile = Effect.fnUntraced(function* (segments: ReadonlyArray, text: string) { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const target = yield* projectPath(...segments); + yield* fs.makeDirectory(path.dirname(target), { recursive: true }); + yield* fs.writeFileString(target, text); +}); + +const readFile = Effect.fnUntraced(function* (...segments: ReadonlyArray) { + const fs = yield* FileSystem.FileSystem; + return yield* fs.readFileString(yield* projectPath(...segments)); +}); + +const exists = Effect.fnUntraced(function* (...segments: ReadonlyArray) { + const fs = yield* FileSystem.FileSystem; + return yield* fs.exists(yield* projectPath(...segments)); +}); + +const materializedConfig = Effect.fnUntraced( + function* () { + const values = yield* CliConfigValues; + const resolved = yield* values.load({ workdir: tempRoot.current, projectRef: Option.none() }); + return resolved.materialized.config; + }, + Effect.provide(Layer.mergeAll(configValuesLayer(), BunServices.layer)), +); + +const run = (dryRun = false) => configConvert({ dryRun }); + +const configTomlPath = projectPath("supabase", "config.toml"); + +const denied = (method: string, pathOrDescriptor: string) => + PlatformError.systemError({ + _tag: "PermissionDenied", + module: "FileSystem", + method, + pathOrDescriptor, + }); + +type FsFailure = + | "rename" + | "rename-and-jsonc-stuck" + | "jsonc-appears" + | "toml-edited" + | "backup-check" + | "backup-unreadable"; + +const failingConfigTomlFsLayer = (failure: FsFailure) => + Layer.effect( + FileSystem.FileSystem, + Effect.gen(function* () { + const real = yield* FileSystem.FileSystem; + const target = yield* configTomlPath; + const jsonc = yield* projectPath("supabase", "config.jsonc"); + const backup = yield* projectPath("supabase", "config.toml.bak"); + return FileSystem.FileSystem.of({ + ...real, + exists: (path) => + failure === "backup-check" && path === backup + ? Effect.fail(denied("exists", path)) + : real.exists(path), + readFileString: (path, encoding) => + failure === "backup-unreadable" && path === backup + ? Effect.fail(denied("readFileString", path)) + : real.readFileString(path, encoding), + stat: (path) => + failure === "jsonc-appears" && path === target + ? real.writeFileString(jsonc, "{}\n").pipe(Effect.andThen(real.stat(path))) + : real.stat(path), + rename: (from, to) => + from !== target + ? real.rename(from, to) + : failure === "toml-edited" + ? real + .writeFileString(target, EDITED_TOML) + .pipe(Effect.andThen(real.rename(from, to))) + : failure === "rename" || failure === "rename-and-jsonc-stuck" + ? Effect.fail(denied("rename", from)) + : real.rename(from, to), + remove: (path, options) => + failure === "rename-and-jsonc-stuck" && path === jsonc + ? Effect.fail(denied("remove", path)) + : real.remove(path, options), + }); + }), + ); + +const EDITED_TOML = 'project_id = "edited"\n'; + +const SIMPLE_TOML = `#:schema https://supabase.com/schemas/config/v1.json +# project name +project_id = "demo" + +[api] +port = 54321 # default +`; + +describe("config convert integration", () => { + it.effect( + "converts the init template, keeping every prose comment once and the same config", + () => { + const { layer, out, telemetry } = setup(); + const template = renderCliConfigTemplate("demo", false); + const tomlExample = /^#\s?(\[[^\]]+\]|[\w."'-]+ = .+)$/; + const templateComments = template + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.startsWith("#") && !line.startsWith("#:schema")); + const expectedProse = templateComments + .filter((line) => !tomlExample.test(line)) + .map((line) => `//${line.slice(1)}`.trimEnd()); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], template); + const before = yield* materializedConfig(); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* exists("supabase", "config.toml")).toBe(false); + expect(yield* readFile("supabase", "config.toml.bak")).toBe(template); + const jsonc = yield* readFile("supabase", "config.jsonc"); + const actualComments = jsonc + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.startsWith("//")) + .map((line) => { + const inner = line.replace(/^\/\/ +/, ""); + return inner.startsWith("//") ? inner : line; + }); + const prose = new Set(expectedProse); + expect(actualComments.filter((line) => prose.has(line)).sort()).toEqual( + [...expectedProse].sort(), + ); + expect(actualComments.filter((line) => /^\/\/ \[.*\]$/.test(line))).toEqual([]); + expect(yield* materializedConfig()).toEqual(before); + + expect(out.stdoutText.split("\n")).toEqual([ + "✓ Converted supabase/config.toml to supabase/config.jsonc", + "", + " Changes", + " + Created supabase/config.jsonc", + " > Moved supabase/config.toml to supabase/config.toml.bak", + "", + " ⚠ Compatibility", + " Supabase CLI versions before 3.1.0 ignore config.jsonc and run with defaults.", + " Upgrade the Supabase CLI on every machine and CI job that uses this project.", + "", + " To undo:", + " mv -- supabase/config.toml.bak supabase/config.toml && rm -- supabase/config.jsonc", + "", + ]); + expect(out.stderrText).toBe(""); + expect(telemetry.flushed).toBe(true); + }).pipe(Effect.provide(BunServices.layer)); + }, + ); + + it.effect("writes the schema directive as $schema and keeps comments in place", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run().pipe(Effect.provide(layer)); + + const jsonc = yield* readFile("supabase", "config.jsonc"); + expect(parseJsonc(jsonc)).toEqual({ + $schema: "https://supabase.com/schemas/config/v1.json", + project_id: "demo", + api: { port: 54321 }, + }); + expect(jsonc).toContain("// project name"); + expect(jsonc).toContain('"port": 54321 // default'); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("gives config.jsonc the permissions of the config.toml it replaces", () => { + const { layer } = setup(); + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* fs.chmod(yield* configTomlPath, 0o600); + + yield* run().pipe(Effect.provide(layer)); + + const info = yield* fs.stat(yield* projectPath("supabase", "config.jsonc")); + expect(info.mode & 0o777).toBe(0o600); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("keeps a comment inside a multi-line array in place without a warning", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile( + ["supabase", "config.toml"], + '[api]\nschemas = [\n "public", # keep\n "graphql",\n]\n', + ); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* readFile("supabase", "config.jsonc")).toContain('"public", // keep'); + expect(out.stdoutText).not.toContain("relocated"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("reports comments moved out of values it cannot place", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile( + ["supabase", "config.toml"], + "[api]\nschemas = [\n [1], # keep\n [2],\n]\n", + ); + + yield* run().pipe(Effect.provide(layer)); + + expect(out.stdoutText).toContain( + " ℹ 1 comment relocated\n Comments inside nested arrays or inline tables move to the line above their key.\n line 3 → api.schemas # keep\n", + ); + expect(yield* readFile("supabase", "config.jsonc")).toContain("// keep"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("fails with the init hint when no config exists", () => { + const { layer } = setup(); + return Effect.gen(function* () { + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + expect(error._tag).toBe("ConfigConvertLoadConfigError"); + expect(error.message).toBe( + "failed to read supabase/config.toml, config.json or config.jsonc: file not found. Run `supabase init` to create one.", + ); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("names the workdir when an explicit --workdir has no project", () => { + const { layer } = setup({ explicitWorkdir: true }); + return Effect.gen(function* () { + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + expect(error._tag).toBe("ConfigConvertLoadConfigError"); + expect(error.message).toContain(tempRoot.current); + expect(error.message).toContain("--workdir/SUPABASE_WORKDIR is used exactly as given"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("reports a TOML parse failure against config.toml", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], "[api\nport = 1\n"); + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + expect(error._tag).toBe("ConfigConvertLoadConfigError"); + expect(error.message).toContain("failed to parse supabase/config.toml"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect.each(["config.jsonc", "config.json"] as const)( + "refuses when config.toml and %s both exist and leaves both files untouched", + (existing) => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile(["supabase", existing], "{}\n"); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertAlreadyJsonError"); + expect(error.message).toBe( + `supabase/config.toml is ignored because supabase/${existing} takes precedence. Delete supabase/${existing} first to convert config.toml again.`, + ); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + expect(yield* readFile("supabase", existing)).toBe("{}\n"); + }).pipe(Effect.provide(BunServices.layer)); + }, + ); + + it.effect.each(["config.jsonc", "config.json"] as const)( + "succeeds without changes when only %s exists", + (existing) => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", existing], "{}\n"); + + yield* run().pipe(Effect.provide(layer)); + + expect(out.stdoutText).toBe( + `supabase/${existing} is already the project config; nothing to convert.\n`, + ); + expect(out.stderrText).toBe(""); + expect(yield* readFile("supabase", existing)).toBe("{}\n"); + expect(yield* exists("supabase", "config.toml")).toBe(false); + }).pipe(Effect.provide(BunServices.layer)); + }, + ); + + it.effect("reports nothing converted in json mode when config.jsonc already exists", () => { + const { layer, out } = setup({ format: "json" }); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.jsonc"], "{}\n"); + + yield* run().pipe(Effect.provide(layer)); + + expect(out.messages).toEqual([ + { + type: "success", + message: "supabase/config.jsonc is already the project config; nothing to convert.", + data: { converted: false, path: "supabase/config.jsonc" }, + }, + ]); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("refuses a config.toml that is not valid UTF-8, leaving it byte-identical", () => { + const { layer } = setup(); + const bytes = new Uint8Array([ + ...new TextEncoder().encode('project_id = "caf'), + 0xe9, + ...new TextEncoder().encode('"\n'), + ]); + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + yield* writeFile(["supabase", "config.toml"], ""); + const tomlPath = yield* projectPath("supabase", "config.toml"); + yield* fs.writeFile(tomlPath, bytes); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertUnsupportedError"); + expect(error.message).toBe(NOT_UTF8_MESSAGE); + expect([...(yield* fs.readFile(tomlPath))]).toEqual([...bytes]); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("refuses a TOML date, leaving config.toml byte-identical and writing nothing", () => { + const { layer } = setup(); + const toml = '# keep me\nproject_id = "demo"\nwhen = 1979-05-27\n'; + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], toml); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertUnsupportedError"); + expect(error.message).toContain("at line 3"); + expect(error.message).toContain("Quote the value as a string, then rerun."); + expect(yield* readFile("supabase", "config.toml")).toBe(toml); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("adds the schema domain to an existing commented VS Code settings file", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile([".vscode", "settings.json"], '{\n // mine\n "editor.fontSize": 14\n}\n'); + + yield* run().pipe(Effect.provide(layer)); + + const settings = yield* readFile(".vscode", "settings.json"); + expect(settings).toContain("// mine"); + expect(parseJsonc(settings)).toEqual({ + "editor.fontSize": 14, + "json.schemaDownload.trustedDomains": { "https://supabase.com/schemas/": true }, + }); + expect(out.stdoutText).toContain( + " ~ Updated .vscode/settings.json (trusts https://supabase.com/schemas/)\n", + ); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("does not create .vscode when it does not exist", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* exists(".vscode")).toBe(false); + expect(out.stdoutText).not.toContain(".vscode/settings.json"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("warns but still converts when settings.json is malformed", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile([".vscode", "settings.json"], "{ nope"); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* exists("supabase", "config.jsonc")).toBe(true); + expect(yield* exists("supabase", "config.toml")).toBe(false); + expect(yield* readFile(".vscode", "settings.json")).toBe("{ nope"); + expect(out.stdoutText).toContain(" ⚠ Could not update .vscode/settings.json\n"); + expect(out.stdoutText).toContain( + 'Add "https://supabase.com/schemas/": true under "json.schemaDownload.trustedDomains" to trust the config schema.', + ); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("--dry-run prints the JSONC and writes nothing", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile([".vscode", "settings.json"], "{}\n"); + + yield* run(true).pipe(Effect.provide(layer)); + + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + expect(yield* readFile(".vscode", "settings.json")).toBe("{}\n"); + expect(parseJsonc(out.stdoutText)).toMatchObject({ + project_id: "demo", + api: { port: 54321 }, + }); + expect(out.stderrText).toContain( + [ + "✓ Config conversion preview", + " Dry run. No files were changed.", + "", + " Planned changes", + " + Create supabase/config.jsonc", + " > Move supabase/config.toml to supabase/config.toml.bak", + " ~ Update .vscode/settings.json (trusts https://supabase.com/schemas/)", + ].join("\n"), + ); + expect(out.stderrText).toContain(" To undo after converting:\n"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("--dry-run lists no VS Code change when settings need none", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run(true).pipe(Effect.provide(layer)); + + expect(out.stderrText).toContain( + " > Move supabase/config.toml to supabase/config.toml.bak\n\n", + ); + expect(out.stderrText).not.toContain(".vscode/settings.json"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("emits a structured payload in json mode without stderr noise", () => { + const { layer, out } = setup({ format: "json" }); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run().pipe(Effect.provide(layer)); + + expect(out.stderrText).toBe(""); + expect(out.stdoutText).toBe(""); + expect(out.messages).toEqual([ + { + type: "success", + message: "Converted supabase/config.toml to supabase/config.jsonc.", + data: expect.objectContaining({ + path: "supabase/config.jsonc", + converted: true, + backup: "supabase/config.toml.bak", + schema: "https://supabase.com/schemas/config/v1.json", + moved_comments: [], + vscode_settings_updated: false, + min_cli_version: CONFIG_JSONC_MIN_CLI_VERSION, + warnings: expect.arrayContaining([minVersionWarning(false, UNDO)]), + }), + }, + ]); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("--dry-run in json mode carries the document and writes nothing", () => { + const { layer, out } = setup({ format: "json" }); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run(true).pipe(Effect.provide(layer)); + + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + const [message] = out.messages; + expect(message).toMatchObject({ + type: "success", + data: { + dry_run: true, + would_backup: "supabase/config.toml.bak", + would_update_vscode_settings: false, + content: expect.stringContaining('"project_id": "demo"'), + warnings: expect.arrayContaining([minVersionWarning(true, UNDO)]), + }, + }); + expect(message?.data).not.toHaveProperty("backup"); + expect(yield* exists("supabase", "config.toml.bak")).toBe(false); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("--dry-run in json mode reports a pending VS Code update without writing it", () => { + const { layer, out } = setup({ format: "json" }); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile([".vscode", "settings.json"], "{}\n"); + + yield* run(true).pipe(Effect.provide(layer)); + + expect(out.messages[0]).toMatchObject({ + data: { would_update_vscode_settings: true }, + }); + expect(yield* readFile(".vscode", "settings.json")).toBe("{}\n"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("keeps an explicit trusted-domain choice in VS Code settings", () => { + const { layer, out } = setup(); + const settings = + '{\n "json.schemaDownload.trustedDomains": {\n "https://supabase.com/schemas/": false\n }\n}\n'; + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* writeFile([".vscode", "settings.json"], settings); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* readFile(".vscode", "settings.json")).toBe(settings); + expect(out.stdoutText).not.toContain(".vscode/settings.json"); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("removes config.jsonc and keeps config.toml when config.toml cannot be moved", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide(Layer.provideMerge(failingConfigTomlFsLayer("rename"), layer)), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertWriteError"); + expect(error.message).toContain( + "Could not move supabase/config.toml to supabase/config.toml.bak", + ); + expect(error.message).toContain(JSONC_REMOVED_NOTE); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + expect(out.stdoutText).toBe(""); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("says config.jsonc remains when the rollback cannot remove it", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide( + Layer.provideMerge(failingConfigTomlFsLayer("rename-and-jsonc-stuck"), layer), + ), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertWriteError"); + expect(error.message).toContain("Could not remove the new supabase/config.jsonc"); + expect(error.message).not.toContain(JSONC_REMOVED_NOTE); + expect(yield* exists("supabase", "config.jsonc")).toBe(true); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("leaves a config.jsonc that appears mid-run in place and keeps config.toml", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide(Layer.provideMerge(failingConfigTomlFsLayer("jsonc-appears"), layer)), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertFileChangedError"); + expect(error.message).toBe(JSONC_APPEARED_MESSAGE); + expect(yield* readFile("supabase", "config.jsonc")).toBe("{}\n"); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("keeps a config.toml edited mid-run in the backup and says how to restore it", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide(Layer.provideMerge(failingConfigTomlFsLayer("toml-edited"), layer)), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertFileChangedError"); + expect(error.message).toBe(tomlChangedMessage(BACKUP, UNDO)); + expect(yield* readFile("supabase", "config.toml.bak")).toBe(EDITED_TOML); + expect(yield* exists("supabase", "config.toml")).toBe(false); + expect(out.stdoutText).toBe(""); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("fails before writing when it cannot check for an existing backup", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide(Layer.provideMerge(failingConfigTomlFsLayer("backup-check"), layer)), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertWriteError"); + expect(error.message).toMatch( + /^Could not check for an existing backup of supabase\/config\.toml: /, + ); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("says the conversion finished but is unverified when the backup cannot be read", () => { + const { layer, out } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe( + Effect.provide(Layer.provideMerge(failingConfigTomlFsLayer("backup-unreadable"), layer)), + Effect.flip, + ); + + expect(error._tag).toBe("ConfigConvertWriteError"); + expect(error.message).toContain("could not read the backup to confirm"); + expect(error.message).toContain(`to undo, run: ${UNDO}`); + expect(yield* exists("supabase", "config.jsonc")).toBe(true); + expect(yield* exists("supabase", "config.toml")).toBe(false); + expect(out.stdoutText).toBe(""); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("backs up to the next free name when a backup already exists", () => { + const { layer } = setup(); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml.bak"], "old backup\n"); + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run().pipe(Effect.provide(layer)); + + expect(yield* readFile("supabase", "config.toml.bak")).toBe("old backup\n"); + expect(yield* readFile("supabase", "config.toml.2.bak")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("prints the undo command relative to the directory the command ran from", () => { + const { layer, out } = setup({ cwd: `${tempRoot.current}/../` }); + return Effect.gen(function* () { + const path = yield* Path.Path; + const root = path.basename(tempRoot.current); + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + yield* run().pipe(Effect.provide(layer)); + + expect(out.stdoutText).toContain( + ` mv -- ${root}/${BACKUP} ${root}/supabase/config.toml && rm -- ${root}/supabase/config.jsonc\n`, + ); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("refuses a symlinked config.toml and leaves the link in place", () => { + const { layer } = setup(); + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + yield* writeFile(["shared", "real.toml"], SIMPLE_TOML); + yield* writeFile(["supabase", "placeholder"], ""); + yield* fs.symlink("../shared/real.toml", yield* configTomlPath); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertUnsupportedError"); + expect(error.message).toBe(TOML_SYMLINK_MESSAGE); + expect(yield* fs.readLink(yield* configTomlPath)).toBe("../shared/real.toml"); + expect(yield* exists("supabase", "config.jsonc")).toBe(false); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("refuses when config.jsonc is a dangling symlink", () => { + const { layer } = setup(); + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + yield* fs.symlink("nowhere.jsonc", yield* projectPath("supabase", "config.jsonc")); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertUnsupportedError"); + expect(error.message).toBe(JSONC_SYMLINK_MESSAGE); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); + + it.effect("rejects -o/--output in favour of --output-format", () => { + const { layer } = setup({ outputFlag: "json" }); + return Effect.gen(function* () { + yield* writeFile(["supabase", "config.toml"], SIMPLE_TOML); + + const error = yield* run().pipe(Effect.provide(layer), Effect.flip); + + expect(error._tag).toBe("ConfigConvertOutputFlagUnsupportedError"); + expect(error.message).toBe( + "the -o/--output flag is not supported by config convert; use --output-format json|stream-json instead.", + ); + expect(yield* readFile("supabase", "config.toml")).toBe(SIMPLE_TOML); + }).pipe(Effect.provide(BunServices.layer)); + }); +}); diff --git a/apps/cli/src/commands/config/convert/convert.template.unit.test.ts b/apps/cli/src/commands/config/convert/convert.template.unit.test.ts new file mode 100644 index 0000000000..aa62821983 --- /dev/null +++ b/apps/cli/src/commands/config/convert/convert.template.unit.test.ts @@ -0,0 +1,81 @@ +import { convertCliConfigTomlToJsonc, parseJsonc } from "@supabase/config/internal"; +import { Effect } from "effect"; +import { parse as parseToml } from "smol-toml"; +import { describe, expect, it } from "vitest"; + +import { renderCliConfigTemplate } from "../../../shared/init/project-init.templates.ts"; + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function leaves(value: unknown, path: ReadonlyArray = []): Map { + if (!isRecord(value) || Object.keys(value).length === 0) { + return new Map([[path.join("."), value]]); + } + return new Map( + Object.entries(value).flatMap(([key, child]) => [...leaves(child, [...path, key])]), + ); +} + +function added(after: Map, before: Map) { + return new Map([...after].filter(([path]) => !before.has(path))); +} + +function commentedMembers(lines: ReadonlyArray): Array { + const members: Array = []; + for (let start = 0; start < lines.length; start++) { + const match = /^(\s*)\/\/ "[^"]+": (.*)$/.exec(lines[start] ?? ""); + if (match === null) { + continue; + } + let end = start; + if (/[{[]$/.test(match[2] ?? "")) { + const close = new RegExp(`^${match[1]}// [}\\]],$`); + while (end < lines.length && !close.test(lines[end] ?? "")) { + end++; + } + if (end === lines.length) { + throw new Error(`No closing delimiter for the commented member on line ${start + 1}`); + } + } + members.push([start, end]); + start = end; + } + return members; +} + +describe("converted init template", () => { + const template = renderCliConfigTemplate("demo", false); + const jsonc = Effect.runSync(convertCliConfigTomlToJsonc(template)).text; + const lines = jsonc.split("\n"); + const example = /^# (\[[^\]]+\]|[\w."'-]+ = .+)$/; + + it("uncommenting any one example yields valid JSONC with its value where the TOML example implied", () => { + const withExamples = template + .split("\n") + .map((line) => (example.test(line) ? line.slice(2) : line)) + .join("\n"); + const active = leaves(parseJsonc(jsonc)); + const expected = added(leaves(parseToml(withExamples)), leaves(parseToml(template))); + const members = commentedMembers(lines); + const seen = new Map(); + + for (const [start, end] of members) { + const document = lines + .map((line, index) => + index >= start && index <= end ? line.replace(/^(\s*)\/\/ ?/, "$1") : line, + ) + .join("\n"); + const gained = added(leaves(parseJsonc(document)), active); + expect(gained.size).toBeGreaterThan(0); + for (const [path, value] of gained) { + seen.set(path, value); + } + } + + expect(members.length).toBeGreaterThan(30); + expect(seen.get("auth.hook.custom_access_token.enabled")).toBe(true); + expect(seen).toEqual(expected); + }); +}); diff --git a/apps/cli/src/commands/config/push/SIDE_EFFECTS.md b/apps/cli/src/commands/config/push/SIDE_EFFECTS.md index 0004c75d90..9c64aa5c12 100644 --- a/apps/cli/src/commands/config/push/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/config/push/SIDE_EFFECTS.md @@ -136,25 +136,25 @@ cannot be resolved from either the read or the file — reported in their own ## Exit Codes -| Code | Condition | -| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `0` | success, **including** a push with nothing to write (the project already matches, so nothing is asked) | -| `1` | resolved `--workdir`/`SUPABASE_WORKDIR` doesn't exist or isn't a directory (`ConfigPushWorkdirError`) — beats target resolution, the config load, and every network call | -| `1` | an explicit `--workdir`/`SUPABASE_WORKDIR` holds no project config (`ConfigPushLoadConfigError`) — checked again, right before target resolution, so a typo'd workdir fails without a branch-lookup round trip; a DEFAULTED workdir with no linked project instead fails with the not-linked error below | -| `1` | `HostedMutationDeclinedError` — the consent question was declined (rendered as `context canceled`); nothing was written, though the diff and cost lines were already printed | -| `1` | `HostedMutationConsentRequiredError` — there is something to write, no `--yes`/shell `SUPABASE_YES`, and the run cannot prompt (stdin not a TTY, redirected stdout, or machine output); nothing was written | -| `1` | `--remote` names a branch that doesn't exist, isn't provisioned yet, or fails to resolve (network/status failure); or names a branch by name while no project is linked, or the linked parent ref is invalid (CLI-2289) | -| `1` | malformed or missing `config.toml`/`config.json` | -| `1` | `config.toml`/`config.json` uses a removed key (`[inbucket]`, `experimental.orioledb_version` unless empty, `[auth.external.linkedin]`, `[auth.external.slack]`, at the top level or in a `[remotes.*]` block), or `SUPABASE_EXPERIMENTAL_ORIOLEDB_VERSION` is set to a non-empty value — the message names every removed key with its replacement; nothing is pushed | -| `1` | a flag, `SUPABASE_*` variable, project `.env*` file or config value fails to decode (`CliConfigValueError`) — names the source that supplied it; surfaced as-is, not wrapped in `ConfigPushLoadConfigError` | -| `1` | an `encrypted:` (dotenvx) secret anywhere in the document cannot be decrypted (`CliConfigValueError`, see below) | -| `1` | invalid `auth.email.*.content_path` (missing/unreadable template file, or a path that resolves outside the project root) | -| `1` | two `[remotes.*]` blocks declare the same `project_id` as the target ref | -| `1` | list-addons failure (network or non-200) | -| `1` | effective-project-config read failure (network, decode, or unexpected status) — one failure mode now covers what used to be six independent per-service read failures | -| `1` | the API's effective project configuration fails to parse | -| `1` | the effective-project-config response carried no block at all (`ConfigPushConfigEmptyError`) — nothing was pushed | -| `1` | any per-service update failure or webhook-enable failure (network or unexpected status) | +| Code | Condition | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `0` | success, **including** a push with nothing to write (the project already matches, so nothing is asked) | +| `1` | resolved `--workdir`/`SUPABASE_WORKDIR` doesn't exist or isn't a directory (`ConfigPushWorkdirError`) — beats target resolution, the config load, and every network call | +| `1` | an explicit `--workdir`/`SUPABASE_WORKDIR` holds no project config (`ConfigPushLoadConfigError`) — checked again, right before target resolution, so a typo'd workdir fails without a branch-lookup round trip; a DEFAULTED workdir with no linked project instead fails with the not-linked error below | +| `1` | `HostedMutationDeclinedError` — the consent question was declined (rendered as `context canceled`); nothing was written, though the diff and cost lines were already printed | +| `1` | `HostedMutationConsentRequiredError` — there is something to write, no `--yes`/shell `SUPABASE_YES`, and the run cannot prompt (stdin not a TTY, redirected stdout, or machine output); nothing was written | +| `1` | `--remote` names a branch that doesn't exist, isn't provisioned yet, or fails to resolve (network/status failure); or names a branch by name while no project is linked, or the linked parent ref is invalid (CLI-2289) | +| `1` | malformed or missing `config.toml`/`config.json` | +| `1` | `config.toml`/`config.json` uses a removed key (`inbucket`, `experimental.orioledb_version` unless empty, `auth.external.linkedin`, `auth.external.slack`, at the top level or in a `remotes.*` block), or `SUPABASE_EXPERIMENTAL_ORIOLEDB_VERSION` is set to a non-empty value — the message names every removed key with its replacement; nothing is pushed | +| `1` | a flag, `SUPABASE_*` variable, project `.env*` file or config value fails to decode (`CliConfigValueError`) — names the source that supplied it; surfaced as-is, not wrapped in `ConfigPushLoadConfigError` | +| `1` | an `encrypted:` (dotenvx) secret anywhere in the document cannot be decrypted (`CliConfigValueError`, see below) | +| `1` | invalid `auth.email.*.content_path` (missing/unreadable template file, or a path that resolves outside the project root) | +| `1` | two `[remotes.*]` blocks declare the same `project_id` as the target ref | +| `1` | list-addons failure (network or non-200) | +| `1` | effective-project-config read failure (network, decode, or unexpected status) — one failure mode now covers what used to be six independent per-service read failures | +| `1` | the API's effective project configuration fails to parse | +| `1` | the effective-project-config response carried no block at all (`ConfigPushConfigEmptyError`) — nothing was pushed | +| `1` | any per-service update failure or webhook-enable failure (network or unexpected status) | ## Output diff --git a/apps/cli/src/commands/config/push/push.integration.test.ts b/apps/cli/src/commands/config/push/push.integration.test.ts index 5d2f7b9a35..59d23eabfb 100644 --- a/apps/cli/src/commands/config/push/push.integration.test.ts +++ b/apps/cli/src/commands/config/push/push.integration.test.ts @@ -2150,7 +2150,7 @@ secret = "${DOTENVX_ENCRYPTED_VALUE}" Effect.catchTag("ConfigPushLoadConfigError", (error) => Effect.succeed(error.message)), ); expect(message).toBe( - "[auth.external.slack] in supabase/config.toml is no longer supported. Use [auth.external.slack_oidc] instead.", + "auth.external.slack in supabase/config.toml is no longer supported. Use auth.external.slack_oidc instead.", ); expect(api.requests).toHaveLength(0); }).pipe(Effect.provide(layer)); diff --git a/apps/cli/src/commands/db/diff/diff.integration.test.ts b/apps/cli/src/commands/db/diff/diff.integration.test.ts index 12f4e3ab0f..05a937b4b0 100644 --- a/apps/cli/src/commands/db/diff/diff.integration.test.ts +++ b/apps/cli/src/commands/db/diff/diff.integration.test.ts @@ -280,6 +280,7 @@ const runningStackApi = (projectRoot: string) => { const stack: Stack = { id: "b".repeat(64), services: { create: () => unused, get: () => Effect.succeed(database), list: unused }, + apiTls: { get: Effect.undefined }, credentials: { get: unused }, composition: { plan: () => unused, diff --git a/apps/cli/src/commands/db/dump/SIDE_EFFECTS.md b/apps/cli/src/commands/db/dump/SIDE_EFFECTS.md index 60a2e61772..3177f54f5f 100644 --- a/apps/cli/src/commands/db/dump/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/dump/SIDE_EFFECTS.md @@ -39,18 +39,18 @@ image), to stdout or `--file`. ## Environment Variables -| Variable | Purpose | -| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `SUPABASE_DB_PASSWORD` (`--password`/`-p` overrides) | remote DB password; ignored for a target other than the linked project (see Notes) | -| `SUPABASE_ACCESS_TOKEN` | auth for a remote project or branch | -| `SUPABASE_PROJECT_ID` | linked project ref override and the parent that `--remote=` is resolved against (superseded by `--remote=`) | -| `BITBUCKET_CLONE_DIR` | clears the `label:disable` security option that mounted TLS files add | -| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | rewrite the pg image registry for compose dumps; stack dumps use the catalog image pin unchanged | -| `SUPABASE_USE_SLIM_IMAGES` | resolve the current Postgres pin from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); majors 13/15 use `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | -| `DOCKER_HOST` | docker daemon endpoint | -| `MSYSTEM`, `TERM_PROGRAM` | suppress the piped-stdout non-ASCII warning in MSYS/mintty sessions | -| `PG*` libpq | remote TLS, timeout, service; see `db push`. An invalid value fails before `pg_dump` runs; a remote target also hands them to `pg_dump` (see Notes) | -| `SSL_CERT_FILE`, `SSL_CERT_DIR` | a native `pg_dump` on libpq 16+ keeps `sslrootcert=system` when either is set; libpq 15 uses only `SSL_CERT_FILE` | +| Variable | Purpose | +| ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SUPABASE_DB_PASSWORD` (`--password`/`-p` overrides) | remote DB password; ignored for a target other than the linked project (see Notes) | +| `SUPABASE_ACCESS_TOKEN` | auth for a remote project or branch | +| `SUPABASE_PROJECT_ID` | linked project ref override and the parent that `--remote=` is resolved against (superseded by `--remote=`) | +| `BITBUCKET_CLONE_DIR` | clears the `label:disable` security option that mounted TLS files add | +| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | rewrite the pg image registry for compose dumps; stack dumps use the catalog image pin unchanged | +| `SUPABASE_USE_SLIM_IMAGES` | resolve the current Postgres pin from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); major 15 uses `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | +| `DOCKER_HOST` | docker daemon endpoint | +| `MSYSTEM`, `TERM_PROGRAM` | suppress the piped-stdout non-ASCII warning in MSYS/mintty sessions | +| `PG*` libpq | remote TLS, timeout, service; see `db push`. An invalid value fails before `pg_dump` runs; a remote target also hands them to `pg_dump` (see Notes) | +| `SSL_CERT_FILE`, `SSL_CERT_DIR` | a native `pg_dump` on libpq 16+ keeps `sslrootcert=system` when either is set; libpq 15 uses only `SSL_CERT_FILE` | ## Exit Codes diff --git a/apps/cli/src/commands/db/dump/dump.integration.test.ts b/apps/cli/src/commands/db/dump/dump.integration.test.ts index 7b78614173..24cba8ee14 100644 --- a/apps/cli/src/commands/db/dump/dump.integration.test.ts +++ b/apps/cli/src/commands/db/dump/dump.integration.test.ts @@ -176,6 +176,7 @@ const managedDumpStackApi = (runtime: "native" | "docker") => { get: () => Effect.succeed(database), list: Effect.succeed([database]), }, + apiTls: { get: Effect.undefined }, credentials: { get: Effect.die("unused") }, composition: { plan: () => Effect.succeed([]), diff --git a/apps/cli/src/commands/db/pull/SIDE_EFFECTS.md b/apps/cli/src/commands/db/pull/SIDE_EFFECTS.md index 2a349c6e65..ea259c5d0d 100644 --- a/apps/cli/src/commands/db/pull/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/pull/SIDE_EFFECTS.md @@ -134,20 +134,20 @@ at all, so nothing is cached for it. ## Environment Variables -| Variable | Purpose | Required? | -| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -| `SUPABASE_ACCESS_TOKEN` | auth for a remote project or branch | no | -| `SUPABASE_DB_PASSWORD` | remote DB password (overridden by `-p`); ignored for a target other than the linked project (see Notes) | no | -| `SUPABASE_DB_SHADOW_PORT` | shadow container's host port (`db.shadow_port`) — NOT `SUPABASE_DB_PORT`, which the shadow never reads | no | -| `SUPABASE_DB_MAJOR_VERSION` / `SUPABASE_DB_HEALTH_TIMEOUT` / `SUPABASE_DB_SETTINGS_*` | shadow container-config overrides, same as `db start`/`db reset` | no | -| `SUPABASE_PROJECT_ID` | overrides the shadow container's project id/labels, same as `db start`/`db reset` (`utils.DbId`); ALSO the linked-ref resolution fallback and the parent project `--remote=` resolves against; `--remote=` supersedes it for the ref — see Notes for the narrower scope of the flag | no | -| `SUPABASE_NETWORK_ID` (`--network-id`) | forces the shadow and initial-migra `pg_dump` containers onto an existing Docker network | no | -| `SUPABASE_USE_SLIM_IMAGES` | resolves the current-pin shadow Postgres, `pg_dump`, PG15+ realtime/storage/auth migrate-job images (migration-style cold shadow), and (for migra) the edge-runtime image from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); majors 13/15 use `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, flag-off `15.8.1.085`, and `deno_version = 1` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | no | -| `SUPABASE_HOME` | overrides the `~/.supabase` root used for the shadow baseline cache (and other CLI state) | no | -| `SUPABASE_SHADOW_CACHE` | shadow baseline cache; on by default, opt-out (`0`/`false`); the shadow's post-baseline state is saved under a managed snapshot key and restored into the next run's fresh stack database (see Notes) | no | -| `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` | overrides `[experimental.pgdelta].enabled` (default true; `false` selects migra for the migration-style diff unless `--diff-engine` is passed, and lets a declarative export write `schema_paths`); a value that is not a boolean fails the command | no | -| `SUPABASE_EXPERIMENTAL` | resolving true (shell, then project `.env`) without `--declarative` fails the command with the removed structured-dump error; `--experimental=false` overrides it for one invocation | no | -| `PG*` libpq | remote-project TLS, timeout, service; see `db push`. The `pg_dump` seed gets them (see `db dump`); the migra container gets none of these `PG*` TLS settings (migra gets the CLI's own bundled CA outside its OOM fallback) | no | +| Variable | Purpose | Required? | +| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `SUPABASE_ACCESS_TOKEN` | auth for a remote project or branch | no | +| `SUPABASE_DB_PASSWORD` | remote DB password (overridden by `-p`); ignored for a target other than the linked project (see Notes) | no | +| `SUPABASE_DB_SHADOW_PORT` | shadow container's host port (`db.shadow_port`) — NOT `SUPABASE_DB_PORT`, which the shadow never reads | no | +| `SUPABASE_DB_MAJOR_VERSION` / `SUPABASE_DB_HEALTH_TIMEOUT` / `SUPABASE_DB_SETTINGS_*` | shadow container-config overrides, same as `db start`/`db reset` | no | +| `SUPABASE_PROJECT_ID` | overrides the shadow container's project id/labels, same as `db start`/`db reset` (`utils.DbId`); ALSO the linked-ref resolution fallback and the parent project `--remote=` resolves against; `--remote=` supersedes it for the ref — see Notes for the narrower scope of the flag | no | +| `SUPABASE_NETWORK_ID` (`--network-id`) | forces the shadow and initial-migra `pg_dump` containers onto an existing Docker network | no | +| `SUPABASE_USE_SLIM_IMAGES` | resolves the current-pin shadow Postgres, `pg_dump`, PG15+ realtime/storage/auth migrate-job images (migration-style cold shadow), and (for migra) the edge-runtime image from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); major 15 uses `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, flag-off `15.8.1.085`, and `deno_version = 1` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | no | +| `SUPABASE_HOME` | overrides the `~/.supabase` root used for the shadow baseline cache (and other CLI state) | no | +| `SUPABASE_SHADOW_CACHE` | shadow baseline cache; on by default, opt-out (`0`/`false`); the shadow's post-baseline state is saved under a managed snapshot key and restored into the next run's fresh stack database (see Notes) | no | +| `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` | overrides `[experimental.pgdelta].enabled` (default true; `false` selects migra for the migration-style diff unless `--diff-engine` is passed, and lets a declarative export write `schema_paths`); a value that is not a boolean fails the command | no | +| `SUPABASE_EXPERIMENTAL` | resolving true (shell, then project `.env`) without `--declarative` fails the command with the removed structured-dump error; `--experimental=false` overrides it for one invocation | no | +| `PG*` libpq | remote-project TLS, timeout, service; see `db push`. The `pg_dump` seed gets them (see `db dump`); the migra container gets none of these `PG*` TLS settings (migra gets the CLI's own bundled CA outside its OOM fallback) | no | ## Exit Codes diff --git a/apps/cli/src/commands/db/reset/SIDE_EFFECTS.md b/apps/cli/src/commands/db/reset/SIDE_EFFECTS.md index fd2c6c4d22..ad5c4104fc 100644 --- a/apps/cli/src/commands/db/reset/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/reset/SIDE_EFFECTS.md @@ -35,14 +35,19 @@ When the `experimental.stack` feature flag is on (`SUPABASE_EXPERIMENTAL_STACK=1 precedence, same rules as [`docs/stack-commands.md`](../../../../docs/stack-commands.md)), the local path stops the saved composition, resets the registered database instance's data, starts and readies that instance, reapplies the catalog overlay and migrations, then starts the saved -composition again instead of recreating containers. The reset retains the saved database -configuration and composition members; it does not rebuild the stack from current config. The -catalog overlay provisions the Auth, Storage, and Realtime schemas for the saved composition's -members, so services excluded at `stack start` stay excluded; for the database-only composition -that `db start` creates, it provisions the services enabled in current config instead. The -catalog also creates the `supabase_functions` schema, which migrations must not recreate. After -the reset, buckets are seeded — reusing the `seed buckets` local path — when Storage is running -(healthy or still starting), starting, or stopping/stopped with wake enabled; an unhealthy or +composition again instead of recreating containers. On a Docker or Podman stack started with +`[api.tls]`, that final start reruns the `api.tls` start check with a fresh nonce; if it fails, the +stack's services stop and the reset fails with `failed to start local stack services: ` followed by +the `stack start` api.tls error, which ends ``its services did not stop (), run `supabase +stack stop --stack-id ` to stop them`` when they don't stop. The reset retains the saved +database configuration and composition members; it does +not rebuild the stack from current config. The catalog overlay provisions the Auth, Storage, +and Realtime schemas for the saved composition's members, so services excluded at `stack +start` stay excluded; for the database-only composition that `db start` creates, it provisions +the services enabled in current config instead. The catalog also creates the +`supabase_functions` schema, which migrations must not recreate. After the reset, buckets are +seeded — reusing the `seed buckets` local path — when Storage is running (healthy or still +starting), starting, or stopping/stopped with wake enabled; an unhealthy or errored Storage is skipped. The gateway handles lazy activation. The command never fails the reset for a Storage problem: an unavailable service, missing credentials, a stack-gateway activation failure, or an invalid bucket config all print `WARNING: skipped seeding storage buckets: @@ -183,25 +188,25 @@ otherwise the satellites stay stopped with a warning to run `supabase stop && su ## Environment Variables -| Variable | Purpose | Required? | -| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | -| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | local path: ambient shell environment only (project dotenv files deliberately never override Docker client keys) — resolves the daemon endpoint for the running probe (in-process) and steers the spawned `docker`/`podman` CLI itself | no | -| `SUPABASE_ACCESS_TOKEN` | auth token for a remote project or branch | no (falls back to keyring → `~/.supabase/access-token`) | -| `SUPABASE_DB_PASSWORD` | password for the remote connection; ignored for a target other than the linked project (see Notes) | no | -| `SUPABASE_DB_SEED_ENABLED` | overrides `[db.seed].enabled` (flag > env > matched `[remotes.*]` > base); honoured on the local and remote paths | no | -| `SUPABASE_YES` | grants the hosted reset consent (shell only; a `SUPABASE_YES` in `supabase/.env` does not count) and auto-confirms the local path's bucket-seed overwrite/prune prompts (shell or project dotenv, same as `seed buckets`) | no (also `--yes`) | -| `SUPABASE_EXPERIMENTAL` | selects the schema-files apply branch on either target | no (also `--experimental`) | -| `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` | overrides `[experimental.pgdelta].enabled` (default true); `false` opens the reset gate (`experimental && resolvedVersion === "" && !toml.pgDelta.enabled`) so `--experimental` applies `schema_paths` files instead of timestamped migrations — switches between two different destructive code paths | no | -| `SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS` | overrides `[db.migrations].schema_paths` (beats the config-file value and a matched `[remotes.*]` block) for the schema-files apply branch — genuinely effective on both targets now | no (no dedicated flag — config-file-only otherwise) | -| `SUPABASE_PROJECT_ID` | overrides the local container id; ALSO the linked-ref resolution fallback and the parent project `--remote=` resolves against; `--remote=` supersedes it for the ref — see Notes for the narrower scope of the flag | no | -| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | overrides the image registry used to resolve the local path's container images (project `.env` or shell) | no (project `.env` or shell) | -| `SUPABASE_USE_SLIM_IMAGES` | resolves the local-reset Postgres image and the realtime/storage/auth migrate-job images from slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); majors 13/15 use `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | no (ambient shell only) | -| `SUPABASE_DB_PORT` / `SUPABASE_DB_MAJOR_VERSION` / `SUPABASE_DB_HEALTH_TIMEOUT` / `SUPABASE_DB_SETTINGS_*` | local-path container-recreate config overrides, same as `db start` | no | -| `SUPABASE_API_PORT` / `SUPABASE_API_EXTERNAL_URL` / `SUPABASE_API_TLS_*` / `SUPABASE_API_ENABLED` | legacy-backend bucket-seed step only: override the matching `[api]` fields for the Storage gateway URL/TLS, same as `seed buckets` (shell or project dotenv; #6452). Not consulted on the stack backend (see above) | no | -| `SUPABASE_AUTH_JWT_SECRET` / `SUPABASE_AUTH_SERVICE_ROLE_KEY` | local path: override `auth.jwt_secret` / `auth.service_role_key` (shell or project dotenv, `encrypted:` decrypted) — feeds the recreated Postgres container (jwt secret), the fresh-database setup jobs (both) and the legacy-backend bucket-seed Storage service-role key, same as `seed buckets`. Not consulted on the stack backend, which uses the stack's own service-role JWT | no | -| `SUPABASE_NETWORK_ID` (`--network-id`) | forces the recreated container/network onto an existing Docker network — legacy backend only | no | -| `SUPABASE_EXPERIMENTAL_STACK` | `1`/`0` selects the stack backend for the local path, overriding `experimental.stack` | no (→ `experimental.stack` → legacy) | -| `PG*` libpq | remote TLS, timeout, service; see `db push` | no | +| Variable | Purpose | Required? | +| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- | +| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | local path: ambient shell environment only (project dotenv files deliberately never override Docker client keys) — resolves the daemon endpoint for the running probe (in-process) and steers the spawned `docker`/`podman` CLI itself | no | +| `SUPABASE_ACCESS_TOKEN` | auth token for a remote project or branch | no (falls back to keyring → `~/.supabase/access-token`) | +| `SUPABASE_DB_PASSWORD` | password for the remote connection; ignored for a target other than the linked project (see Notes) | no | +| `SUPABASE_DB_SEED_ENABLED` | overrides `[db.seed].enabled` (flag > env > matched `[remotes.*]` > base); honoured on the local and remote paths | no | +| `SUPABASE_YES` | grants the hosted reset consent (shell only; a `SUPABASE_YES` in `supabase/.env` does not count) and auto-confirms the local path's bucket-seed overwrite/prune prompts (shell or project dotenv, same as `seed buckets`) | no (also `--yes`) | +| `SUPABASE_EXPERIMENTAL` | selects the schema-files apply branch on either target | no (also `--experimental`) | +| `SUPABASE_EXPERIMENTAL_PGDELTA_ENABLED` | overrides `[experimental.pgdelta].enabled` (default true); `false` opens the reset gate (`experimental && resolvedVersion === "" && !toml.pgDelta.enabled`) so `--experimental` applies `schema_paths` files instead of timestamped migrations — switches between two different destructive code paths | no | +| `SUPABASE_DB_MIGRATIONS_SCHEMA_PATHS` | overrides `[db.migrations].schema_paths` (beats the config-file value and a matched `[remotes.*]` block) for the schema-files apply branch — genuinely effective on both targets now | no (no dedicated flag — config-file-only otherwise) | +| `SUPABASE_PROJECT_ID` | overrides the local container id; ALSO the linked-ref resolution fallback and the parent project `--remote=` resolves against; `--remote=` supersedes it for the ref — see Notes for the narrower scope of the flag | no | +| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | overrides the image registry used to resolve the local path's container images (project `.env` or shell) | no (project `.env` or shell) | +| `SUPABASE_USE_SLIM_IMAGES` | resolves the local-reset Postgres image and the realtime/storage/auth migrate-job images from slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); major 15 uses `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli` | no (ambient shell only) | +| `SUPABASE_DB_PORT` / `SUPABASE_DB_MAJOR_VERSION` / `SUPABASE_DB_HEALTH_TIMEOUT` / `SUPABASE_DB_SETTINGS_*` | local-path container-recreate config overrides, same as `db start` | no | +| `SUPABASE_API_PORT` / `SUPABASE_API_EXTERNAL_URL` / `SUPABASE_API_TLS_*` / `SUPABASE_API_ENABLED` | legacy-backend bucket-seed step only: override the matching `[api]` fields for the Storage gateway URL/TLS, same as `seed buckets` (shell or project dotenv; #6452). Not consulted on the stack backend (see above) | no | +| `SUPABASE_AUTH_JWT_SECRET` / `SUPABASE_AUTH_SERVICE_ROLE_KEY` | local path: override `auth.jwt_secret` / `auth.service_role_key` (shell or project dotenv, `encrypted:` decrypted) — feeds the recreated Postgres container (jwt secret), the fresh-database setup jobs (both) and the legacy-backend bucket-seed Storage service-role key, same as `seed buckets`. Not consulted on the stack backend, which uses the stack's own service-role JWT | no | +| `SUPABASE_NETWORK_ID` (`--network-id`) | forces the recreated container/network onto an existing Docker network — legacy backend only | no | +| `SUPABASE_EXPERIMENTAL_STACK` | `1`/`0` selects the stack backend for the local path, overriding `experimental.stack` | no (→ `experimental.stack` → legacy) | +| `PG*` libpq | remote TLS, timeout, service; see `db push` | no | ## Connection loss during migration apply diff --git a/apps/cli/src/commands/db/reset/reset.integration.test.ts b/apps/cli/src/commands/db/reset/reset.integration.test.ts index d1fd3a4aae..3db0e145b8 100644 --- a/apps/cli/src/commands/db/reset/reset.integration.test.ts +++ b/apps/cli/src/commands/db/reset/reset.integration.test.ts @@ -843,6 +843,7 @@ function mockResetStackApi(opts: { }, list: Effect.succeed(members), }, + apiTls: { get: Effect.undefined }, credentials: { get: Effect.succeed(RESET_STACK_CREDENTIALS) }, composition: { plan: () => Effect.succeed([]), diff --git a/apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md b/apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md index 1fdb8e1b07..592346f866 100644 --- a/apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/schema/declarative/generate/SIDE_EFFECTS.md @@ -49,17 +49,17 @@ formatting without disabling safe compaction. ## Environment Variables -| Variable | Purpose | Required? | -| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `SUPABASE_ACCESS_TOKEN` | auth token for a remote project or branch | no | -| `SUPABASE_DB_PASSWORD` | remote database password for a remote project or branch (`--password`/`-p` overrides) | -| `SUPABASE_PROJECT_ID` | the project ref of a bare `--remote` target, and the parent that `--remote=` is resolved against | -| `SUPABASE_HOME` | overrides the `~/.supabase` root (access token and other CLI state) | no | -| `PGDELTA_DEBUG` | bundled-engine debug artifacts | no | -| `SUPABASE_SERVICES_HOSTNAME` | local DB host for a local target | no | -| `DOCKER_HOST` | tcp daemon host used as the local DB host fallback | no | -| `SUPABASE_USE_SLIM_IMAGES` | resolves the expected local `db` image for the stale-container guard from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); majors 13/15 use `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a container started from the `public.ecr.aws/supabase/cli` mirror counts as slim | no | -| `PG*` libpq | remote-project TLS, timeout, service; see `db push` | no | +| Variable | Purpose | Required? | +| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `SUPABASE_ACCESS_TOKEN` | auth token for a remote project or branch | no | +| `SUPABASE_DB_PASSWORD` | remote database password for a remote project or branch (`--password`/`-p` overrides) | +| `SUPABASE_PROJECT_ID` | the project ref of a bare `--remote` target, and the parent that `--remote=` is resolved against | +| `SUPABASE_HOME` | overrides the `~/.supabase` root (access token and other CLI state) | no | +| `PGDELTA_DEBUG` | bundled-engine debug artifacts | no | +| `SUPABASE_SERVICES_HOSTNAME` | local DB host for a local target | no | +| `DOCKER_HOST` | tcp daemon host used as the local DB host fallback | no | +| `SUPABASE_USE_SLIM_IMAGES` | resolves the expected local `db` image for the stale-container guard from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); major 15 uses `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a container started from the `public.ecr.aws/supabase/cli` mirror counts as slim | no | +| `PG*` libpq | remote-project TLS, timeout, service; see `db push` | no | ## Exit Codes diff --git a/apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts b/apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts index f5c02a2d3a..4082a12025 100644 --- a/apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts +++ b/apps/cli/src/commands/db/schema/declarative/generate/generate.integration.test.ts @@ -177,6 +177,7 @@ function generateStackApi(workdir: string) { ? Effect.succeed(database) : Effect.fail(new StackError({ operation: "get", message: "unknown instance" })), }, + apiTls: { get: Effect.undefined }, credentials: { get: unusedStack }, composition: { plan: () => Effect.succeed([]), diff --git a/apps/cli/src/commands/db/schema/declarative/sync/SIDE_EFFECTS.md b/apps/cli/src/commands/db/schema/declarative/sync/SIDE_EFFECTS.md index 86606fca80..5ce8c8e3d9 100644 --- a/apps/cli/src/commands/db/schema/declarative/sync/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/schema/declarative/sync/SIDE_EFFECTS.md @@ -58,15 +58,15 @@ disabling safe compaction. ## Environment Variables -| Variable | Purpose | Required? | -| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `SUPABASE_HOME` | overrides the `~/.supabase` root used for the shadow baseline cache (and other CLI state) | no | -| `SUPABASE_SHADOW_CACHE` | shadow baseline cache; on by default, opt-out (`0`/`false`); the shadow's post-baseline state is saved under a managed snapshot key and restored into the next run's fresh stack database (see Notes) | no | -| `PGDELTA_DEBUG` | bundled-engine debug artifacts | no | -| `SUPABASE_SERVICES_HOSTNAME` | local DB host for the bootstrap generate | no | -| `DOCKER_HOST` | tcp daemon host used as the local DB host fallback | no | -| `SUPABASE_USE_SLIM_IMAGES` | resolves the current-pin shadow Postgres and PG15+ realtime/storage/auth migrate-job images from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); majors 13/15 use `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli`; a container started from that mirror counts as slim | no | -| `PG*` libpq | no-files bootstrap only, when the target prompt picks **Linked project**: remote-project TLS, timeout, service; see `db push`. Sync itself has no target flag | no | +| Variable | Purpose | Required? | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | +| `SUPABASE_HOME` | overrides the `~/.supabase` root used for the shadow baseline cache (and other CLI state) | no | +| `SUPABASE_SHADOW_CACHE` | shadow baseline cache; on by default, opt-out (`0`/`false`); the shadow's post-baseline state is saved under a managed snapshot key and restored into the next run's fresh stack database (see Notes) | no | +| `PGDELTA_DEBUG` | bundled-engine debug artifacts | no | +| `SUPABASE_SERVICES_HOSTNAME` | local DB host for the bootstrap generate | no | +| `DOCKER_HOST` | tcp daemon host used as the local DB host fallback | no | +| `SUPABASE_USE_SLIM_IMAGES` | resolves the current-pin shadow Postgres and PG15+ realtime/storage/auth migrate-job images from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); major 15 uses `15.14.1.167` when the flag is on; historical pins, PG14, OrioleDB tags the catalog does not pin, and flag-off `15.8.1.085` stay on docker.io; a failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli`; a container started from that mirror counts as slim | no | +| `PG*` libpq | no-files bootstrap only, when the target prompt picks **Linked project**: remote-project TLS, timeout, service; see `db push`. Sync itself has no target flag | no | ## Exit Codes diff --git a/apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts b/apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts index b3ebb1e2ee..cc22063dd9 100644 --- a/apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts +++ b/apps/cli/src/commands/db/schema/declarative/sync/sync.integration.test.ts @@ -176,6 +176,7 @@ function syncStackApi(workdir: string, port: number) { ? Effect.succeed(database) : Effect.fail(new StackError({ operation: "get", message: "unknown instance" })), }, + apiTls: { get: Effect.undefined }, credentials: { get: unusedSync }, composition: { plan: () => Effect.succeed([]), diff --git a/apps/cli/src/commands/db/start/SIDE_EFFECTS.md b/apps/cli/src/commands/db/start/SIDE_EFFECTS.md index 69995b0ccc..2ab9186749 100644 --- a/apps/cli/src/commands/db/start/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/db/start/SIDE_EFFECTS.md @@ -44,10 +44,10 @@ composition reuses too — see that command's `SIDE_EFFECTS.md`): `cron.launch_active_jobs = off` appended to `postgresql.conf` — applies regardless of `db.major_version`. The backup file itself is bind-mounted `:ro` at `/etc/backup.sql` (host path resolved against the CALLER's cwd when relative). - `SUPABASE_USE_SLIM_IMAGES` rewrites the current Dockerfile pin (and majors - 13/15's published slim PG15 pin, `15.14.1.167`) to + `SUPABASE_USE_SLIM_IMAGES` rewrites the current Dockerfile pin (and major + 15's published slim PG15 pin, `15.14.1.167`) to `ghcr.io/supabase/cli/postgres`; a historical `.temp/postgres-version` pin, - PG14, OrioleDB tags the catalog does not pin, and flag-off majors 13/15 (`15.8.1.085`) stay on docker.io. + PG14, OrioleDB tags the catalog does not pin, and flag-off major 15 (`15.8.1.085`) stay on docker.io. A failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli/postgres`. The restore entrypoint is the same on both families. 6. Wait for Postgres to accept connections (`db.health_timeout`, default `2m`): every 500ms, @@ -158,25 +158,25 @@ API request over the active context's local unix socket / named pipe: ## Environment Variables -| Variable | Purpose | Required? | -| -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `SUPABASE_PROJECT_ID` | overrides the local container id | no | -| `SUPABASE_DB_PORT` | overrides `db.port` (the published host port) | no | -| `SUPABASE_DB_MAJOR_VERSION` | overrides `db.major_version` (image selection, schema branch) | no | -| `SUPABASE_DB_HEALTH_TIMEOUT` | overrides `db.health_timeout` | no | -| `SUPABASE_DB_SETTINGS_*` | overrides individual `[db.settings]` fields | no | -| `SUPABASE_DB_ORIOLEDB_VERSION` | overrides `db.orioledb_version` (image + env) | no | -| `SUPABASE_EXPERIMENTAL_S3_{HOST,REGION,ACCESS_KEY,SECRET_KEY}` | OrioleDB S3 env overrides | no | -| `SUPABASE_REALTIME_ENABLED` | gates the fresh-volume realtime migrate job | no | -| `SUPABASE_REALTIME_IP_VERSION` / `_MAX_HEADER_LENGTH` | realtime migrate job env overrides | no | -| `SUPABASE_STORAGE_ENABLED` | gates the fresh-volume storage migrate job | no | -| `SUPABASE_STORAGE_FILE_SIZE_LIMIT` | storage migrate job env override | no | -| `SUPABASE_AUTH_ENABLED` | gates the fresh-volume auth migrate job | no | -| `SUPABASE_AUTH_EXTERNAL_URL` / `SUPABASE_AUTH_SITE_URL` | auth migrate job env overrides | no | -| `SUPABASE_AUTH_JWT_EXPIRY` | Postgres's `JWT_EXP` env / signing | no | -| `SUPABASE_EXPERIMENTAL` (or `--experimental`) | fresh volume + no pg-delta: applies `db.migrations.schema_paths` files instead of `migrations/*.sql` | no | -| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | Read from the ambient shell environment to pick the Docker daemon this whole command talks to (project dotenv files deliberately never override Docker client keys) | no | -| `SUPABASE_USE_SLIM_IMAGES` | resolves the current Dockerfile pin (and majors 13/15's published slim PG15 pin, `15.14.1.167`) and PG15+ realtime/storage/auth migrate-job images from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); historical `.temp` pins, PG14, OrioleDB tags the catalog does not pin, and flag-off majors 13/15 (`15.8.1.085`) stay on docker.io | no | +| Variable | Purpose | Required? | +| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `SUPABASE_PROJECT_ID` | overrides the local container id | no | +| `SUPABASE_DB_PORT` | overrides `db.port` (the published host port) | no | +| `SUPABASE_DB_MAJOR_VERSION` | overrides `db.major_version` (image selection, schema branch) | no | +| `SUPABASE_DB_HEALTH_TIMEOUT` | overrides `db.health_timeout` | no | +| `SUPABASE_DB_SETTINGS_*` | overrides individual `[db.settings]` fields | no | +| `SUPABASE_DB_ORIOLEDB_VERSION` | overrides `db.orioledb_version` (image + env) | no | +| `SUPABASE_EXPERIMENTAL_S3_{HOST,REGION,ACCESS_KEY,SECRET_KEY}` | OrioleDB S3 env overrides | no | +| `SUPABASE_REALTIME_ENABLED` | gates the fresh-volume realtime migrate job | no | +| `SUPABASE_REALTIME_IP_VERSION` / `_MAX_HEADER_LENGTH` | realtime migrate job env overrides | no | +| `SUPABASE_STORAGE_ENABLED` | gates the fresh-volume storage migrate job | no | +| `SUPABASE_STORAGE_FILE_SIZE_LIMIT` | storage migrate job env override | no | +| `SUPABASE_AUTH_ENABLED` | gates the fresh-volume auth migrate job | no | +| `SUPABASE_AUTH_EXTERNAL_URL` / `SUPABASE_AUTH_SITE_URL` | auth migrate job env overrides | no | +| `SUPABASE_AUTH_JWT_EXPIRY` | Postgres's `JWT_EXP` env / signing | no | +| `SUPABASE_EXPERIMENTAL` (or `--experimental`) | fresh volume + no pg-delta: applies `db.migrations.schema_paths` files instead of `migrations/*.sql` | no | +| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | Read from the ambient shell environment to pick the Docker daemon this whole command talks to (project dotenv files deliberately never override Docker client keys) | no | +| `SUPABASE_USE_SLIM_IMAGES` | resolves the current Dockerfile pin (and major 15's published slim PG15 pin, `15.14.1.167`) and PG15+ realtime/storage/auth migrate-job images from the slim `ghcr.io/supabase/cli` builds (`true`/`1` enable); historical `.temp` pins, PG14, OrioleDB tags the catalog does not pin, and flag-off major 15 (`15.8.1.085`) stay on docker.io | no | `--network-id` (a global CLI flag, not an environment variable — `command-internal/global-flags.ts`) forces every created container/network onto that Docker network instead of the generated @@ -204,6 +204,8 @@ code is surfaced on failure. ### `--output-format text` +- `db.major_version = 14` → a `WARNING:` line on **stderr** saying Postgres 14 is end of life + and the CLI will drop support for it soon, printed before the already-running check. - Already running → `Postgres database is already running.` on **stderr**, exit 0. - Starting → `Starting database...` / `Starting database from backup...`, then (fresh volume, no `--from-backup`) `Initialising schema...` and `Seeding globals from diff --git a/apps/cli/src/commands/db/start/start.integration.test.ts b/apps/cli/src/commands/db/start/start.integration.test.ts index e61e2df631..9c03b4cbf3 100644 --- a/apps/cli/src/commands/db/start/start.integration.test.ts +++ b/apps/cli/src/commands/db/start/start.integration.test.ts @@ -862,6 +862,7 @@ describe("db start", () => { }); return Effect.gen(function* () { yield* dbStart(DEFAULT_FLAGS).pipe(Effect.provide(layer)); + expect(out.stderrText).toContain("Postgres 14 reached end of life"); expect(out.stderrText).toContain("Initialising schema..."); expect(dbSetupJobCalls(child.spawned)).toHaveLength(0); expect(dbSession.calls.length).toBeGreaterThan(0); @@ -1950,7 +1951,7 @@ describe("db start", () => { const message = Cause.pretty(exit.cause); expect(message).toContain("DbConfigLoadError"); expect(message).toContain( - "[inbucket] in supabase/config.toml is no longer supported. Use [local_smtp] instead.", + "inbucket in supabase/config.toml is no longer supported. Use local_smtp instead.", ); } expect(child.spawned.some((s) => s.args[0] === "create")).toBe(false); @@ -2161,6 +2162,7 @@ describe("db start stack backend", () => { : Effect.fail(new StackError({ operation: "get", message: `unknown ${id}` })), list: Effect.sync(() => registered), }, + apiTls: { get: Effect.undefined }, credentials: { get: Effect.succeed({ jwtSecret: "secret", diff --git a/apps/cli/src/commands/domains/SIDE_EFFECTS.md b/apps/cli/src/commands/domains/SIDE_EFFECTS.md index 78de585c3c..d750175a79 100644 --- a/apps/cli/src/commands/domains/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/domains/SIDE_EFFECTS.md @@ -60,10 +60,10 @@ Cloudflare DNS-over-HTTPS CNAME pre-check. ## Telemetry Events Fired -| Event | When | Notable properties / groups | -| ----------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` (all redacted — no `domains` flag is telemetry-safe); a rejected `--include-raw-output` fails with `error_fingerprint` ending in `:removed_flag` (`RemovedSurfaceError`) | -| `cli_upgrade_suggested` | `create`/`get`/`activate`/`reverify` 4xx carrying the `entitlement_required` envelope | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`); envelope-only, no entitlements fallback | +| Event | When | Notable properties / groups | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `cli_command_executed` | post-run, success or failure (via wrapper) | `exit_code`, `duration_ms`, `flags` (all redacted — no `domains` flag is telemetry-safe); a rejected `--include-raw-output` fails with `error_fingerprint` ending in `:removed_flag` (`RemovedSurfaceError`) | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a `create`/`get`/`activate`/`reverify` 4xx carrying the `entitlement_required` envelope | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`); envelope-only, no entitlements fallback | ## Output diff --git a/apps/cli/src/commands/domains/activate/activate.handler.ts b/apps/cli/src/commands/domains/activate/activate.handler.ts index 3ecc38ee71..167db3d162 100644 --- a/apps/cli/src/commands/domains/activate/activate.handler.ts +++ b/apps/cli/src/commands/domains/activate/activate.handler.ts @@ -8,7 +8,6 @@ import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; import { emitHostnameResult } from "../domains.emit.ts"; import { mapDomainsHttpError } from "../domains.errors.ts"; import { requireHostedMutationConsent } from "../../../command-internal/hosted-consent/hosted-consent.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import type { DomainsActivateFlags } from "./activate.command.ts"; const mapActivateError = mapDomainsHttpError("activate"); @@ -33,7 +32,7 @@ export const domainsActivate = Effect.fn("domains.activate")(function* ( output.format === "text" ? yield* output.task("Activating custom hostname...") : undefined; const response = yield* api.v1.activateCustomHostname({ ref }).pipe( Effect.tapError(() => activating?.fail() ?? Effect.void), - Effect.catch(gateMapError({ projectRef: ref }, mapActivateError)), + Effect.catch(mapActivateError), ); yield* activating?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/domains/activate/activate.integration.test.ts b/apps/cli/src/commands/domains/activate/activate.integration.test.ts index 9f91574859..efb0ad9151 100644 --- a/apps/cli/src/commands/domains/activate/activate.integration.test.ts +++ b/apps/cli/src/commands/domains/activate/activate.integration.test.ts @@ -91,7 +91,7 @@ const baseFlags = { }; describe("domains activate integration", () => { - it.effect("suggests upgrade from entitlement_required envelope on 400", () => { + it.effect("fails with the entitlement_required envelope's entitlement on 400", () => { const { layer, out, analytics, api } = setup({ status: 400, response: { @@ -105,18 +105,17 @@ describe("domains activate integration", () => { }, }); return Effect.gen(function* () { - const exit = yield* Effect.exit(domainsActivate(baseFlags)); - expect(Exit.isFailure(exit)).toBe(true); + const error = yield* Effect.flip(domainsActivate(baseFlags)); + expect(error).toMatchObject({ + entitlement: { + feature: "custom_domain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); expect(api.requests).toHaveLength(1); assertPermissionDrift({ command: "domains activate", requests: api.requests }); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "custom_domain", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); diff --git a/apps/cli/src/commands/domains/create/create.handler.ts b/apps/cli/src/commands/domains/create/create.handler.ts index 8eaf665f15..de861add98 100644 --- a/apps/cli/src/commands/domains/create/create.handler.ts +++ b/apps/cli/src/commands/domains/create/create.handler.ts @@ -11,7 +11,6 @@ import { verifyCname } from "../domains.cname.ts"; import { emitHostnameResult } from "../domains.emit.ts"; import { mapDomainsHttpError } from "../domains.errors.ts"; import { requireHostedMutationConsent } from "../../../command-internal/hosted-consent/hosted-consent.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import type { DomainsCreateFlags } from "./create.command.ts"; const mapCreateError = mapDomainsHttpError("create"); @@ -48,7 +47,7 @@ export const domainsCreate = Effect.fn("domains.create")(function* (flags: Domai .updateHostnameConfig({ ref, custom_hostname: flags.customHostname }) .pipe( Effect.tapError(() => creating?.fail() ?? Effect.void), - Effect.catch(gateMapError({ projectRef: ref }, mapCreateError)), + Effect.catch(mapCreateError), ); yield* creating?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/domains/create/create.integration.test.ts b/apps/cli/src/commands/domains/create/create.integration.test.ts index a73af421a2..f47bc3216a 100644 --- a/apps/cli/src/commands/domains/create/create.integration.test.ts +++ b/apps/cli/src/commands/domains/create/create.integration.test.ts @@ -151,7 +151,7 @@ describe("domains create integration", () => { }).pipe(Effect.provide(layer)); }); - it.effect("suggests upgrade from entitlement_required envelope on 400", () => { + it.effect("fails with the entitlement_required envelope's entitlement on 400", () => { const { layer, out, analytics, api } = setup({ apiStatus: 400, apiResponse: { @@ -165,19 +165,18 @@ describe("domains create integration", () => { }, }); return Effect.gen(function* () { - const exit = yield* Effect.exit(domainsCreate(flags())); - expect(Exit.isFailure(exit)).toBe(true); + const error = yield* Effect.flip(domainsCreate(flags())); + expect(error).toMatchObject({ + entitlement: { + feature: "custom_domain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); expect(api.requests).toHaveLength(2); expect(postedToInitialize(api)).toBe(true); assertPermissionDrift({ command: "domains create", requests: api.requests }); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "custom_domain", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); diff --git a/apps/cli/src/commands/domains/get/get.handler.ts b/apps/cli/src/commands/domains/get/get.handler.ts index fb14b2e700..8dfacc7905 100644 --- a/apps/cli/src/commands/domains/get/get.handler.ts +++ b/apps/cli/src/commands/domains/get/get.handler.ts @@ -7,7 +7,6 @@ import { LinkedProjectCache } from "../../../telemetry/linked-project-cache.serv import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; import { emitHostnameResult } from "../domains.emit.ts"; import { mapDomainsHttpError } from "../domains.errors.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import type { DomainsGetFlags } from "./get.command.ts"; const mapGetError = mapDomainsHttpError("get"); @@ -29,7 +28,7 @@ export const domainsGet = Effect.fn("domains.get")(function* (flags: DomainsGetF : undefined; const response = yield* api.v1.getHostnameConfig({ ref }).pipe( Effect.tapError(() => fetching?.fail() ?? Effect.void), - Effect.catch(gateMapError({ projectRef: ref }, mapGetError)), + Effect.catch(mapGetError), ); yield* fetching?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/domains/get/get.integration.test.ts b/apps/cli/src/commands/domains/get/get.integration.test.ts index ab61e36eba..e74e099b47 100644 --- a/apps/cli/src/commands/domains/get/get.integration.test.ts +++ b/apps/cli/src/commands/domains/get/get.integration.test.ts @@ -373,7 +373,7 @@ describe("domains get integration", () => { }).pipe(Effect.provide(layer)); }); - it.effect("suggests upgrade from entitlement_required envelope on 400", () => { + it.effect("fails with the entitlement_required envelope's entitlement on 400", () => { const { layer, out, analytics, api } = setup({ status: 400, response: { @@ -387,18 +387,17 @@ describe("domains get integration", () => { }, }); return Effect.gen(function* () { - const exit = yield* Effect.exit(domainsGet(baseFlags)); - expect(Exit.isFailure(exit)).toBe(true); + const error = yield* Effect.flip(domainsGet(baseFlags)); + expect(error).toMatchObject({ + entitlement: { + feature: "custom_domain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); expect(api.requests).toHaveLength(1); assertPermissionDrift({ command: "domains get", requests: api.requests }); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "custom_domain", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); diff --git a/apps/cli/src/commands/domains/reverify/reverify.handler.ts b/apps/cli/src/commands/domains/reverify/reverify.handler.ts index 6683caea67..bb77ea5590 100644 --- a/apps/cli/src/commands/domains/reverify/reverify.handler.ts +++ b/apps/cli/src/commands/domains/reverify/reverify.handler.ts @@ -7,7 +7,6 @@ import { LinkedProjectCache } from "../../../telemetry/linked-project-cache.serv import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; import { emitHostnameResult } from "../domains.emit.ts"; import { mapDomainsHttpError } from "../domains.errors.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import type { DomainsReverifyFlags } from "./reverify.command.ts"; const mapReverifyError = mapDomainsHttpError("re-verify"); @@ -27,7 +26,7 @@ export const domainsReverify = Effect.fn("domains.reverify")(function* ( output.format === "text" ? yield* output.task("Re-verifying custom hostname...") : undefined; const response = yield* api.v1.verifyDnsConfig({ ref }).pipe( Effect.tapError(() => reverifying?.fail() ?? Effect.void), - Effect.catch(gateMapError({ projectRef: ref }, mapReverifyError)), + Effect.catch(mapReverifyError), ); yield* reverifying?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/domains/reverify/reverify.integration.test.ts b/apps/cli/src/commands/domains/reverify/reverify.integration.test.ts index 5eb4006728..8ebd89e7fa 100644 --- a/apps/cli/src/commands/domains/reverify/reverify.integration.test.ts +++ b/apps/cli/src/commands/domains/reverify/reverify.integration.test.ts @@ -83,7 +83,7 @@ const baseFlags = { }; describe("domains reverify integration", () => { - it.effect("suggests upgrade from entitlement_required envelope on 400", () => { + it.effect("fails with the entitlement_required envelope's entitlement on 400", () => { const { layer, out, analytics, api } = setup({ status: 400, response: { @@ -97,17 +97,16 @@ describe("domains reverify integration", () => { }, }); return Effect.gen(function* () { - const exit = yield* Effect.exit(domainsReverify(baseFlags)); - expect(Exit.isFailure(exit)).toBe(true); - expect(api.requests).toHaveLength(1); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "custom_domain", org_slug: "env-org" }, + const error = yield* Effect.flip(domainsReverify(baseFlags)); + expect(error).toMatchObject({ + entitlement: { + feature: "custom_domain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", }, - ]); + }); + expect(api.requests).toHaveLength(1); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); diff --git a/apps/cli/src/commands/experimental/compute/new/SIDE_EFFECTS.md b/apps/cli/src/commands/experimental/compute/new/SIDE_EFFECTS.md index 2010ab82f5..3c50cb3f3f 100644 --- a/apps/cli/src/commands/experimental/compute/new/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/experimental/compute/new/SIDE_EFFECTS.md @@ -25,13 +25,13 @@ and the command handler does not run. See the [Compute command guide](../../../. ## Files Written -| Path | Format | When | -| ----------------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `/supabase/config.{json,jsonc}` | JSON | on success, when it is the selected config — adds `compute.` with the same keys, keeping comments | -| `/supabase/config.toml` | TOML | on success — appends `[compute.]` with `runtime`, `size` and `exposure` always, `exclude` whenever the chosen runtime declares default patterns, `instances` only when it differs from the default of 1, and `source` only when `--source` was passed, preserving surrounding formatting | -| `/supabase/compute//*` | varies | on success, unless `--source` names another directory | -| `//*` | varies | on success, when `--source` is given | -| `/telemetry.json` | JSON | whenever the handler runs — flushed on success and on failure | +| Path | Format | When | +| ----------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `/supabase/config.{json,jsonc}` | JSON | on success, when it is the selected config — adds `compute.` with the same keys, keeping comments | +| `/supabase/config.toml` | TOML | on success — appends `[compute.]` with `runtime`, `size`, `exposure` and `secrets_scope` always, `exclude` whenever the chosen runtime declares default patterns, `instances` only when it differs from the default of 1, and `source` only when `--source` was passed, preserving surrounding formatting | +| `/supabase/compute//*` | varies | on success, unless `--source` names another directory | +| `//*` | varies | on success, when `--source` is given | +| `/telemetry.json` | JSON | whenever the handler runs — flushed on success and on failure | ## Default `exclude` patterns @@ -68,12 +68,12 @@ prompt refuses a name that is not a DNS label or that `config.toml` already records — so nothing is asked, and nothing written, for a name the command was going to refuse. With `-o json|yaml|toml|env`, a redirected stdout, or a stdin that is not a terminal, there is nowhere to ask, and the command fails instead -of defaulting: unlike the runtime, size and exposure, the name has no default to +of defaulting: unlike the runtime, size, exposure and secrets scope, the name has no default to fall back on. Every prompt is gated on both streams, so `printf 'api\n' | supabase compute new` takes that failure path rather than reading the compute name off the pipe. -`runtime`, `size` and `exposure` are always written, defaults included: they are +`runtime`, `size`, `exposure` and `secrets_scope` are always written, defaults included: they are closed sets the command prompts for, and pinning the answer is the point of recording it. `instances` is written only when it differs from the default of 1 — it has no prompt, because how many instances a compute needs is not something a @@ -138,7 +138,7 @@ No custom events — only the `cli_command_executed` that the instrumentation wrapper emits for every command. Nothing is emitted for a failure the parser catches, such as a -`--runtime`/`--size`/`--exposure` value outside the choice list, or a negative +`--runtime`/`--size`/`--exposure`/`--secrets-scope`/`--secrets-scope:custom` value outside the choice list, or a negative `--instances`. The wrapper is installed by `Command.withHandler`, so a command that never reaches its handler never reaches the instrumentation either — and `telemetry.json` is not written. A missing name diff --git a/apps/cli/src/commands/experimental/compute/new/new.command.ts b/apps/cli/src/commands/experimental/compute/new/new.command.ts index c55f468cc3..0a675dd089 100644 --- a/apps/cli/src/commands/experimental/compute/new/new.command.ts +++ b/apps/cli/src/commands/experimental/compute/new/new.command.ts @@ -1,5 +1,5 @@ -import { Layer } from "effect"; -import { Argument, Command, Flag } from "effect/cli"; +import { Effect, Layer, Option } from "effect"; +import { Argument, CliError, Command, Flag } from "effect/cli"; import type * as CliCommand from "effect/cli/Command"; import { withPermissions } from "../../../../command-internal/command-permissions/command-permissions.annotation.ts"; import { withCliConfigFlags } from "../../../../config/cli-config-flags.ts"; @@ -9,7 +9,9 @@ import { commandRuntimeLayer } from "../../../../shared/runtime/command-runtime. import { COMPUTE_EXPOSURES, COMPUTE_RUNTIMES, + COMPUTE_SECRETS_SCOPE, COMPUTE_SIZES, + parseSecretsScopeCustom, } from "../../../../shared/compute/compute-runtimes.ts"; import { commandSettingsLayer } from "../../../../config/command-settings.layer.ts"; import { debugLoggerLayer } from "../../../../command-internal/debug-logger.layer.ts"; @@ -43,6 +45,24 @@ const config = { ), Flag.optional, ), + secretsScope: Flag.Literals("secrets-scope", COMPUTE_SECRETS_SCOPE).pipe( + Flag.withDescription( + "Controls whether secrets are available, overriding `secrets_scope` in the project config file for this deploy. Falls back to the recorded value, then all.", + ), + Flag.optional, + ), + secretsScopeCustom: Flag.String("secrets-scope:custom").pipe( + Flag.map(parseSecretsScopeCustom), + Flag.withMetavar("SECRET_NAMES"), + Flag.withDescription( + "Controls whether secrets are available, overriding `secrets_scope` with a comma separated list of allowed secret names. Falls back to the recorded value, then all.", + ), + Flag.filter( + (secretNames) => secretNames != undefined && secretNames.length > 0, + () => "Must contain at least one secret name.", + ), + Flag.optional, + ), instances: Flag.Int("instances").pipe( // Bounded at the parser, the same way `push --instances` and the config // schema's own `instances` are. @@ -107,7 +127,15 @@ export const computeNewCommand = Command.make("new", config).pipe( ]), withPermissions({ operations: [], - noApiEffectFlags: ["runtime", "size", "exposure", "instances", "source"], + noApiEffectFlags: [ + "runtime", + "size", + "exposure", + "secrets-scope", + "secrets-scope:custom", + "instances", + "source", + ], }), Command.withHandler((flags) => computeNew(flags).pipe(withCommandTelemetry({ flags, config }), withJsonErrorHandling), @@ -116,4 +144,13 @@ export const computeNewCommand = Command.make("new", config).pipe( Command.provide(cliConfigValuesLayer), withCliConfigFlags(config), withTargetPolicy({ group: "local-only", consent: "none" }), + Command.validate(({ secretsScope, secretsScopeCustom }) => + Option.isSome(secretsScope) && Option.isSome(secretsScopeCustom) + ? Effect.fail( + new CliError.ValidationError({ + message: "--secrets-scope and --secrets-scope:custom are mutually exclusive", + }), + ) + : Effect.void, + ), ); diff --git a/apps/cli/src/commands/experimental/compute/new/new.handler.ts b/apps/cli/src/commands/experimental/compute/new/new.handler.ts index 31daedad16..508689ee3d 100644 --- a/apps/cli/src/commands/experimental/compute/new/new.handler.ts +++ b/apps/cli/src/commands/experimental/compute/new/new.handler.ts @@ -40,6 +40,14 @@ import { type ComputeExposure, type ComputeRuntime, type ComputeSize, + DEFAULT_COMPUTE_SECRETS_SCOPE, + COMPUTE_SECRETS_SCOPE_DESCRIPTIONS, + parseComputeSecretsScope, + type ComputeSecretsScopeEnum, + COMPUTE_SECRETS_SCOPE_ENUM, + type ComputeSecretsScope, + parseSecretsScopeCustom, + formatSecretsScope, } from "../../../../shared/compute/compute-runtimes.ts"; import { COMPUTE_STACKS } from "../../../../shared/compute/compute-stacks.ts"; import { @@ -199,6 +207,53 @@ const resolveExposure = Effect.fnUntraced(function* (options: { return DEFAULT_COMPUTE_EXPOSURE; }); +/** + */ +const resolveSecretsScope = Effect.fnUntraced(function* (options: { + readonly explicit: Option.Option; + /** Whether there is a terminal to ask on — see `canPromptFor`. */ + readonly canPrompt: boolean; +}) { + if (Option.isSome(options.explicit)) { + return options.explicit.value; + } + + if (options.canPrompt) { + const output = yield* Output; + const selected = yield* output.promptSelect( + "Which secrets should be available for this compute?", + defaultFirst( + [...COMPUTE_SECRETS_SCOPE_ENUM], + DEFAULT_COMPUTE_SECRETS_SCOPE as ComputeSecretsScopeEnum, + ).map((scope) => ({ + value: scope, + label: scope, + hint: COMPUTE_SECRETS_SCOPE_DESCRIPTIONS[scope], + })), + ); + + let selectedSecretsScope: string | string[] = selected; + + if ((selected as ComputeSecretsScopeEnum) === "custom") { + const customSecretsNames = yield* output.promptText("Comma-separated list of secret names:", { + validate: (value) => { + const customSecretsScope = parseSecretsScopeCustom(value); + + return customSecretsScope.length > 0 + ? undefined + : `Enter at least one secret name, separated by ","`; + }, + }); + + selectedSecretsScope = parseSecretsScopeCustom(customSecretsNames); + } + + return parseComputeSecretsScope(selectedSecretsScope) ?? DEFAULT_COMPUTE_SECRETS_SCOPE; + } + + return DEFAULT_COMPUTE_SECRETS_SCOPE; +}); + /** * The instance count to record, and whether to record it at all. * @@ -276,6 +331,12 @@ export const computeNew = Effect.fn("compute.new")(function* (flags: ComputeNewF const runtime = yield* resolveRuntime({ explicit: flags.runtime, canPrompt }); const size = yield* resolveSize({ explicit: flags.size, canPrompt }); const exposure = yield* resolveExposure({ explicit: flags.exposure, canPrompt }); + + const secretsScope = yield* resolveSecretsScope({ + explicit: flags.secretsScope.pipe(Option.orElse(() => flags.secretsScopeCustom)), + canPrompt, + }); + const instances = recordedInstances(flags.instances); // Recorded in `config.toml` rather than applied at push time; see ./SIDE_EFFECTS.md. const exclude = COMPUTE_RUNTIME_EXCLUSIONS[runtime]; @@ -335,6 +396,7 @@ export const computeNew = Effect.fn("compute.new")(function* (flags: ComputeNewF runtime, size, exposure, + secrets_scope: secretsScope, ...(instances === undefined ? {} : { instances }), ...(source === undefined ? {} : { source }), ...(exclude.length === 0 ? {} : { exclude }), @@ -348,6 +410,7 @@ export const computeNew = Effect.fn("compute.new")(function* (flags: ComputeNewF "compute.runtime": runtime, "compute.size": size, "compute.exposure": exposure, + "compute.secrets_scope": secretsScope, "compute.starter_file_count": starters.length, }); const destinationExisted = yield* fs.exists(destination); @@ -384,6 +447,7 @@ export const computeNew = Effect.fn("compute.new")(function* (flags: ComputeNewF size, vcpu: vcpuForSize(size), exposure, + secrets_scope: secretsScope, // The count a deploy will use, whether or not it was written down — a // payload that omitted it for the default would read as "unknown" rather // than "one". @@ -415,6 +479,7 @@ export const computeNew = Effect.fn("compute.new")(function* (flags: ComputeNewF ["Runtime", runtime], ["Size", `${size} (${vcpuForSize(size)} vCPU)`], ["Access", exposure], + ["Secrets Scope", formatSecretsScope(secretsScope)], // `declared`, the way `compute status` labels the same number: nothing // is running yet, so a bare count would read as a live tally. ["Instances", `${instances ?? DEFAULT_COMPUTE_INSTANCES} declared`], diff --git a/apps/cli/src/commands/experimental/compute/new/new.integration.test.ts b/apps/cli/src/commands/experimental/compute/new/new.integration.test.ts index e7a89aba1f..5366a8e0bf 100644 --- a/apps/cli/src/commands/experimental/compute/new/new.integration.test.ts +++ b/apps/cli/src/commands/experimental/compute/new/new.integration.test.ts @@ -51,6 +51,8 @@ function flags(overrides: Partial = {}): ComputeNewFlags { exposure: Option.none(), instances: Option.none(), source: Option.none(), + secretsScope: Option.none(), + secretsScopeCustom: Option.none(), ...overrides, }; } @@ -93,7 +95,7 @@ describe("compute new", () => { const computeDir = path.join(repo.dir, "supabase", "compute", "api"); expect(yield* fs.exists(path.join(computeDir, "index.mjs"))).toBe(true); expect(yield* repo.config).toBe( - `${CONFIG_WITH_COMMENTS}\n[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\n${excludeLine( + `${CONFIG_WITH_COMMENTS}\n[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\nsecrets_scope = "all"\n${excludeLine( "node", )}`, ); @@ -200,7 +202,7 @@ describe("compute new", () => { }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); - it.effect("prompts for runtime, size and exposure when none is given", () => + it.effect("prompts for runtime, size, exposure and secrets scope when none is given", () => Effect.gen(function* () { const path = yield* Path.Path; const fs = yield* FileSystem.FileSystem; @@ -217,6 +219,7 @@ describe("compute new", () => { "Which runtime should this compute use?", "Which instance size should this compute use?", "Should this compute be reachable from the internet?", + "Which secrets should be available for this compute?", ]); expect(yield* repo.config).toContain('runtime = "node"'); expect(yield* repo.config).toContain('size = "4gb"'); @@ -340,6 +343,48 @@ describe("compute new", () => { }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); + // Written even when it is the default, the same way `runtime` and `size + it.effect("records the default secrets scope when nothing names one", () => + Effect.gen(function* () { + const repo = yield* project(); + const { layer } = setupCompute({ workdir: repo.dir, format: "json" }); + + return yield* Effect.gen(function* () { + yield* computeNew(flags({ name: Option.some("api") })); + + expect(yield* repo.config).toContain('secrets_scope = "all"'); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("records a secrets scope that differs from the default", () => + Effect.gen(function* () { + const repo = yield* project(); + const { layer } = setupCompute({ workdir: repo.dir }); + + return yield* Effect.gen(function* () { + yield* computeNew(flags({ secretsScope: Option.some("supabase") })); + + expect(yield* repo.config).toContain('secrets_scope = "supabase"'); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("records custom secrets scope as array", () => + Effect.gen(function* () { + const repo = yield* project(); + const { layer } = setupCompute({ workdir: repo.dir }); + + return yield* Effect.gen(function* () { + yield* computeNew( + flags({ secretsScopeCustom: Option.some(["STRIPE_KEY", "ANTHROPIC_KEY"]) }), + ); + + expect(yield* repo.config).toContain('secrets_scope = ["STRIPE_KEY", "ANTHROPIC_KEY"]'); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + // Written into config.toml rather than applied invisibly at push time, so the list is // visible and editable and `push` needs no built-in defaults of its own. describe("the chosen runtime's default exclude patterns", () => { @@ -409,6 +454,7 @@ describe("compute new", () => { expect(yield* repo.config).toContain('runtime = "deno"'); expect(yield* repo.config).toContain('size = "2gb"'); expect(yield* repo.config).toContain('exposure = "public"'); + expect(yield* repo.config).toContain('secrets_scope = "all"'); }).pipe(Effect.provide(layer)); }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); @@ -442,6 +488,7 @@ describe("compute new", () => { runtime: Option.some("deno"), size: Option.some("4gb"), exposure: Option.some("public"), + secretsScope: Option.some("all"), }), ); const recorded = yield* repo.config; @@ -604,7 +651,7 @@ describe("compute new", () => { const computeDir = path.join(created.dir, "supabase", "compute", "api"); expect(yield* fs.exists(path.join(computeDir, "index.mjs"))).toBe(true); expect(yield* fs.readFileString(path.join(created.dir, "supabase", "config.toml"))).toBe( - `[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\n${excludeLine("node")}`, + `[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\nsecrets_scope = "all"\n${excludeLine("node")}`, ); // An EXPLICIT --workdir has no cwd-relative reading, so the success // message names the absolute path rather than a project-root-relative one. @@ -713,6 +760,7 @@ describe("compute new", () => { size: "2gb", vcpu: 1, exposure: "public", + secrets_scope: "all", instances: 1, }); }).pipe(Effect.provide(layer)); @@ -722,7 +770,7 @@ describe("compute new", () => { // The count and the exposure are recorded sparsely — `instances` is left out // of config.toml at the default — so the payload is the only place a caller // can read what this scaffold will actually deploy as. - it.effect("reports the chosen exposure and count under -o json", () => + it.effect("reports the chosen exposure, secrets scope and count under -o json", () => Effect.gen(function* () { const repo = yield* project(); const { layer, out } = setupCompute({ workdir: repo.dir, outputFlag: "json" }); @@ -732,6 +780,7 @@ describe("compute new", () => { flags({ runtime: Option.some("node"), exposure: Option.some("private"), + secretsScopeCustom: Option.some(["STRIPE_KEY", "ANTHROPIC_KEY"]), instances: Option.some(3), }), ); @@ -740,13 +789,14 @@ describe("compute new", () => { yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Unknown))(out.stdoutText), ).toMatchObject({ exposure: "private", + secrets_scope: ["STRIPE_KEY", "ANTHROPIC_KEY"], instances: 3, }); }).pipe(Effect.provide(layer)); }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); - it.effect("shows the exposure and declared count in the details block", () => + it.effect("shows the exposure, secrets scope and declared count in the details block", () => Effect.gen(function* () { const repo = yield* project(); const { layer, out } = setupCompute({ workdir: repo.dir }); @@ -756,6 +806,7 @@ describe("compute new", () => { flags({ runtime: Option.some("node"), exposure: Option.some("private"), + secretsScope: Option.some("none"), instances: Option.some(3), }), ); @@ -763,6 +814,11 @@ describe("compute new", () => { // `Access`, the way `compute status` and `push` label the same field. expect(out.stdoutText).toContain("Access"); expect(out.stdoutText).toContain("private"); + + // `Secrets Scope`, the way `compute status` and `push` label the same field. + expect(out.stdoutText).toContain("Secrets Scope"); + expect(out.stdoutText).toContain("none"); + // `declared`, because nothing is running yet — a bare count would read as // a live tally. expect(out.stdoutText).toContain("3 declared"); @@ -975,7 +1031,7 @@ describe("compute new", () => { // The workdir got both the entry and the scaffold it points at. expect(yield* fs.readFileString(path.join(workdir, "supabase", "config.toml"))).toBe( - `[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\n${excludeLine("node")}`, + `[compute.api]\nruntime = "node"\nsize = "2gb"\nexposure = "public"\nsecrets_scope = "all"\n${excludeLine("node")}`, ); expect( yield* fs.exists(path.join(workdir, "supabase", "compute", "api", "index.mjs")), @@ -1108,11 +1164,14 @@ describe("compute new", () => { exposure: Option.none(), instances: Option.none(), source: Option.none(), + secretsScope: Option.none(), + secretsScopeCustom: Option.none(), }); expect(yield* repo.config).toContain(`runtime = "deno"`); expect(yield* repo.config).toContain(`size = "2gb"`); expect(yield* repo.config).toContain(`exposure = "public"`); + expect(yield* repo.config).toContain(`secrets_scope = "all"`); }).pipe(Effect.provide(layer)); }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); diff --git a/apps/cli/src/commands/experimental/compute/push/push.command.ts b/apps/cli/src/commands/experimental/compute/push/push.command.ts index ab1096b9e0..bdb2640610 100644 --- a/apps/cli/src/commands/experimental/compute/push/push.command.ts +++ b/apps/cli/src/commands/experimental/compute/push/push.command.ts @@ -1,4 +1,4 @@ -import { Argument, Command, Flag } from "effect/cli"; +import { Argument, CliError, Command, Flag } from "effect/cli"; import type * as CliCommand from "effect/cli/Command"; import { withPermissions } from "../../../../command-internal/command-permissions/command-permissions.annotation.ts"; import { @@ -12,13 +12,18 @@ import { computeRead } from "../../../../shared/compute/compute-api.ts"; import { withCliConfigFlags } from "../../../../config/cli-config-flags.ts"; import { cliConfigValuesLayer } from "../../../../config/cli-config-values.layer.ts"; import { withJsonErrorHandling } from "../../../../shared/output/json-error-handling.ts"; -import { COMPUTE_EXPOSURES } from "../../../../shared/compute/compute-runtimes.ts"; +import { + COMPUTE_EXPOSURES, + COMPUTE_SECRETS_SCOPE, + parseSecretsScopeCustom, +} from "../../../../shared/compute/compute-runtimes.ts"; import { managementApiRuntimeLayer } from "../../../../command-internal/management-api-runtime.layer.ts"; import { withCommandTelemetry } from "../../../../telemetry/command-telemetry.ts"; import { computePush } from "./push.handler.ts"; import { withTargetPolicy } from "../../../../command-internal/target/target-policy.ts"; import { branchResolution } from "../../../../command-internal/target/branch-resolution.ts"; import { projectTargetFlags } from "../../../../command-internal/target/target-flags.ts"; +import { Effect, Option } from "effect"; const config = { names: Argument.String("name").pipe( @@ -48,6 +53,24 @@ const config = { ), Flag.optional, ), + secretsScope: Flag.Literals("secrets-scope", COMPUTE_SECRETS_SCOPE).pipe( + Flag.withDescription( + "Controls whether secrets are available, overriding `secrets_scope` in the project config file for this deploy. Falls back to the recorded value, then all.", + ), + Flag.optional, + ), + secretsScopeCustom: Flag.String("secrets-scope:custom").pipe( + Flag.map(parseSecretsScopeCustom), + Flag.withMetavar("SECRET_NAMES"), + Flag.withDescription( + "Controls whether secrets are available, overriding `secrets_scope` with a comma separated list of allowed secret names. Falls back to the recorded value, then all.", + ), + Flag.filter( + (secretNames) => secretNames != undefined && secretNames.length > 0, + () => "Must contain at least one secret name.", + ), + Flag.optional, + ), noWait: Flag.Boolean("no-wait").pipe( // The deploy POST returns once the platform accepts the spec and context; the // server-side build that follows can run for minutes. Waiting stays the @@ -98,7 +121,7 @@ export const computePushCommand = Command.make("push", config).pipe( { operationId: "v2-create-compute-instance-upload", kind: "required" }, { operationId: "v2-deploy-a-compute-instance", kind: "required" }, ], - noApiEffectFlags: ["instances", "exposure"], + noApiEffectFlags: ["instances", "exposure", "secrets-scope", "secrets-scope:custom"], }, withContext( withCondition(computeRead, { flag: "no-wait", is: false }), @@ -116,4 +139,13 @@ export const computePushCommand = Command.make("push", config).pipe( Command.provide(cliConfigValuesLayer), withCliConfigFlags(config), withTargetPolicy({ group: "hosted", consent: "no" }), + Command.validate(({ secretsScope, secretsScopeCustom }) => + Option.isSome(secretsScope) && Option.isSome(secretsScopeCustom) + ? Effect.fail( + new CliError.ValidationError({ + message: "--secrets-scope and --secrets-scope:custom are mutually exclusive", + }), + ) + : Effect.void, + ), ); diff --git a/apps/cli/src/commands/experimental/compute/push/push.handler.ts b/apps/cli/src/commands/experimental/compute/push/push.handler.ts index a9caeb6351..fff6ab0fa2 100644 --- a/apps/cli/src/commands/experimental/compute/push/push.handler.ts +++ b/apps/cli/src/commands/experimental/compute/push/push.handler.ts @@ -34,12 +34,18 @@ import { COMPUTE_RUNTIMES, COMPUTE_SIZES, type ComputeExposure, + COMPUTE_SECRETS_SCOPE, + parseComputeSecretsScope, + DEFAULT_COMPUTE_SECRETS_SCOPE, + formatSecretsScope, + type ComputeSecretsScope, } from "../../../../shared/compute/compute-runtimes.ts"; import { computeUrl } from "../../../../shared/compute/compute-url.ts"; import { awaitComputeBuild, createComputeUpload, deployCompute, + parseComputeSecretsScopeToAPIFormat, uploadBuildContext, type ComputeDeploySpec, } from "../../../../shared/compute/compute-api.ts"; @@ -51,6 +57,7 @@ import { ComputeBuildFailedError, ComputeSourceMissingError, MissingComputeExposureError, + UnknownComputeSecretsScopeError, } from "../../../../shared/compute/compute.errors.ts"; import { requireHostedMutationConsent } from "../../../../command-internal/hosted-consent/hosted-consent.ts"; import { resolveProjectTarget } from "../../../../command-internal/target/resolve-project-target.ts"; @@ -195,6 +202,59 @@ const resolveExposure = Effect.fnUntraced(function* (options: { return recorded; }); +const resolveSecretsScope = Effect.fnUntraced(function* (options: { + readonly config: ConfigFileRef; + readonly name: string; + readonly recorded: string | readonly string[] | undefined; + readonly configured: boolean; + readonly override: Option.Option; +}) { + if (Option.isSome(options.override)) { + const chosen = options.override.value; + const withoutTheFlag = + options.recorded === undefined + ? DEFAULT_COMPUTE_SECRETS_SCOPE + : parseComputeSecretsScope(options.recorded as string | string[]); + + const isCustom = Array.isArray(chosen); + const isChosenEquals = + isCustom && Array.isArray(withoutTheFlag) + ? withoutTheFlag.length === chosen.length && chosen.every((v) => withoutTheFlag.includes(v)) + : withoutTheFlag === chosen; + + if (!options.configured || !isChosenEquals) { + const flagName = `--secrets-scope${isCustom ? ":custom" : ""}`; + const output = yield* Output; + + const applyFormat = (v: string | string[] | readonly string[]) => + Array.isArray(v) ? `[${formatSecretsScope(v.map((i) => `"${i}"`))}]` : `"${v}"`; + + const message = options.configured + ? `${flagName} ${chosen} applies to this deploy only: ${options.config.path} ${ + options.recorded === undefined + ? `records no secrets_scope for ${options.name}` + : `records secrets_scope = ${applyFormat(options.recorded)}` + }, so the next bare push will not use ${chosen}. Set ${configSetting(options.config.format, `compute.${options.name}`, "secrets_scope", applyFormat(chosen))} in ${options.config.path}.\n` + : `${flagName} ${chosen} is required for an unconfigured source directory. Record it under ${settingRef(options.config, options.name, "secrets_scope")} for future pushes.\n`; + yield* output.raw(message, "stderr"); + } + return chosen; + } + + if (options.recorded === undefined) { + return DEFAULT_COMPUTE_SECRETS_SCOPE; + } + const recorded = parseComputeSecretsScope(options.recorded as string | string[]); + if (recorded === undefined) { + return yield* new UnknownComputeSecretsScopeError({ + detail: `${options.config.path} records an unknown secrets scope "${options.recorded}" for "${options.name}".`, + suggestion: `Set ${settingRef(options.config, options.name, "secrets_scope")} to one of: ${COMPUTE_SECRETS_SCOPE.join(", ")}.`, + }); + } + + return recorded; +}); + /** * What to do about a compute whose source directory is not there at all. * @@ -240,6 +300,7 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { readonly refSuffix: string; readonly instances: Option.Option; readonly exposure: Option.Option; + readonly secretsScope: Option.Option; /** `--no-wait`: return once the deploy is accepted instead of blocking on the build. */ readonly noWait: boolean; readonly pollSchedule?: Schedule.Schedule; @@ -331,6 +392,14 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { override: input.exposure, }); + const secretsScope = yield* resolveSecretsScope({ + config, + name, + recorded: compute.entry?.secrets_scope, + configured: compute.entry !== undefined, + override: input.secretsScope, + }); + // Same reason, and the same place: a pattern the CLI cannot read is a config mistake, and // finding it out mid-walk would mean reporting it after the packaging step announced itself. const exclude = yield* compileComputeExclude({ name, patterns: compute.entry?.exclude }); @@ -340,6 +409,7 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { "compute.size": size, "compute.exposure": exposure, "compute.instances": instances, + "compute.secrets_scope": secretsScope, }); let contextUploadId: string; @@ -400,6 +470,7 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { ...(runtime === "dockerfile" ? {} : { runtime }), size: apiSizeFor(size), exposure, + secrets_scope: parseComputeSecretsScopeToAPIFormat(secretsScope), instances, }; @@ -462,6 +533,11 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { // one. Only reachable under `--no-wait` — the default polls until it settles. const imageVersion = settled.buildState === "building" ? undefined : settled.imageVersion; + const settledSecretsScope = + typeof settled.spec.secrets_scope === "string" + ? (settled.spec.secrets_scope as string) + : settled.spec.secrets_scope?.map(({ secret_name }) => secret_name); + // Suppressed when `-o` is in play: the payload owns stdout, and these lines // would land in the middle of it. if (output.format === "text" && !input.machineOutput) { @@ -482,6 +558,7 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { // empty-valued row. ["Image", imageVersion ?? ""], ["Access", settled.spec.exposure], + ["Secrets Scope", formatSecretsScope(settledSecretsScope ?? "")], ["URL", url ?? ""], ]), ); @@ -502,6 +579,7 @@ const deployOneCompute = Effect.fn("compute.push.deployOne")(function* (input: { runtime, size: settled.spec.size, exposure: settled.spec.exposure, + secrets_scope: settledSecretsScope, instances: settled.spec.instances, // Omitted rather than present-and-undefined: `-o toml` hands this to // smol-toml, which can't represent undefined and would throw after the @@ -629,6 +707,7 @@ export const computePush = Effect.fn("compute.push")(function* ( "stderr", ); } + const compute = yield* deployOneCompute({ project, name, @@ -636,6 +715,7 @@ export const computePush = Effect.fn("compute.push")(function* ( refSuffix, instances: flags.instances, exposure: flags.exposure, + secretsScope: flags.secretsScope.pipe(Option.orElse(() => flags.secretsScopeCustom)), noWait: flags.noWait, machineOutput, ...(options.pollSchedule === undefined ? {} : { pollSchedule: options.pollSchedule }), diff --git a/apps/cli/src/commands/experimental/compute/push/push.integration.test.ts b/apps/cli/src/commands/experimental/compute/push/push.integration.test.ts index 413a2b2d62..8a72f6319c 100644 --- a/apps/cli/src/commands/experimental/compute/push/push.integration.test.ts +++ b/apps/cli/src/commands/experimental/compute/push/push.integration.test.ts @@ -33,6 +33,7 @@ import { ComputeUploadFailedError, InvalidComputeExcludeError, MissingComputeExposureError, + UnknownComputeSecretsScopeError, } from "../../../../shared/compute/compute.errors.ts"; import { computePush } from "./push.handler.ts"; import { computePushCommand } from "./push.command.ts"; @@ -62,6 +63,10 @@ const deployRequest = Schema.Struct({ runtime: Schema.optionalKey(Schema.String), size: Schema.String, exposure: Schema.String, + secrets_scope: Schema.Union([ + Schema.String, + Schema.Array(Schema.Struct({ secret_name: Schema.String })), + ]), instances: Schema.Finite, }), context_upload_id: Schema.String, @@ -79,6 +84,8 @@ function flags(overrides: Partial = {}): ComputePushFlags { noWait: false, remote: Option.none(), projectRef: Option.none(), + secretsScope: Option.none(), + secretsScopeCustom: Option.none(), ...overrides, }; } @@ -161,6 +168,7 @@ describe("compute push", () => { runtime: "node", size: "2gb-1vcpu", exposure: "public", + secrets_scope: "all", instances: 1, }, context_upload_id: UPLOAD_ID, @@ -345,6 +353,7 @@ describe("compute push", () => { expect(attributes.spec).toEqual({ size: "2gb-1vcpu", exposure: "public", + secrets_scope: "all", instances: 1, }); expect(attributes.context_upload_id).toBe(UPLOAD_ID); @@ -374,6 +383,9 @@ describe("compute push", () => { expect((yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.exposure).toBe( "private", ); + expect((yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.secrets_scope).toBe( + "all", + ); }).pipe(Effect.provide(layer)); }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); @@ -504,6 +516,7 @@ describe("compute push", () => { runtime: "node", size: "4gb-2vcpu", exposure: "public", + secrets_scope: "all", instances: 3, }); }).pipe(Effect.provide(layer)); @@ -768,6 +781,98 @@ describe("compute push", () => { }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), ); + it.effect("reads the compute secrets_scope defined on config", () => + Effect.gen(function* () { + const repo = yield* project({ + "supabase/config.toml": `project_id = "demo"\n\n[compute.api]\nruntime = "node"\nsecrets_scope = "none"`, + }); + const { layer, http } = setupPush({ workdir: repo.dir, routes: routes() }); + + return yield* Effect.gen(function* () { + yield* push(); + + const deploy = http.requests.find((request) => request.url.endsWith("/deploy")); + expect((yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.secrets_scope).toBe( + "none", + ); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("reads the compute secrets_scope defined on config as array", () => + Effect.gen(function* () { + const repo = yield* project({ + "supabase/config.toml": `project_id = "demo"\n\n[compute.api]\nruntime = "node"\nsecrets_scope = ["STRIPE_KEY", "ANTHROPIC_KEY"]`, + }); + const { layer, http } = setupPush({ workdir: repo.dir, routes: routes() }); + + return yield* Effect.gen(function* () { + yield* push(); + + const deploy = http.requests.find((request) => request.url.endsWith("/deploy")); + expect( + (yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.secrets_scope, + ).toStrictEqual([{ secret_name: "STRIPE_KEY" }, { secret_name: "ANTHROPIC_KEY" }]); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("lets --secrets-scope overrided the defined secrets_scope", () => + Effect.gen(function* () { + const repo = yield* project({ + "supabase/config.toml": `project_id = "demo"\n\n[compute.api]\nruntime = "node"\nsecrets_scope = "all"`, + }); + const { layer, http } = setupPush({ workdir: repo.dir, routes: routes() }); + + return yield* Effect.gen(function* () { + yield* push({ secretsScope: Option.some("supabase") }); + + const deploy = http.requests.find((request) => request.url.endsWith("/deploy")); + expect((yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.secrets_scope).toBe( + "supabase", + ); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("lets --secrets-scope overrided the defined secrets_scope as array", () => + Effect.gen(function* () { + const repo = yield* project({ + "supabase/config.toml": `project_id = "demo"\n\n[compute.api]\nruntime = "node"\nsecrets_scope = "all"`, + }); + const { layer, http } = setupPush({ workdir: repo.dir, routes: routes() }); + + return yield* Effect.gen(function* () { + yield* push({ secretsScopeCustom: Option.some(["STRIPE_KEY", "ANTHROPIC_KEY"]) }); + + const deploy = http.requests.find((request) => request.url.endsWith("/deploy")); + expect( + (yield* decodeDeploy(deploy?.body ?? "{}")).data.attributes.spec.secrets_scope, + ).toStrictEqual([{ secret_name: "STRIPE_KEY" }, { secret_name: "ANTHROPIC_KEY" }]); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + + it.effect("refuses an invalid secrets_scope defined on config", () => + Effect.gen(function* () { + const repo = yield* project({ + "supabase/config.toml": `project_id = "demo"\n\n[compute.api]\nruntime = "node"\nsecrets_scope = "meow"`, + }); + const { layer, http } = setupPush({ workdir: repo.dir, routes: routes() }); + + return yield* Effect.gen(function* () { + const error = yield* push().pipe(Effect.flip); + + expect(error).toBeInstanceOf(UnknownComputeSecretsScopeError); + expect(error).toMatchObject({ + detail: expect.stringContaining("meow"), + suggestion: expect.stringContaining("all, supabase, none"), + }); + expect(http.requests).toHaveLength(0); + }).pipe(Effect.provide(layer)); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer)), + ); + it.effect("polls until the build leaves `building`", () => Effect.gen(function* () { const repo = yield* project(); @@ -1088,6 +1193,7 @@ describe("compute push", () => { runtime: "node", size: "2gb-1vcpu", exposure: "public", + secrets_scope: "all", instances: 3, }); // Every value came from config, so nothing was inferred from the files. diff --git a/apps/cli/src/commands/experimental/stack/install/install.handler.ts b/apps/cli/src/commands/experimental/stack/install/install.handler.ts index 160e091a7f..31ecb2a201 100644 --- a/apps/cli/src/commands/experimental/stack/install/install.handler.ts +++ b/apps/cli/src/commands/experimental/stack/install/install.handler.ts @@ -3,7 +3,10 @@ import type { PreparedRelease } from "@supabase/stack/internal/artifacts"; import { Effect, Path, Ref, Schema } from "effect"; import { FetchHttpClient } from "effect/http"; import { OutputFlag } from "../../../../command-internal/global-flags.ts"; -import { loadStackConfig } from "../../../../command-internal/stack-config.ts"; +import { + loadStackConfig, + stackConfigSuggestion, +} from "../../../../command-internal/stack-config.ts"; import { LockResolutionError, lockedResolution, @@ -103,6 +106,7 @@ export const stackInstall = Effect.fn("experimental.stack.install")(function* ( : new StackCommandInstallError({ reason: Schema.is(LockResolutionError)(error) ? "lock" : "invalid-config", message: error.message, + suggestion: stackConfigSuggestion(error), cause: error, }), ), diff --git a/apps/cli/src/commands/experimental/stack/outdated/outdated.handler.ts b/apps/cli/src/commands/experimental/stack/outdated/outdated.handler.ts index 7bfacc3f3d..b34eded722 100644 --- a/apps/cli/src/commands/experimental/stack/outdated/outdated.handler.ts +++ b/apps/cli/src/commands/experimental/stack/outdated/outdated.handler.ts @@ -1,7 +1,10 @@ import { defaultArtifactSelection } from "@supabase/stack/defaults"; import { Effect, Ref, Schema } from "effect"; import { OutputFlag } from "../../../../command-internal/global-flags.ts"; -import { loadStackConfig } from "../../../../command-internal/stack-config.ts"; +import { + loadStackConfig, + stackConfigSuggestion, +} from "../../../../command-internal/stack-config.ts"; import { LockResolutionError, outdatedServices, @@ -79,6 +82,7 @@ export const stackOutdated = Effect.fn("experimental.stack.outdated")(function* new StackCommandOutdatedError({ reason: Schema.is(LockResolutionError)(error) ? "lock" : "invalid-config", message: error.message, + suggestion: stackConfigSuggestion(error), cause: error, }), ), diff --git a/apps/cli/src/commands/experimental/stack/restart/SIDE_EFFECTS.md b/apps/cli/src/commands/experimental/stack/restart/SIDE_EFFECTS.md index 2710a054af..75c9dd5338 100644 --- a/apps/cli/src/commands/experimental/stack/restart/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/experimental/stack/restart/SIDE_EFFECTS.md @@ -24,7 +24,14 @@ owners. An owner may be launched by restart when none exists. Existing runtime resources are stopped/recreated for composition members only. Artifacts are resolved from `/cache/stack`; missing artifacts may be downloaded. Shared routing/settings may read project config and profiles. -No hosted project API calls or caller-owned data deletion occur. +No hosted project API calls or caller-owned data deletion occur. While the API +port serves TLS on Docker or Podman, the database container then sends the start +check (see `stack start`) with a fresh nonce. A failed check stops the stack's +services and fails with the same `api.tls: unsupported networking on : +...`, `api.tls: containers can't reach the api port on ...` or +`api.tls: the api port on isn't answering this stack's start +check ...` error as `stack start`; if they don't stop, the error says to run +`supabase stack stop` instead. ## Output, exit codes and telemetry diff --git a/apps/cli/src/commands/experimental/stack/stack-config.integration.test.ts b/apps/cli/src/commands/experimental/stack/stack-config.integration.test.ts index 697b22ae7f..23041f1e30 100644 --- a/apps/cli/src/commands/experimental/stack/stack-config.integration.test.ts +++ b/apps/cli/src/commands/experimental/stack/stack-config.integration.test.ts @@ -17,6 +17,8 @@ import { renderCliConfigTemplate } from "../../../shared/init/project-init.templ import { mockCommandSettings } from "../../../../tests/helpers/command-mocks.ts"; import { loadStackConfig } from "../../../command-internal/stack-config.ts"; +import { KONG_LOCAL_TLS_CERT, KONG_LOCAL_TLS_KEY } from "../../start/templates/kong-local-tls.ts"; +import { generateKeyPairSync } from "node:crypto"; import { createStackConfigProject } from "../../../../tests/helpers/stack-config.ts"; import { CommandTelemetryAttributes, @@ -197,6 +199,24 @@ max_rows = 250 }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("hands REST [api] db_pool only when set", () => + Effect.gen(function* () { + const restConfig = (name: string, apiSection: string) => + Effect.gen(function* () { + const config = yield* load(yield* project(`project_id = "${name}"\n${apiSection}`)); + const rest = byService(yield* config.creations(name)).get("rest"); + return rest?.service === "rest" ? rest.config : undefined; + }); + + expect(yield* restConfig("stack-config-pool", "[api]\ndb_pool = 10\n")).toMatchObject({ + dbPool: 10, + }); + const unset = yield* restConfig("stack-config-no-pool", ""); + expect(unset).toMatchObject({ maxRows: 1000 }); + expect(unset).not.toHaveProperty("dbPool"); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("leaves stack-opt-in init listeners automatic except disabled pooler", () => Effect.gen(function* () { const root = yield* project(renderCliConfigTemplate("stack-config-init", false, true)); @@ -323,6 +343,118 @@ content_path = "./supabase/templates/missing.html" }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("serves api.tls with legacy's embedded pair or the configured one, like legacy", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const plain = yield* project(`project_id = "stack-config-tls-off"\n`); + expect(yield* (yield* load(plain)).apiTls).toBeUndefined(); + + const embedded = yield* project(`project_id = "stack-config-tls-embedded" +[api.tls] +enabled = true +`); + expect(yield* (yield* load(embedded)).apiTls).toEqual({ + cert: KONG_LOCAL_TLS_CERT, + key: KONG_LOCAL_TLS_KEY, + }); + + /* Without PostgREST the API port still serves https, on the embedded pair. */ + const apiOff = yield* project(`project_id = "stack-config-tls-api-off" +[api] +enabled = false +[api.tls] +enabled = true +cert_path = "certs/missing.crt" +`); + expect(yield* (yield* load(apiOff)).apiTls).toEqual({ + cert: KONG_LOCAL_TLS_CERT, + key: KONG_LOCAL_TLS_KEY, + }); + + const custom = yield* project(`project_id = "stack-config-tls-custom" +[api.tls] +enabled = true +cert_path = "certs/local.crt" +key_path = "certs/local.key" +`); + const certs = path.join(custom, "supabase", "certs"); + yield* fs.makeDirectory(certs); + yield* fs.writeFileString(path.join(certs, "local.crt"), KONG_LOCAL_TLS_CERT); + yield* fs.writeFileString(path.join(certs, "local.key"), KONG_LOCAL_TLS_KEY); + expect(yield* (yield* load(custom)).apiTls).toEqual({ + cert: KONG_LOCAL_TLS_CERT, + key: KONG_LOCAL_TLS_KEY, + }); + const other = generateKeyPairSync("ec", { namedCurve: "prime256v1" }).privateKey; + for (const key of [other.export({ type: "pkcs8", format: "pem" }).toString(), "not a pem"]) { + yield* fs.writeFileString(path.join(certs, "local.key"), key); + expect((yield* Effect.flip((yield* load(custom)).apiTls)).message).toMatch( + /^Invalid config for api\.tls: failed to load TLS key pair from \S+certs\/local\.crt and \S+certs\/local\.key: /u, + ); + } + /* An empty file still builds a secure context, which then serves no certificate. */ + for (const [cert, key] of [ + ["", KONG_LOCAL_TLS_KEY], + [KONG_LOCAL_TLS_CERT, ""], + ]) { + yield* fs.writeFileString(path.join(certs, "local.crt"), cert ?? ""); + yield* fs.writeFileString(path.join(certs, "local.key"), key ?? ""); + expect((yield* Effect.flip((yield* load(custom)).apiTls)).message).toMatch( + /^Invalid config for api\.tls: failed to load TLS key pair from \S+certs\/local\.crt and \S+certs\/local\.key: /u, + ); + } + + /* A matching pair whose certificate names localhost, and 127.0.0.1 only by CN, not by IP SAN. */ + const stackCerts = path.join( + import.meta.dirname, + "..", + "..", + "..", + "..", + "..", + "..", + "packages", + "stack", + "tests", + "certs", + ); + yield* fs.writeFileString( + path.join(certs, "local.crt"), + yield* fs.readFileString(path.join(stackCerts, "dns-only.crt")), + ); + yield* fs.writeFileString( + path.join(certs, "local.key"), + yield* fs.readFileString(path.join(stackCerts, "localhost.key")), + ); + expect((yield* Effect.flip((yield* load(custom)).apiTls)).message).toMatch( + /^Invalid config for api\.tls: failed to load TLS key pair from \S+certs\/local\.crt and \S+certs\/local\.key: the certificate has no IP subject alternative name for 127\.0\.0\.1 \(for example `mkcert localhost 127\.0\.0\.1`\)$/u, + ); + + const halfPair = yield* project(`project_id = "stack-config-tls-half" +[api.tls] +enabled = true +cert_path = "certs/local.crt" +`); + expect((yield* Effect.flip((yield* load(halfPair)).apiTls)).message).toContain( + "api.tls.key_path", + ); + + const unreadable = yield* project(`project_id = "stack-config-tls-missing" +[api.tls] +enabled = true +cert_path = "certs/missing.crt" +key_path = "certs/missing.key" +`); + /* Only the start applying TLS reads the files; every other command loads and composes. */ + const missingFiles = yield* load(unreadable); + expect(yield* missingFiles.creations("stack-config-tls-missing")).not.toHaveLength(0); + expect((yield* Effect.flip(missingFiles.apiTls)).message).toContain( + "failed to read TLS cert", + ); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("validates enabled Auth third-party providers", () => Effect.gen(function* () { const root = yield* project(`project_id = "stack-config-auth-third-party" @@ -450,6 +582,20 @@ backend = "bigquery" }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("accepts storage analytics and declared vector buckets", () => + Effect.gen(function* () { + const root = yield* project(`project_id = "stack-config-storage-buckets" +[storage.analytics] +enabled = true +[storage.analytics.buckets.my-warehouse] +[storage.vector.buckets.documents-openai] +`); + const services = yield* (yield* load(root)).creations("stack-storage-buckets"); + const storage = byService(services).get("storage"); + expect(storage?.service === "storage" && storage.config.vectorEnabled).toBe(true); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("rejects unsupported database versions before creating recipes", () => Effect.gen(function* () { const root = yield* project(`project_id = "stack-config-db-version" diff --git a/apps/cli/src/commands/experimental/stack/stack-endpoints.format.ts b/apps/cli/src/commands/experimental/stack/stack-endpoints.format.ts index 869d6b8ee1..23ebc9431c 100644 --- a/apps/cli/src/commands/experimental/stack/stack-endpoints.format.ts +++ b/apps/cli/src/commands/experimental/stack/stack-endpoints.format.ts @@ -1,7 +1,7 @@ import type { Observation } from "@supabase/stack/effect"; const endpointUrl = (endpoint: Observation["endpoints"][number]) => - `${endpoint.protocol}://${endpoint.host}:${endpoint.port}`; + `${endpoint.scheme ?? endpoint.protocol}://${endpoint.host}:${endpoint.port}`; export const endpointReports = (observation: Observation | undefined) => Object.fromEntries( diff --git a/apps/cli/src/commands/experimental/stack/start/SIDE_EFFECTS.md b/apps/cli/src/commands/experimental/stack/start/SIDE_EFFECTS.md index 4ff7cb17c8..476c906a08 100644 --- a/apps/cli/src/commands/experimental/stack/start/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/experimental/stack/start/SIDE_EFFECTS.md @@ -8,7 +8,10 @@ It creates or resumes the stack for the project and optional `--stack` name, or For a new stack or a stopped existing stack, the CLI loads the target project's `supabase/config.toml`, supported environment overrides, and project dotenv files. It validates the -supported configuration before creating service definitions. When every member of the existing +supported configuration before creating service definitions. A config that uses a removed key +(for example `inbucket`) fails with exit 1 before any stack is created; the error names the key and +its replacement and carries the suggestion `Update supabase/config.toml, then rerun the command.`, +in text and JSON output. When every member of the existing composition is running and healthy, or armed to wake and not already starting, start reports its current endpoints and returns without reading or applying project configuration. When the database is running and every other member is running with any health, starting, or armed to wake, start @@ -24,6 +27,12 @@ S3 protocol/vector controls are forwarded to their services. Storage receives th keys and region, and uses the gateway's `/storage/v1` prefix to verify S3 signatures and to build resumable upload URLs. `analytics.vector_port` and `SUPABASE_ANALYTICS_VECTOR_PORT` are accepted and ignored: the stack runs no Vector service. +`[storage.analytics]` is accepted, but analytics buckets are hosted-only: the stack configures no +Iceberg catalog on Storage and a local start seeds none. +An `edge_runtime.deno_version` other than 2 while Edge Runtime is enabled, or a non-empty +`analytics.gcp_*` value while Analytics is enabled, fails loading with ` is unsupported by +the experimental stack`. `analytics.backend = "bigquery"` with Analytics enabled and no `gcp_*` +value fails with `analytics.backend must be postgres for the experimental stack`. Encrypted JWT secrets are decrypted before shared credentials are derived. `[edge_runtime.secrets]` names are uppercased, empty or unresolved `env()` values and `SUPABASE_`-prefixed names are dropped, and encrypted values are decrypted before they reach the Functions service. `db.health_timeout` @@ -51,6 +60,52 @@ template mailed and read it there. A changed `content_path` applies after stop a sleeps after 60 s idle unless the stack started with `--eager`, and each wake refetches. A replaced file reaches mail at the next wake, or once Auth's template cache expires. A deleted file mails Auth's cached copy until the next wake, then the built-in template. + +With `[api.tls] enabled`, the API port serves HTTPS with legacy's embedded local pair, or the +`cert_path`/`key_path` pair joined to `supabase/` (ignored, like legacy, with +`[api] enabled = false`), saved in the stack's state at start; no listener or port is added. The +embedded pair's key ships in the CLI, so never add its certificate to a trust store. Only +`stack start` reads those files, and fails before it creates or starts anything on an unreadable one +with `failed to read TLS cert: ` (or `key`), or on a pair that does not parse as a matching +PEM pair, or whose certificate has no IP subject alternative name for `127.0.0.1`, with `Invalid +config for api.tls: failed to load TLS key pair from and : `. Only `stack start` +sets TLS; it, or a command that composes a database-only stack such as `db start`, clears it, and a +recompose that retains members keeps it. Host URLs (`API_URL`, Auth links, Studio's public URL, and +Functions' `SUPABASE_INTERNAL_HOST_URL`, which the Functions banner prefers) use +`https://127.0.0.1:`, and user URL overrides stay as given. Runtime URLs stay +`http://host.supabase.internal:` for containers and `http://127.0.0.1:` on native, so +`SUPABASE_URL`, `SUPABASE_INTERNAL_HOST_PORT` and `pg_net` SQL are unchanged. + +A TLS hello gets HTTPS from any peer. Plain HTTP answers only loopback (`127.0.0.0/8` or `::1`): +processes on this host, any user's, and containers on runtimes that forward their traffic from +loopback. Any other peer, such as a LAN device, a routed VPN or a container arriving from a bridge +address, is closed before any HTTP byte and must use `https://`. A plain request needs a stack host +alias, `localhost` or an IP address with the API port in `Host` (the port may be left out on port +80), or gets 421, WebSocket upgrades included, and `/email` templates answer only plain requests. +Each request forwards its own connection's proto. While the API port serves TLS on Docker or Podman, +every stack start or restart, and every instance start or restart while the database runs, ends with +the database container sending `GET /__api_tls_check` once in plain; it passes only on a 200 read to +its end whose body is `supabase-stack `, a fresh nonce that is never saved and +admits nothing. On macOS, Docker Desktop, colima and Podman machine forward containers from +loopback; on Linux, rootful Docker, rootful Podman and rootless Podman on pasta deliver them from a +bridge or host address, so a TLS start there fails with ``api.tls: unsupported networking on +: containers must reach the api from loopback (the database container's plain request was +closed without a reply); its services stopped: turn off `[api.tls]`, or use a runtime whose +containers reach this host from loopback (on macOS: Docker Desktop, colima or Podman machine), then +start the stack again``. Other runtimes are unmeasured; the check decides. A connection that is +refused or never opens, or a probe the engine can't run, fails with ``api.tls: containers can't +reach the api port on (); its services stopped: let +containers reach the api port, or turn off `[api.tls]`, then start the stack again``, and any other +reply, or none within 5 s, with `api.tls: the api port on isn't answering this +stack's start check (); its services stopped: check what else listens on port +, then start the stack again`; if they don't stop, the error says to run `supabase stack stop` +instead. + +Bucket seeding and stack `storage` commands use the saved certificate, never `config.toml`, so +editing `api.tls` applies at the next start. A saved certificate with a self-signed root is the only +trusted CA; a CA-issued one is verified against Bun's default trust store and `NODE_EXTRA_CA_CERTS`. +Without TLS every listener, URL and output is unchanged. + `db.orioledb_version` (or `SUPABASE_DB_ORIOLEDB_VERSION`) is a `local.services.database.version` request for that OrioleDB build instead of the stock major, resolved like any other version (see "Service versions and the lock"); the two keys must agree when both are set, and `db.major_version` @@ -142,6 +197,9 @@ When Functions is selected, the CLI reads and validates `supabase/functions/.env `start`, skipping reserved `SUPABASE_*` entries with a warning. That file overrides `edge_runtime.secrets`, per-function `.env` files are not read, and `functions..env` provides per-function values from project environment references. Multiline values are supported. +Functions receive `SUPABASE_DB_URL` for the `postgres` role, like legacy `start`. A stack saved +with the earlier `supabase_admin` URL keeps it through `stack restart` and gets the `postgres` one +after stop and start. `--debug` runs the Functions runtime verbose; `status` does not report it as drift. Per-function enabled/JWT policies, entrypoints, import maps and static files are forwarded to the worker bootstrap. Without a configured `import_map`, a function uses its own `deno.json` or `deno.jsonc`; a @@ -345,8 +403,9 @@ reset of database data removes the record. A service on an external database has The first configured startup prepares the database catalog, temporarily runs configured schema-owning services, creates the `supabase_functions` schema, which migrations must not recreate, applies the -database overlay, and runs project migrations and seeds. Membership changes -apply needed catalog and webhook setup without replaying project migrations or seeds. An unchanged +database overlay (`roles.sql`, vault, API grants) as `postgres`, like legacy `start`, and runs project +migrations and seeds. Membership changes apply needed catalog and webhook setup without replaying +the overlay, project migrations or seeds. An unchanged composition reapplies the webhook setting before activation, first creating the `supabase_functions` schema when the database lacks it. diff --git a/apps/cli/src/commands/experimental/stack/start/start-export-pointer.integration.test.ts b/apps/cli/src/commands/experimental/stack/start/start-export-pointer.integration.test.ts index e4aec80e9e..c228500bb4 100644 --- a/apps/cli/src/commands/experimental/stack/start/start-export-pointer.integration.test.ts +++ b/apps/cli/src/commands/experimental/stack/start/start-export-pointer.integration.test.ts @@ -95,6 +95,7 @@ function makeDatabaseStack(sqlPort: number, credentials: StackCredentials): Stac get: () => Effect.succeed(databaseInstance), list: Effect.succeed([databaseInstance]), }, + apiTls: { get: Effect.undefined }, credentials: { get: Effect.succeed(credentials) }, composition: { plan: () => Effect.die("unused"), diff --git a/apps/cli/src/commands/experimental/stack/start/start.handler.ts b/apps/cli/src/commands/experimental/stack/start/start.handler.ts index 5cd28a592a..2431eed60a 100644 --- a/apps/cli/src/commands/experimental/stack/start/start.handler.ts +++ b/apps/cli/src/commands/experimental/stack/start/start.handler.ts @@ -71,6 +71,7 @@ import { CliConfigKeys } from "../../../../config/cli-config-keys.ts"; import type { CliConfigMaterialized } from "../../../../config/cli-config-values.service.ts"; import { loadStackConfig, + stackConfigSuggestion, stackEndpointKey, stackMajorVersionKey, stackUploadsDir, @@ -234,7 +235,9 @@ const loadStartConfig = Effect.fn("experimental.stack.start.loadConfig")( }); const keys = yield* config.keys; const toml = yield* readDbConfig(fs, path, projectRoot); - return { config, keys, toml }; + /* The pair is read and checked here, before a stack or owner exists. */ + const apiTls = yield* config.apiTls; + return { config, keys, toml, apiTls }; }, Effect.mapError( (error) => @@ -243,6 +246,7 @@ const loadStartConfig = Effect.fn("experimental.stack.start.loadConfig")( ? { reason: "lock" as const } : { reason: "invalid-config" as const, configIssue: "project-config" as const }), message: error.message, + suggestion: stackConfigSuggestion(error), cause: error, }), ), @@ -878,7 +882,7 @@ export const stackStart = Effect.fn("experimental.stack.start")(function* (flags message: "A standalone database exists outside the saved stack composition", suggestion: "Destroy the standalone database before starting this stack.", }); - const { config, keys, toml } = yield* startConfig; + const { config, keys, toml, apiTls } = yield* startConfig; // Reuses the creations resolved for a fresh owner's re-plan above instead of reading the // Functions dotenv a second time. A new stack has none yet, and a live owner's were resolved // silently, so both resolve here with warnings. @@ -1018,6 +1022,7 @@ export const stackStart = Effect.fn("experimental.stack.start")(function* (flags .supabase(requested, { keys, eager: flags.eager, + ...(apiTls === undefined ? {} : { apiTls }), ...(reuseIds.length === 0 ? {} : { reuseIds }), }) .pipe( @@ -1103,8 +1108,9 @@ export const stackStart = Effect.fn("experimental.stack.start")(function* (flags databaseServices: catalogDatabaseServices(requested), selection: config.selection, }, - overlay: projectCatalogOverlay(toml, target.projectRoot), - ...(migrations === undefined ? {} : { migrations }), + ...(migrations === undefined + ? {} + : { overlay: projectCatalogOverlay(toml, target.projectRoot), migrations }), }).pipe( Effect.tapError((error) => starting.fail(error.message)), Effect.mapError(stackError), @@ -1133,9 +1139,11 @@ export const stackStart = Effect.fn("experimental.stack.start")(function* (flags Effect.tapError((error) => starting.fail(error.message)), Effect.mapError(stackError), ); + const apiTls = yield* stack.apiTls.get.pipe(Effect.mapError(stackError)); const credentials = yield* stackStorageCredentialsFor( storage, stackCredentials.serviceRoleKey, + apiTls?.cert, ).pipe(Effect.mapError(stackError)); yield* seedBucketsRun({ projectRef: "", diff --git a/apps/cli/src/commands/experimental/stack/start/start.integration.test.ts b/apps/cli/src/commands/experimental/stack/start/start.integration.test.ts index c45503a16f..2e176edd57 100644 --- a/apps/cli/src/commands/experimental/stack/start/start.integration.test.ts +++ b/apps/cli/src/commands/experimental/stack/start/start.integration.test.ts @@ -42,6 +42,7 @@ import { writeLock, } from "@supabase/stack/effect"; import { planSupabaseComposition } from "@supabase/stack/internal/composition"; +import { normalizeCliError } from "../../../../shared/output/normalize-error.ts"; import { mockCommandSettings, mockTelemetryStateTracked, @@ -94,6 +95,10 @@ import { StackTargetResolver, } from "../../../../command-internal/stack-target.ts"; import { stackStart } from "./start.handler.ts"; +import { + KONG_LOCAL_TLS_CERT, + KONG_LOCAL_TLS_KEY, +} from "../../../start/templates/kong-local-tls.ts"; import { StackCommandStartError } from "./start.errors.ts"; import { cliConfigValuesTestLayer } from "../../../../../tests/helpers/config-values-layer.ts"; @@ -338,6 +343,7 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { let hostDestroyed = 0; let composed = 0; let catalogApplied = 0; + const catalogOverlays: Array = []; let compositionStarts = 0; let lifecycle: "stopped" | "running" = "stopped"; let activations = new Map(); @@ -347,6 +353,7 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { /** The endpoint changes a simulated owner startup re-planned, until the next `applyStartupReplan`. */ let pendingStartupChanges: ReadonlyArray = []; let savedCredentials = credentialsFor(undefined, undefined); + let composedApiTls: { readonly cert: string; readonly key: string } | undefined; const memberView = (id: string): MemberView => { const status = memberStatuses.get(id); const memberLifecycle = status?.lifecycle ?? lifecycle; @@ -376,6 +383,7 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { return Effect.succeed(members); }, }, + apiTls: { get: Effect.undefined }, credentials: { get: Effect.sync(() => savedCredentials), }, @@ -387,6 +395,7 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { supabase: (creations: ReadonlyArray, options) => Effect.sync(() => { composed += 1; + composedApiTls = options?.apiTls; savedCredentials = credentialsFor( creations.find((creation) => creation.service === "database"), options, @@ -477,6 +486,10 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { get composed() { return composed; }, + /** The API TLS the last compose was given. */ + get composedApiTls() { + return composedApiTls; + }, /** Whether a detached owner is still up, the way a live stack's would be between calls. */ get hostRunning() { return lifecycle === "running"; @@ -487,8 +500,12 @@ const fakeStack = (compositionStart?: Stack["composition"]["start"]) => { get compositionStarts() { return compositionStarts; }, - applyCatalog() { + get catalogOverlays() { + return catalogOverlays; + }, + applyCatalog(overlay: boolean) { catalogApplied += 1; + catalogOverlays.push(overlay); }, get savedCredentials() { return savedCredentials; @@ -624,7 +641,7 @@ const layers = ( ciUnsetLayer, Layer.succeed(CliArgs, { args: ["stack", "start"] }), Layer.succeed(StackCatalogSetup, { - apply: () => Effect.sync(() => fixture.applyCatalog()), + apply: (input) => Effect.sync(() => fixture.applyCatalog(input.overlay !== undefined)), }), Layer.succeed(DbConnection, { connect: () => Effect.scoped(Effect.succeed(session)) }), Layer.succeed(YesFlag, false), @@ -772,6 +789,29 @@ describe("experimental stack start", () => { }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("fails a removed config key with its replacement as the suggestion", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "stack-start-removed-key-" }); + yield* fs.makeDirectory(`${root}/supabase`, { recursive: true }); + yield* fs.writeFileString( + `${root}/supabase/config.toml`, + 'project_id = "removed-key"\n\n[inbucket]\nenabled = true\n', + ); + const fixture = fakeStack(); + const error = yield* stackStart(flags()).pipe( + Effect.provide(layers(root, fixture)), + Effect.flip, + ); + expect(normalizeCliError(error)).toMatchObject({ + code: "ExperimentalStackStartError", + message: "inbucket in supabase/config.toml is no longer supported. Use local_smtp instead.", + suggestion: "Update supabase/config.toml, then rerun the command.", + }); + expect(fixture.composed).toBe(0); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("refuses an unreadable Auth email template before creating a stack", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -794,6 +834,79 @@ describe("experimental stack start", () => { }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect( + "rejects an api.tls pair that does not load, or has no IP SAN for 127.0.0.1, before creating a stack", + () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const certs = `${import.meta.dirname}/../../../../../../../packages/stack/tests/certs`; + const pairs = [ + { cert: "not a pem", key: "not a pem", reason: "" }, + { + cert: yield* fs.readFileString(`${certs}/dns-only.crt`), + key: yield* fs.readFileString(`${certs}/localhost.key`), + reason: "the certificate has no IP subject alternative name for 127.0.0.1", + }, + ]; + for (const { cert, key, reason } of pairs) { + const root = yield* fs.makeTempDirectoryScoped({ prefix: "stack-start-tls-pair-" }); + yield* fs.makeDirectory(`${root}/supabase/certs`, { recursive: true }); + yield* fs.writeFileString( + `${root}/supabase/config.toml`, + '[api.tls]\nenabled = true\ncert_path = "certs/api.crt"\nkey_path = "certs/api.key"\n', + ); + yield* fs.writeFileString(`${root}/supabase/certs/api.crt`, cert); + yield* fs.writeFileString(`${root}/supabase/certs/api.key`, key); + let created = false; + const fixture = fakeStack(); + const base = layers(root, fixture, mockOutput(), false); + const api = Layer.succeed(StackApi, { + create: () => + Effect.sync(() => { + created = true; + return fixture.stack; + }), + open: () => Effect.succeed(fixture.stack), + discover: () => Effect.succeed([]), + find: () => Effect.die("identity not used"), + findDeleted: () => Effect.die("identity not used"), + }); + const result = yield* stackStart(flags()).pipe( + Effect.flip, + Effect.provide(Layer.merge(base, api)), + ); + expect(result).toMatchObject({ + reason: "invalid-config", + message: expect.stringContaining( + "Invalid config for api.tls: failed to load TLS key pair", + ), + }); + expect(result.message).toContain(reason); + expect(created).toBe(false); + } + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + + it.effect("composes the stack with the api.tls pair only while api.tls is enabled", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "stack-start-tls-on-" }); + yield* fs.makeDirectory(`${root}/supabase`, { recursive: true }); + const start = (config: string) => + Effect.gen(function* () { + yield* fs.writeFileString(`${root}/supabase/config.toml`, config); + const fixture = fakeStack(); + yield* stackStart(flags()).pipe(Effect.provide(layers(root, fixture))); + return fixture.composedApiTls; + }); + expect(yield* start('project_id = "start-tls"\n[api.tls]\nenabled = true\n')).toEqual({ + cert: KONG_LOCAL_TLS_CERT, + key: KONG_LOCAL_TLS_KEY, + }); + expect(yield* start('project_id = "start-tls"\n')).toBeUndefined(); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("rejects malformed configuration before creating a stack", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -1320,6 +1433,23 @@ describe("experimental stack start", () => { }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("applies the project overlay once when a later start adds a service", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "stack-start-overlay-once-" }); + yield* fs.makeDirectory(`${root}/supabase`, { recursive: true }); + yield* fs.writeFileString(`${root}/supabase/config.toml`, 'project_id = "overlay-once"\n'); + const fixture = fakeStack(); + + yield* stackStart(flags(["storage"])).pipe(Effect.provide(layers(root, fixture))); + yield* fixture.stack.composition.stop; + yield* stackStart(flags()).pipe(Effect.provide(layers(root, fixture))); + + expect(fixture.members.some(({ service }) => service === "storage")).toBe(true); + expect(fixture.catalogOverlays).toEqual([true, false]); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("creates the supabase_functions schema once when restarting a stack without it", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; diff --git a/apps/cli/src/commands/experimental/stack/status/status.integration.test.ts b/apps/cli/src/commands/experimental/stack/status/status.integration.test.ts index c6341788db..358e5f91c0 100644 --- a/apps/cli/src/commands/experimental/stack/status/status.integration.test.ts +++ b/apps/cli/src/commands/experimental/stack/status/status.integration.test.ts @@ -172,6 +172,7 @@ const makeStack = ( get: (_id) => Effect.die("unused"), list: Effect.succeed([...services]), }, + apiTls: { get: Effect.undefined }, credentials: { get: credentialsUnavailable ? Effect.fail(new StackError({ operation: "credentials", message: "owner unreachable" })) diff --git a/apps/cli/src/commands/experimental/stack/update/update.handler.ts b/apps/cli/src/commands/experimental/stack/update/update.handler.ts index a98737607f..5997da5ec7 100644 --- a/apps/cli/src/commands/experimental/stack/update/update.handler.ts +++ b/apps/cli/src/commands/experimental/stack/update/update.handler.ts @@ -5,7 +5,10 @@ import { CommandPlatformApiFactory } from "../../../../auth/command-platform-api import { probeLinkedTarget } from "../../../../command-internal/hosted-versions.ts"; import { readProjectLink } from "../../../../shared/config/project-link.ts"; import { OutputFlag } from "../../../../command-internal/global-flags.ts"; -import { loadStackConfig } from "../../../../command-internal/stack-config.ts"; +import { + loadStackConfig, + stackConfigSuggestion, +} from "../../../../command-internal/stack-config.ts"; import { LOCK_FILE, LockResolutionError, @@ -108,6 +111,7 @@ export const stackUpdate = Effect.fn("experimental.stack.update")(function* ( : new StackCommandUpdateError({ reason: Schema.is(LockResolutionError)(error) ? "lock" : "invalid-config", message: error.message, + suggestion: stackConfigSuggestion(error), cause: error, }), ), diff --git a/apps/cli/src/commands/functions/serve/SIDE_EFFECTS.md b/apps/cli/src/commands/functions/serve/SIDE_EFFECTS.md index f0cf7b2394..fb4d3c40e4 100644 --- a/apps/cli/src/commands/functions/serve/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/functions/serve/SIDE_EFFECTS.md @@ -133,8 +133,9 @@ any difference between the configuration serve resolves (env files, per-function restarts Functions for the serving session, and the saved composed configuration is restored on exit when the owner remains reachable. Edits made while serving apply on the next `functions serve`, because the stack backend does not watch files. Import-map and inspector flags -are rejected before any stack mutation. Stack mode writes no project files and does not stop or -restart the whole composition. +are rejected before any stack mutation with `Import-map and inspector flags are not supported by +experimental Functions serve.` Stack mode writes no project files and does not stop or +restart the whole composition, except that a failed api.tls start check stops it. Stack mode resolves the env like legacy serve on every invocation, for a composed or temporary service: the shared Functions `.env`, or the explicit `--env-file` instead, overrides the TOML `edge_runtime.secrets`, and without `--env-file` each enabled `/.env` overrides @@ -145,7 +146,13 @@ fails the command. Per-function TOML `env` remains the final override for that function. Multiline values and names the process environment cannot carry reach the runtime through its Functions config. `--debug` runs the runtime verbose for the command lifetime. A temporary service uses the API port of a -running REST, Auth, Storage or Realtime service, else the configured `api.port`. +running REST, Auth, Storage or Realtime service, else the configured `api.port`; on a stack +started with `[api.tls]` it also gets `SUPABASE_INTERNAL_HOST_URL=https://127.0.0.1:`, which +its banner prints, like a composed one. Functions receive `SUPABASE_DB_URL` for the `postgres` +role, like legacy serve. +On a Docker or Podman stack serving `[api.tls]` with its database running, starting the Functions +instance runs the `stack start` api.tls check; a failure stops the stack's services and fails serve +with that error. Without a configured `import_map`, a function uses its own `deno.json` or `deno.jsonc`; a per-function `import_map.json` is not read and does not fail the command. diff --git a/apps/cli/src/commands/functions/serve/serve.integration.test.ts b/apps/cli/src/commands/functions/serve/serve.integration.test.ts index fc03242585..704d862b73 100644 --- a/apps/cli/src/commands/functions/serve/serve.integration.test.ts +++ b/apps/cli/src/commands/functions/serve/serve.integration.test.ts @@ -311,7 +311,9 @@ function mockCommandTelemetry() { record: (values: CommandTelemetryAttributeValues) => Ref.update(records, (current) => [...current, values]), }), - recorded: Ref.get(records), + recorded: Ref.get(records).pipe( + Effect.map((recorded) => recorded.filter((values) => !("config_format" in values))), + ), }; } diff --git a/apps/cli/src/commands/functions/serve/serve.stack.e2e.test.ts b/apps/cli/src/commands/functions/serve/serve.stack.e2e.test.ts index 2e7728ecd7..601770e4d8 100644 --- a/apps/cli/src/commands/functions/serve/serve.stack.e2e.test.ts +++ b/apps/cli/src/commands/functions/serve/serve.stack.e2e.test.ts @@ -133,9 +133,10 @@ const fixture = Effect.fn("FunctionsServeE2e.fixture")(function* ( if (rest === undefined || database === undefined) return yield* Effect.die("fixture services missing"); const apiUrl = (yield* rest.credentials()).apiUrl; - const databaseUrl = (yield* database.credentials({ from: "runtime" })).databaseUrl; - if (apiUrl === undefined || databaseUrl === undefined) + const { databaseUrl, functionsDatabaseUrl } = yield* database.credentials({ from: "runtime" }); + if (apiUrl === undefined || databaseUrl === undefined || functionsDatabaseUrl === undefined) return yield* Effect.die("fixture URLs missing"); + expect(new URL(functionsDatabaseUrl).username).toBe("postgres"); if (!included) { const httpPort = (yield* rest.status).endpoints.find(({ name }) => name === "http")?.port; if (httpPort === undefined) return yield* Effect.die("API port missing"); @@ -151,7 +152,15 @@ const fixture = Effect.fn("FunctionsServeE2e.fixture")(function* ( endpoints: { http: { port: httpPort } }, }); } - return { root, home, stack, services: yield* stack.services.list, apiUrl, databaseUrl }; + return { + root, + home, + stack, + services: yield* stack.services.list, + apiUrl, + databaseUrl, + functionsDatabaseUrl, + }; }); const serve = Effect.fn("FunctionsServeE2e.serve")(function* ( @@ -249,7 +258,7 @@ describe("functions serve (stack e2e)", () => { `attaches and restores temporary overrides on the ${runtime} Functions member`, () => Effect.gen(function* () { - const { root, home, stack, services, apiUrl, databaseUrl } = yield* fixture( + const { root, home, stack, services, apiUrl, functionsDatabaseUrl } = yield* fixture( runtime, true, ); @@ -276,7 +285,7 @@ describe("functions serve (stack e2e)", () => { value: "original", anon: true, service: true, - databaseUrl, + databaseUrl: functionsDatabaseUrl, }); const fs = yield* FileSystem.FileSystem; const sourcePath = `${root}/supabase/functions/hello/index.ts`; @@ -303,7 +312,7 @@ describe("functions serve (stack e2e)", () => { value: "overridden", anon: true, service: true, - databaseUrl, + databaseUrl: functionsDatabaseUrl, }); yield* interrupt(overridden); // The override's own restart is the only launch before its configuration is running. @@ -328,10 +337,8 @@ describe("functions serve (stack e2e)", () => { `removes temporary ${runtime} Functions and keeps it excluded on Ctrl-C`, () => Effect.gen(function* () { - const { root, home, stack, services, apiUrl, databaseUrl } = yield* fixture( - runtime, - false, - ); + const { root, home, stack, services, apiUrl, databaseUrl, functionsDatabaseUrl } = + yield* fixture(runtime, false); const composition = yield* stack.composition.describe; const startedAt = yield* postmasterStartTime(stack, databaseUrl); const child = yield* serve(root, home); @@ -339,7 +346,7 @@ describe("functions serve (stack e2e)", () => { value: null, anon: true, service: true, - databaseUrl, + databaseUrl: functionsDatabaseUrl, }); expect(yield* stack.composition.describe).toEqual(composition); expect(yield* stack.services.list).toHaveLength(services.length + 1); diff --git a/apps/cli/src/commands/functions/serve/serve.stack.handler.ts b/apps/cli/src/commands/functions/serve/serve.stack.handler.ts index db9f0dae05..f7b00791f9 100644 --- a/apps/cli/src/commands/functions/serve/serve.stack.handler.ts +++ b/apps/cli/src/commands/functions/serve/serve.stack.handler.ts @@ -1,4 +1,5 @@ import { StackError, type ServiceCreation, type Stack } from "@supabase/stack/effect"; +import { functionsHostApiUrl } from "@supabase/stack/internal/composition"; import { DateTime, Effect, @@ -293,7 +294,7 @@ const session = Effect.fn("functions.serve.session")(function* (flags: Functions const remoteKeys = refreshedJwks === undefined ? [] : yield* Schema.decodeEffect(JwkArray)(refreshedJwks); const jwks = yield* Schema.encodeEffect(JwksDocument)({ keys: [...remoteKeys, ...localKeys] }); - const databaseUrl = (yield* database.credentials({ from: "runtime" })).databaseUrl; + const databaseUrl = (yield* database.credentials({ from: "runtime" })).functionsDatabaseUrl; if (databaseUrl === undefined) return yield* invalidConfig("The database has no runtime URL."); const apiSource = [...members, ...instances].find( (instance) => @@ -314,6 +315,14 @@ const session = Effect.fn("functions.serve.session")(function* (flags: Functions ? `http://${databaseAddress.hostname}:${port}` : (yield* apiSource.credentials({ from: "runtime" })).apiUrl; if (apiUrl === undefined) return yield* invalidConfig("The stack has no runtime API URL."); + /* Without an API member, saved api TLS still makes the banner's host API origin + `https://127.0.0.1:`. */ + const hostApiUrl = + apiSource === undefined + ? (yield* stack.apiTls.get) === undefined + ? undefined + : `https://127.0.0.1:${port}` + : functionsHostApiUrl((yield* apiSource.credentials({ from: "host" })).apiUrl); const { jwtSecret: _jwtSecret, ...sourceConfig } = source.config; const creation: FunctionsCreation = { ...source, @@ -321,6 +330,7 @@ const session = Effect.fn("functions.serve.session")(function* (flags: Functions ...sourceConfig, jwks, apiUrl, + ...(hostApiUrl === undefined ? {} : { hostApiUrl }), databaseUrl, ...(yield* serveEnv(workdir, envFile, config.source, source.config)), ...(Option.isSome(flags.noVerifyJwt) ? { verifyJwt: !flags.noVerifyJwt.value } : {}), diff --git a/apps/cli/src/commands/functions/serve/serve.stack.integration.test.ts b/apps/cli/src/commands/functions/serve/serve.stack.integration.test.ts index f73156e633..b213732a6b 100644 --- a/apps/cli/src/commands/functions/serve/serve.stack.integration.test.ts +++ b/apps/cli/src/commands/functions/serve/serve.stack.integration.test.ts @@ -126,6 +126,8 @@ const fixture = ( readonly projectRoot?: string; readonly standaloneProjectRoot?: string; readonly realtimeApiPort?: number; + /** The stack serves its API port over TLS, so host clients get an `https` origin. */ + readonly apiTls?: boolean; readonly savedFunctions?: Partial>; readonly savedGotrueJwtKeys?: string; readonly savedJwks?: string; @@ -221,7 +223,10 @@ const fixture = ( service: "database" as const, status: Effect.succeed(observation("database", databaseCreation)), credentials: () => - Effect.succeed({ databaseUrl: "postgresql://postgres@127.0.0.1:54322/postgres" }), + Effect.succeed({ + databaseUrl: "postgresql://supabase_admin@127.0.0.1:54322/postgres", + functionsDatabaseUrl: "postgresql://postgres@127.0.0.1:54322/postgres", + }), start: Effect.void, ready: Effect.void, stop: Effect.void, @@ -258,7 +263,10 @@ const fixture = ( }, ), ), - credentials: () => Effect.succeed({ apiUrl: `http://127.0.0.1:${realtimeApiPort}` }), + credentials: (input) => + Effect.succeed({ + apiUrl: `${options.apiTls === true && input?.from === "host" ? "https" : "http"}://127.0.0.1:${realtimeApiPort}`, + }), start: Effect.void, ready: Effect.void, stop: Effect.void, @@ -328,6 +336,9 @@ const fixture = ( >; }, }, + apiTls: { + get: Effect.succeed(options.apiTls === true ? { cert: "saved-cert" } : undefined), + }, credentials: { get: Effect.succeed(stackCredentials) }, composition: { plan: () => Effect.succeed([]), @@ -441,6 +452,7 @@ describe("experimental Stack Functions serve", () => { expect(created.config.anonKey).toBeUndefined(); expect(created.config.serviceRoleKey).toBeUndefined(); expect(created.config.jwks).toBeDefined(); + expect(created.config.databaseUrl).toBe("postgresql://postgres@127.0.0.1:54322/postgres"); const jwks = yield* Schema.decodeEffect(testJwksDocument)(created.config.jwks ?? ""); expect( jwks.keys.some((key) => key.kty === "oct" && key.k === "c2F2ZWQtand0LXNlY3JldA"), @@ -600,6 +612,54 @@ describe("experimental Stack Functions serve", () => { yield* Deferred.await(state.started); expect(state.createdFunctions?.endpoints?.http?.port).toBe(23848); expect(state.createdFunctions?.config.apiUrl).toBe("http://127.0.0.1:23848"); + expect(state.createdFunctions?.config.hostApiUrl).toBeUndefined(); + yield* Deferred.succeed(state.signal, undefined); + yield* Fiber.join(run); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + + it.live("gives standalone Functions the stack's HTTPS host API origin under api.tls", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "functions-api-tls-" }); + yield* fs.makeDirectory(`${root}/supabase`, { recursive: true }); + yield* fs.writeFileString( + `${root}/supabase/config.toml`, + 'project_id = "functions-api-tls"\n\n[edge_runtime]\nenabled = true\n', + ); + const state = yield* fixture({ + standaloneProjectRoot: root, + realtimeApiPort: 23849, + apiTls: true, + }); + const run = yield* functionsServeStack(flags()).pipe( + Effect.provide(state.layer), + Effect.forkChild({ startImmediately: true }), + ); + yield* Deferred.await(state.started); + expect(state.createdFunctions?.config.apiUrl).toBe("http://127.0.0.1:23849"); + expect(state.createdFunctions?.config.hostApiUrl).toBe("https://127.0.0.1:23849"); + yield* Deferred.succeed(state.signal, undefined); + yield* Fiber.join(run); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + + it.live("gives standalone Functions the HTTPS host API origin without an API member", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "functions-api-tls-db-only-" }); + yield* fs.makeDirectory(`${root}/supabase`, { recursive: true }); + yield* fs.writeFileString( + `${root}/supabase/config.toml`, + 'project_id = "functions-api-tls-db-only"\n\n[api]\nport = 23850\n\n[edge_runtime]\nenabled = true\n', + ); + const state = yield* fixture({ standaloneProjectRoot: root, apiTls: true }); + const run = yield* functionsServeStack(flags()).pipe( + Effect.provide(state.layer), + Effect.forkChild({ startImmediately: true }), + ); + yield* Deferred.await(state.started); + expect(state.createdFunctions?.config.hostApiUrl).toBe("https://127.0.0.1:23850"); yield* Deferred.succeed(state.signal, undefined); yield* Fiber.join(run); }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), diff --git a/apps/cli/src/commands/init/SIDE_EFFECTS.md b/apps/cli/src/commands/init/SIDE_EFFECTS.md index 21c00e9a70..75bcfabce5 100644 --- a/apps/cli/src/commands/init/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/init/SIDE_EFFECTS.md @@ -99,5 +99,5 @@ Try rerunning the command with --debug to troubleshoot the error. - The `--with-vscode-settings` and `--with-vscode-workspace` flags are hidden backward-compat aliases for the same VS Code helper and both write `.vscode/settings.json` and `.vscode/extensions.json`. - `.vscode/settings.json` includes `json.schemaDownload.trustedDomains` trusting `https://supabase.com/schemas/`, so VS Code loads the hosted config schema without an untrusted-location warning. - The `--with-intellij-settings` flag is a hidden backward-compat alias for generating `.idea/deno.xml`. -- An existing `.vscode/settings.json` / `.vscode/extensions.json` is parsed tolerantly through a JSONC boundary that strips line/block comments and trailing commas, then the template is merged on top: nested objects are merged key by key with template values winning on conflicts, and arrays and scalars from the template replace the existing value. An empty file is treated as absent and the template is written verbatim. A non-empty file that is not valid JSON(C) aborts the command with `InitParseSettingsError` and is left untouched rather than being overwritten. +- An existing `.vscode/settings.json` / `.vscode/extensions.json` is parsed tolerantly through a JSONC boundary that strips line/block comments and trailing commas, then the template is merged on top: nested objects are merged key by key with template values winning on conflicts, and arrays and scalars from the template replace the existing value. The merged result is applied to the existing text as minimal edits, so comments and formatting outside the changed values survive; when the edits cannot be applied without dropping comments, the file is rewritten as plain formatted JSON instead. An empty file is treated as absent and the template is written verbatim. A non-empty file that is not valid JSON(C) aborts the command with `InitParseSettingsError` and is left untouched rather than being overwritten. - No authentication required - purely local file creation. diff --git a/apps/cli/src/commands/init/init.integration.test.ts b/apps/cli/src/commands/init/init.integration.test.ts index d978abc455..648b3ba677 100644 --- a/apps/cli/src/commands/init/init.integration.test.ts +++ b/apps/cli/src/commands/init/init.integration.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "@effect/vitest"; import { BunServices } from "@effect/platform-bun"; import * as SmolToml from "smol-toml"; +import { parseJsonc } from "@supabase/config/internal"; import { orioledbVersions } from "@supabase/stack/internal/artifacts"; import { Cause, @@ -33,10 +34,6 @@ const decodeOrioleDbConfig = Schema.decodeUnknownEffect( }), ); -const decodeJsonObject = Schema.decodeUnknownEffect( - Schema.fromJsonString(Schema.Record(Schema.String, Schema.Unknown)), -); - const readTextFile = (...segments: Array) => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -466,7 +463,9 @@ describe("init", () => { Effect.provide(layer), ); - expect(yield* decodeJsonObject(yield* readTextFile(settingsPath))).toMatchObject({ + const merged = yield* readTextFile(settingsPath); + expect(merged).toContain("// user preferences"); + expect(parseJsonc(merged)).toMatchObject({ "editor.fontSize": 14, "json.schemaDownload.trustedDomains": { "https://example.com/": true, diff --git a/apps/cli/src/commands/secrets/set/set.integration.test.ts b/apps/cli/src/commands/secrets/set/set.integration.test.ts index 0c2bea8032..a006ecd7b8 100644 --- a/apps/cli/src/commands/secrets/set/set.integration.test.ts +++ b/apps/cli/src/commands/secrets/set/set.integration.test.ts @@ -1143,7 +1143,7 @@ FROM_CONFIG = "config-value" Effect.catchTag("CliConfigRemovedKeyError", (error) => Effect.succeed(error.message)), ); expect(message).toBe( - "[inbucket] in supabase/config.toml is no longer supported. Use [local_smtp] instead.", + "inbucket in supabase/config.toml is no longer supported. Use local_smtp instead.", ); expect(api.requests).toHaveLength(0); expect(out.stdoutText).not.toContain("Finished supabase secrets set."); diff --git a/apps/cli/src/commands/seed/buckets/SIDE_EFFECTS.md b/apps/cli/src/commands/seed/buckets/SIDE_EFFECTS.md index be893ff40e..a74154866b 100644 --- a/apps/cli/src/commands/seed/buckets/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/seed/buckets/SIDE_EFFECTS.md @@ -45,10 +45,13 @@ first, so the gateway targets the same port/scheme the stack was actually brought up on (#6452). **Local (stack backend):** the Storage endpoint comes from the selected composition's -Storage member observation, and the service-role JWT is generated from the primary database's -observed JWT secret. `[api]`/`[api.tls]` fields and their `SUPABASE_API_*` overrides are not -consulted. The stack is opened without launching the owner or any service member. See Notes -for the capability-state gate. +Storage member observation, and the service-role JWT is the stack's saved service-role key +(`stack.credentials`). `[api]`/`[api.tls]` fields and their `SUPABASE_API_*` overrides are not +consulted: a stack started with `[api.tls]` serves that endpoint over `https`, trusting the +certificate saved in the stack's state at start, never `config.toml`. A saved certificate with a +self-signed root is the only trusted CA; a CA-issued one is verified against Bun's default trust +store and `NODE_EXTRA_CA_CERTS`. The stack is opened without launching the owner or any service +member. See Notes for the capability-state gate. **Remote project:** `https://.` (default host: `supabase.co`). @@ -238,8 +241,8 @@ configured`, or a 404 on `ListVectorBuckets`), a WARNING is printed and object result is refined by extension via a built-in MIME table (the host OS MIME database is not consulted; the deterministic built-in table is used instead). - **Stack backend (local).** The Storage endpoint comes from the selected composition's - Storage member observation, and the service-role JWT is generated from the primary database's - observed JWT secret. `seed buckets` opens saved state without launching the owner or any + Storage member observation, and the service-role JWT is the stack's saved service-role key + (`stack.credentials`). `seed buckets` opens saved state without launching the owner or any service member. All legacy `[api]`/`[api.tls]`/`SUPABASE_API_*`/`SUPABASE_AUTH_{JWT_SECRET,SERVICE_ROLE_KEY}` config validation above (including the `<16`-char secret and TLS cert/key-pairing checks) is skipped on this path, even when there is nothing configured to seed. diff --git a/apps/cli/src/commands/services/SIDE_EFFECTS.md b/apps/cli/src/commands/services/SIDE_EFFECTS.md index 9eb8041645..a83b288bfe 100644 --- a/apps/cli/src/commands/services/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/services/SIDE_EFFECTS.md @@ -40,14 +40,14 @@ Tenant calls send `apikey: ` and additionally ## Environment Variables -| Variable | Purpose | Required? | -| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| `SUPABASE_ACCESS_TOKEN` | auth token for Management API linked-version checks | no (falls back to keyring, then `~/.supabase/access-token`) | -| `SUPABASE_PROFILE` | built-in profile name or YAML file path | no (falls back to `~/.supabase/profile` -> `supabase`) | -| `SUPABASE_API_MAX_RETRIES` | Management API client retries for linked-version checks (`0` = none) | no (falls back to 5) | -| `SUPABASE_USE_SLIM_IMAGES` | Ambient `process.env` only (`true`/`1` enable). Rewrites legacy current-pin `SERVICE IMAGE`/`name` fields to `ghcr.io/supabase/cli/`; Kong stays on docker.io. Majors 13/15 list the slim `15.14.1.167` pin when enabled; flag-off keeps `15.8.1.085`. Ignored by the stack backend. | no | -| `SUPABASE_EXPERIMENTAL_STACK` | Selects the stack backend (`1`/`true`) or legacy backend (`0`/`false`); unset or empty uses `experimental.stack`. Non-boolean values fail routing. | no | -| `SUPABASE_DB_MAJOR_VERSION` | Stack backend PostgreSQL major override; supported values are 15 and 17. | no | +| Variable | Purpose | Required? | +| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | +| `SUPABASE_ACCESS_TOKEN` | auth token for Management API linked-version checks | no (falls back to keyring, then `~/.supabase/access-token`) | +| `SUPABASE_PROFILE` | built-in profile name or YAML file path | no (falls back to `~/.supabase/profile` -> `supabase`) | +| `SUPABASE_API_MAX_RETRIES` | Management API client retries for linked-version checks (`0` = none) | no (falls back to 5) | +| `SUPABASE_USE_SLIM_IMAGES` | Ambient `process.env` only (`true`/`1` enable). Rewrites legacy current-pin `SERVICE IMAGE`/`name` fields to `ghcr.io/supabase/cli/`; Kong stays on docker.io. Major 15 lists the slim `15.14.1.167` pin when enabled; flag-off keeps `15.8.1.085`. Ignored by the stack backend. | no | +| `SUPABASE_EXPERIMENTAL_STACK` | Selects the stack backend (`1`/`true`) or legacy backend (`0`/`false`); unset or empty uses `experimental.stack`. Non-boolean values fail routing. | no | +| `SUPABASE_DB_MAJOR_VERSION` | Stack backend PostgreSQL major override; supported values are 15 and 17. | no | ## Exit Codes diff --git a/apps/cli/src/commands/start/SIDE_EFFECTS.md b/apps/cli/src/commands/start/SIDE_EFFECTS.md index 2c4c72505a..b614c70e22 100644 --- a/apps/cli/src/commands/start/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/start/SIDE_EFFECTS.md @@ -97,12 +97,15 @@ reports ` container is not ready: `, after the contain start` runs the same wait, including with `--from-backup`. Every other health-checked container is gated on Docker's health status (`healthy`), polled once -per second within the 30s service timeout. A container with no Docker healthcheck passes once -it is running. PostgREST and Edge Runtime keep their HTTP HEAD probes through Kong. The wait also -stops after `(30 + 1) * (1 + 10)` seconds of wall-clock time, so a gateway that accepts -connections and never answers cannot outlast the retry budget; it then fails like an exhausted -budget, with the last round's reasons (`container is not ready: readiness probe hung after s` -when no round completed). +per second within the 30s service timeout. When Logflare or Vector is started, the timeout is +60s: Logflare migrates its database before serving `/health`, and Vector starts only after +Logflare answers. Both containers also set a 60s health start period, so Docker's 1s start +interval (below) keeps probing them until their first pass. A container with no Docker +healthcheck passes once it is running. PostgREST and Edge Runtime keep their HTTP HEAD probes +through Kong. The wait also stops after `( + 1) * (1 + 10)` seconds of wall-clock time, +so a gateway that accepts connections and never answers cannot outlast the retry budget; it then +fails like an exhausted budget, with the last round's reasons +(`container is not ready: readiness probe hung after s` when no round completed). After that wait, including when `--ignore-health-check` downgrades its failure and when no health-checked service was started, `start` waits up to 15s for Docker's first health verdict on @@ -115,13 +118,14 @@ Before creating any container, `start` runs `docker version --format are Docker API versions >= 1.44, every container whose spec sets a Docker healthcheck also gets `--health-start-interval 1s` and, unless its service sets its own, `--health-start-period 10s`. The first check then runs about 1s after the container starts instead of one 10s interval later, and the -interval returns to 10s after the first pass. Failures inside the period do not count, so a failing -service with 3 retries reaches `unhealthy` about 30s after it starts, or one interval later if a slow -probe straddles the end of the period; the wait's budget and error type do not change. Below API -1.44, when `docker version` fails, or with the Podman CLI or a `docker` shim for it, -`--health-start-interval` is not passed and only Mailpit and Logflare keep their own start period. -The real `docker` client on a Podman socket reporting 1.44 gets them: Podman keeps the start period -and drops the start interval, so there is no speedup there. +interval returns to 10s after the first pass or when the start period ends. Failures inside the +period do not count, so a failing service with 3 retries reaches `unhealthy` about 20s after its +start period ends, or one interval later if a slow probe straddles the end of the period; the wait's +budget and error type do not change. Below API 1.44, when `docker version` fails, or with the +Podman CLI or a `docker` shim for it, `--health-start-interval` is not passed and only Mailpit, +Logflare, and Vector keep their own start period. The real `docker` client on a Podman socket +reporting 1.44 gets them: Podman keeps the start period and drops the start interval, so there is +no speedup there. When a container is running but Docker could not launch its health check, it is judged from the host instead of failing. This applies only when the container's last recorded probe has exit @@ -286,19 +290,19 @@ version check that _would_ call the Management API and is deliberately not imple ## Environment Variables -| Variable | Purpose | Required? | -| -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | -| `SUPABASE_*` (any dotted config field) | Overrides the config key at the matching path, `SUPABASE_` plus the upper-snake path (e.g. `SUPABASE_AUTH_ENABLED`, `SUPABASE_API_PORT`). Shell beats project `.env*`, which beats config. An unparsable value fails the command; an empty value is ignored. Env for a key inside an optional section (e.g. an SMS provider) applies only when the section exists in config. `SUPABASE_AUTH_EMAIL_ENABLED`/`SUPABASE_AUTH_SMS_ENABLED` set `enable_signup` in `[auth.email]`/`[auth.sms]` and beat `SUPABASE_AUTH_EMAIL_ENABLE_SIGNUP`/`SUPABASE_AUTH_SMS_ENABLE_SIGNUP` | no | -| `SUPABASE_EXPERIMENTAL` (or `--experimental`) | Fresh volume + no pg-delta: applies `db.migrations.schema_paths` files instead of `migrations/*.sql` (see "Fresh-volume DB setup" above) | no | -| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | Overrides the image registry used to resolve every service's image | no | -| `SUPABASE_PROJECT_ID` | Overrides the resolved local project id (shell → project `.env*` → config → workdir basename) | no | -| `SUPABASE_WORKDIR` | Resolves `CommandSettings.workdir` | no | -| `SUPABASE_YES` (or `--yes`) | Auto-confirms the fresh-volume bucket-seed overwrite/prune prompts (shell or project dotenv, same as `seed buckets`) | no | -| `BITBUCKET_CLONE_DIR` | When non-empty, drops named volumes and `--security-opt` from every container create | no | -| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | Read from the ambient shell only (a project `.env`/`.env.`/`.env.local` file never selects the daemon) to discover the Docker daemon this whole command talks to; `DOCKER_HOST` is also re-derived and set on Vector's container env so it can reach the host's Docker socket for log collection | no | -| `KONG_NGINX_WORKER_PROCESSES` | Read (ambient shell or project dotenv) into Kong's own container env (defaults to `"1"` when unset) | no | -| `HTTP_PROXY` / `http_proxy` / `HTTPS_PROXY` / `https_proxy` / `NO_PROXY` / `no_proxy` | Bun proxy settings. After project dotenv and container creation, `start` appends `localhost,127.0.0.1,[::1]` to the effective no-proxy value before local Kong probes and seeding; it never changes project/container env and ends with this CLI process. | no | -| `SUPABASE_USE_SLIM_IMAGES` | Ambient `process.env` only (`true`/`1` enable) — not project dotenv. Rewrites current Dockerfile pins to `ghcr.io/supabase/cli/` (including PG15+ realtime/storage/auth migrate jobs). Kong, PG14, OrioleDB tags the catalog does not pin, historical Postgres pins, and `deno_version = 1` remain non-slim (still subject to `SUPABASE_INTERNAL_IMAGE_REGISTRY`). Majors 13/15 use the published slim PG15 pin (`15.14.1.167`) when the flag is on; flag-off keeps `15.8.1.085`. `SUPABASE_INTERNAL_IMAGE_REGISTRY` does not apply to slim refs. A failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli/` | no | +| Variable | Purpose | Required? | +| -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | +| `SUPABASE_*` (any dotted config field) | Overrides the config key at the matching path, `SUPABASE_` plus the upper-snake path (e.g. `SUPABASE_AUTH_ENABLED`, `SUPABASE_API_PORT`). Shell beats project `.env*`, which beats config. An unparsable value fails the command; an empty value is ignored. Env for a key inside an optional section (e.g. an SMS provider) applies only when the section exists in config. `SUPABASE_AUTH_EMAIL_ENABLED`/`SUPABASE_AUTH_SMS_ENABLED` set `enable_signup` in `[auth.email]`/`[auth.sms]` and beat `SUPABASE_AUTH_EMAIL_ENABLE_SIGNUP`/`SUPABASE_AUTH_SMS_ENABLE_SIGNUP` | no | +| `SUPABASE_EXPERIMENTAL` (or `--experimental`) | Fresh volume + no pg-delta: applies `db.migrations.schema_paths` files instead of `migrations/*.sql` (see "Fresh-volume DB setup" above) | no | +| `SUPABASE_INTERNAL_IMAGE_REGISTRY` | Overrides the image registry used to resolve every service's image | no | +| `SUPABASE_PROJECT_ID` | Overrides the resolved local project id (shell → project `.env*` → config → workdir basename) | no | +| `SUPABASE_WORKDIR` | Resolves `CommandSettings.workdir` | no | +| `SUPABASE_YES` (or `--yes`) | Auto-confirms the fresh-volume bucket-seed overwrite/prune prompts (shell or project dotenv, same as `seed buckets`) | no | +| `BITBUCKET_CLONE_DIR` | When non-empty, drops named volumes and `--security-opt` from every container create | no | +| `DOCKER_HOST` / `DOCKER_CONTEXT` / `DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH` / `DOCKER_API_VERSION` / `DOCKER_CONFIG` | Read from the ambient shell only (a project `.env`/`.env.`/`.env.local` file never selects the daemon) to discover the Docker daemon this whole command talks to; `DOCKER_HOST` is also re-derived and set on Vector's container env so it can reach the host's Docker socket for log collection | no | +| `KONG_NGINX_WORKER_PROCESSES` | Read (ambient shell or project dotenv) into Kong's own container env (defaults to `"1"` when unset) | no | +| `HTTP_PROXY` / `http_proxy` / `HTTPS_PROXY` / `https_proxy` / `NO_PROXY` / `no_proxy` | Bun proxy settings. After project dotenv and container creation, `start` appends `localhost,127.0.0.1,[::1]` to the effective no-proxy value before local Kong probes and seeding; it never changes project/container env and ends with this CLI process. | no | +| `SUPABASE_USE_SLIM_IMAGES` | Ambient `process.env` only (`true`/`1` enable) — not project dotenv. Rewrites current Dockerfile pins to `ghcr.io/supabase/cli/` (including PG15+ realtime/storage/auth migrate jobs). Kong, PG14, OrioleDB tags the catalog does not pin, historical Postgres pins, and `deno_version = 1` remain non-slim (still subject to `SUPABASE_INTERNAL_IMAGE_REGISTRY`). Major 15 uses the published slim PG15 pin (`15.14.1.167`) when the flag is on; flag-off keeps `15.8.1.085`. `SUPABASE_INTERNAL_IMAGE_REGISTRY` does not apply to slim refs. A failed GHCR pull falls back to the same tag and digest on `public.ecr.aws/supabase/cli/` | no | `docker`/`podman` must be resolvable on `PATH` — same fallback behavior as `stop`/`status`. @@ -308,29 +312,31 @@ code is surfaced on failure. ## Exit Codes -| Code | Condition | -| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `0` | success — every started container passed its health check, or was accepted through the exec-failure fallback with a stderr `WARNING:` (see "Readiness gating") | -| `0` | the stack was already running — shows status instead of restarting | -| `0` | `--ignore-health-check` set and one or more containers timed out — the failure is printed and swallowed, no rollback | -| `1` | `--ignore-health-check` set, the fresh-volume/Storage-healthy recheck-and-seed path ran (see "Storage bucket seeding"), and that seed itself failed — rolls back despite the flag | -| `1` | malformed CSV in an `--exclude`/`-x` value — fails during flag parsing, before the handler and telemetry, with the exact diagnostic text on stderr; the shorthand frames it with both spellings (e.g. `invalid argument "a\"b" for "-x, --exclude" flag: parse error on line 1, column 2: bare " in non-quoted-field`; a blank-only value fails with `EOF`) — CLI-2005 | -| `1` | malformed `config.toml` / `Config.Validate` failure, including an `auth.email.*.content_path` that resolves outside the project root, or that resolves in-root but is missing/unreadable (checked eagerly, before any Docker work, regardless of `auth.enabled` — see Notes) | -| `1` | an enabled function has `import_map.json` but no `deno.json`/`deno.jsonc` and no `functions..import_map` — `import_map.json in a function directory is no longer supported: `; checked in the preflight whenever Edge Runtime or Studio is enabled, so it fails before any container is created | -| `1` | an unparsable `SUPABASE_*` config override (e.g. a non-boolean `SUPABASE_AUTH_ENABLED`) | -| `1` | stopped Postgres detected but the project id sanitizes to empty — aborts before recovery removes any containers | -| `1` | Postgres container exists but is not running and is not recovered (Bitbucket Pipelines, or Docker reported no state) — ` container is not running: ` (`unknown` for an empty status) with a `supabase stop` then `supabase start` suggestion; the "already running" banner is never printed | -| `1` | another lifecycle command still holds this project's lock after 10 minutes — prints `Waiting for another Supabase CLI command to finish with project ...` (or `...with local Supabase projects...` behind `stop --all`) to stderr first (`ProjectLifecycleLockBusyError`) | -| `1` | `docker`/`podman` not spawnable, or the daemon is unreachable | -| `1` | stopped-stack recovery cannot list, stop, or prune current-project containers, or prune matching networks — aborts before startup; named volumes are preserved | -| `1` | image pull exhausted across every registry candidate, or the Docker daemon becomes unreachable during the pre-pull — even with `--ignore-health-check` (never swallowed into exit 0; see the `--ignore-health-check` note under "Notes") | -| `1` | Studio is enabled and `/supabase/snippets/` cannot be created (a file is in the way, or the workdir is not writable) — fails before any network or container is created | -| `1` | network, volume, container create, or container start failure (including a port conflict) — rolls back everything created so far | -| `1` | health check timeout **without** `--ignore-health-check` (including a container whose exec-failure fallback request keeps failing) — rolls back | -| `1` | Postgres itself fails to start or its own readiness wait (inspect + host connect) times out, **without** `--ignore-health-check` — rolls back | -| `0` | `--ignore-health-check` set and Postgres's own health wait times out — the failure is printed and swallowed, no rollback; no OTHER service is ever created (Postgres's failure is returned before any other bring-up step runs), but the command still prints "Started..." + the (config-derived) status table | -| `1` | fresh-volume DB setup failure (schema SQL / one-shot migrate job / vault upsert / roles seed / migration-apply) — rolls back | -| `1` | fresh-volume bucket-seeding failure — rolls back | +| Code | Condition | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `0` | success — every started container passed its health check, or was accepted through the exec-failure fallback with a stderr `WARNING:` (see "Readiness gating") | +| `0` | the stack was already running — shows status instead of restarting | +| `0` | `--ignore-health-check` set and one or more containers timed out — the failure is printed and swallowed, no rollback | +| `1` | `--ignore-health-check` set, the fresh-volume/Storage-healthy recheck-and-seed path ran (see "Storage bucket seeding"), and that seed itself failed — rolls back despite the flag | +| `1` | malformed CSV in an `--exclude`/`-x` value — fails during flag parsing, before the handler and telemetry, with the exact diagnostic text on stderr; the shorthand frames it with both spellings (e.g. `invalid argument "a\"b" for "-x, --exclude" flag: parse error on line 1, column 2: bare " in non-quoted-field`; a blank-only value fails with `EOF`) — CLI-2005 | +| `1` | a stack-only flag (`--runtime`, `--stack`, `--stack-id`, `--preparation`, `--frozen`, `--eager`) is given while the legacy backend is active — fails during flag parsing with `Unrecognized flag: ` plus a `Hint:` naming the opt-in (`SUPABASE_EXPERIMENTAL_STACK=1`, or `stack = true` under `[experimental]` with that variable unset); other unrecognized flags get no hint | +| `1` | malformed `config.toml` / `Config.Validate` failure, including an `auth.email.*.content_path` that resolves outside the project root, or that resolves in-root but is missing/unreadable (checked eagerly, before any Docker work, regardless of `auth.enabled` — see Notes) | +| `1` | `config.toml` uses a removed key (e.g. `inbucket`) — the message names the key and its replacement and the suggestion is `Update supabase/config.toml, then rerun the command.`, in text and JSON output; fails before any Docker work | +| `1` | an enabled function has `import_map.json` but no `deno.json`/`deno.jsonc` and no `functions..import_map` — `import_map.json in a function directory is no longer supported: `; checked in the preflight whenever Edge Runtime or Studio is enabled, so it fails before any container is created | +| `1` | an unparsable `SUPABASE_*` config override (e.g. a non-boolean `SUPABASE_AUTH_ENABLED`) | +| `1` | stopped Postgres detected but the project id sanitizes to empty — aborts before recovery removes any containers | +| `1` | Postgres container exists but is not running and is not recovered (Bitbucket Pipelines, or Docker reported no state) — ` container is not running: ` (`unknown` for an empty status) with a `supabase stop` then `supabase start` suggestion; the "already running" banner is never printed | +| `1` | another lifecycle command still holds this project's lock after 10 minutes — prints `Waiting for another Supabase CLI command to finish with project ...` (or `...with local Supabase projects...` behind `stop --all`) to stderr first (`ProjectLifecycleLockBusyError`) | +| `1` | `docker`/`podman` not spawnable, or the daemon is unreachable | +| `1` | stopped-stack recovery cannot list, stop, or prune current-project containers, or prune matching networks — aborts before startup; named volumes are preserved | +| `1` | image pull exhausted across every registry candidate, or the Docker daemon becomes unreachable during the pre-pull — even with `--ignore-health-check` (never swallowed into exit 0; see the `--ignore-health-check` note under "Notes") | +| `1` | Studio is enabled and `/supabase/snippets/` cannot be created (a file is in the way, or the workdir is not writable) — fails before any network or container is created | +| `1` | network, volume, container create, or container start failure (including a port conflict) — rolls back everything created so far | +| `1` | health check timeout **without** `--ignore-health-check` (including a container whose exec-failure fallback request keeps failing) — rolls back | +| `1` | Postgres itself fails to start or its own readiness wait (inspect + host connect) times out, **without** `--ignore-health-check` — rolls back | +| `0` | `--ignore-health-check` set and Postgres's own health wait times out — the failure is printed and swallowed, no rollback; no OTHER service is ever created (Postgres's failure is returned before any other bring-up step runs), but the command still prints "Started..." + the (config-derived) status table | +| `1` | fresh-volume DB setup failure (schema SQL / one-shot migrate job / vault upsert / roles seed / migration-apply) — rolls back | +| `1` | fresh-volume bucket-seeding failure — rolls back | Rollback (`rollbackStart`) tears down everything created so far by Docker label, and never masks the original failure — a rollback error @@ -371,6 +377,8 @@ output modes. - stderr (conditional, `--exclude` had invalid values): a `WARNING:` line naming the invalid values and listing the 13 valid ones — the command still proceeds. +- stderr (conditional, `db.major_version = 14`): a `WARNING:` line saying Postgres 14 is end of life + and the CLI will drop support for it soon, printed before any container work and in every output mode. - stderr: already-running banner (`supabase start` in aqua) **or** the bring-up sequence: `Starting database...` (fresh volume) / `Starting database from backup...` (existing volume) → Postgres create+start+readiness wait → `Starting containers...` → (image @@ -408,7 +416,8 @@ buckets to prune.` for a bucket left in place. These seeding lines use the raw w A single JSON object (or a `result` NDJSON event) carrying the same value shape `supabase status --output json` produces. All the progress/warning/banner/security-notice text above is suppressed in these modes — stdout stays payload-only — except the exec-failure -`WARNING:` (see "Readiness gating"), which stays on stderr. On a health-check +`WARNING:` (see "Readiness gating") and the Postgres 14 deprecation `WARNING:`, which stay on +stderr. On a health-check timeout the error payload carries the advice above as a discrete `error.suggestion` string alongside `error.message`, so a caller can surface it without re-parsing the message. It is prose, not structured data. diff --git a/apps/cli/src/commands/start/services/logflare.service.ts b/apps/cli/src/commands/start/services/logflare.service.ts index c677829813..174acebf5c 100644 --- a/apps/cli/src/commands/start/services/logflare.service.ts +++ b/apps/cli/src/commands/start/services/logflare.service.ts @@ -30,6 +30,12 @@ const LOGFLARE_DB_USERNAME = "supabase_admin"; /** The analytics API key's only possible value; never decoded from `config.toml`, so it's hardcoded rather than threaded through as an input. */ const LOGFLARE_API_KEY = "api-key"; +/** + * Keeps Docker's 1s start-interval probes running while Logflare migrates and Vector waits on it, + * so their health turns `healthy` right after they answer; matches the doubled analytics wait. + */ +export const ANALYTICS_HEALTH_START_PERIOD_SECONDS = 60; + /** * Writes and execs a custom `run.sh`: the image's own entrypoint conflicts with the container * healthcheck due to a 15-second startup sleep. Runs `migrate && start` so a failed migration @@ -140,7 +146,7 @@ export function buildLogflareContainerSpec( ports: [{ hostPort: String(input.port), containerPort: "4000" }], healthcheck: slim ? slimWgetHealthcheck("http://127.0.0.1:4000/health", { - startPeriodSeconds: 10, + startPeriodSeconds: ANALYTICS_HEALTH_START_PERIOD_SECONDS, }) : { test: [ @@ -155,7 +161,7 @@ export function buildLogflareContainerSpec( intervalSeconds: 10, timeoutSeconds: 2, retries: 3, - startPeriodSeconds: 10, + startPeriodSeconds: ANALYTICS_HEALTH_START_PERIOD_SECONDS, }, restartPolicy: "unless-stopped", networkId: input.networkId, diff --git a/apps/cli/src/commands/start/services/logflare.service.unit.test.ts b/apps/cli/src/commands/start/services/logflare.service.unit.test.ts index 66d2f1dc79..814d909982 100644 --- a/apps/cli/src/commands/start/services/logflare.service.unit.test.ts +++ b/apps/cli/src/commands/start/services/logflare.service.unit.test.ts @@ -62,7 +62,7 @@ describe("buildLogflareContainerSpec", () => { intervalSeconds: 10, timeoutSeconds: 2, retries: 3, - startPeriodSeconds: 10, + startPeriodSeconds: 60, }); expect(spec.restartPolicy).toBe("unless-stopped"); expect(spec.networkAliases).toEqual(["analytics"]); @@ -205,7 +205,7 @@ describe("buildLogflareContainerSpec", () => { "--spider", "http://127.0.0.1:4000/health", ]); - expect(slim.healthcheck?.startPeriodSeconds).toBe(10); + expect(slim.healthcheck?.startPeriodSeconds).toBe(60); }).pipe(Effect.provide(BunPath.layer)); }); }); diff --git a/apps/cli/src/commands/start/services/postgrest.service.ts b/apps/cli/src/commands/start/services/postgrest.service.ts index 11eeab5ea3..8458bb7287 100644 --- a/apps/cli/src/commands/start/services/postgrest.service.ts +++ b/apps/cli/src/commands/start/services/postgrest.service.ts @@ -23,6 +23,8 @@ export interface PostgrestEnvInput { readonly extraSearchPath: CliConfig["api"]["extra_search_path"]; /** `config.api.max_rows`. */ readonly maxRows: CliConfig["api"]["max_rows"]; + /** `config.api.db_pool`. */ + readonly dbPool: CliConfig["api"]["db_pool"]; /** The `db` container's own Docker name (`serviceContainerName("db", projectId)`). */ readonly dbHost: string; /** See {@link startInternalDbPassword}. */ @@ -41,6 +43,7 @@ export function buildPostgrestEnv(input: PostgrestEnvInput): Record { schemas: ["public", "graphql_public"], extraSearchPath: ["public", "extensions"], maxRows: 1000, + dbPool: undefined, dbHost: "supabase_db_proj", dbPassword: "postgres", jwks: '{"keys":[]}', @@ -52,6 +53,7 @@ describe("buildPostgrestContainerSpec", () => { schemas: ["public"], extraSearchPath: ["public"], maxRows: 1000, + dbPool: undefined, dbUrl: "postgresql://postgres:postgres@127.0.0.1:54322/postgres", jwks: '{"keys":[]}', }; diff --git a/apps/cli/src/commands/start/services/vector.service.ts b/apps/cli/src/commands/start/services/vector.service.ts index 7cec409f56..8ab5f3be89 100644 --- a/apps/cli/src/commands/start/services/vector.service.ts +++ b/apps/cli/src/commands/start/services/vector.service.ts @@ -22,6 +22,7 @@ import { withChildTraceEnv, withProcessSpanScoped } from "../../../shared/teleme import { usesSlimImageRuntime } from "../../../shared/services/slim-images.ts"; import { platformDefaultDockerHost } from "../../../command-internal/hostname.ts"; import { renderStartVectorYaml } from "../lib/template-render.ts"; +import { ANALYTICS_HEALTH_START_PERIOD_SECONDS } from "./logflare.service.ts"; import { ambientEnvironment } from "../../../shared/config/cli-config-provider.layer.ts"; type Spawner = ChildProcessSpawner["Service"]; @@ -227,6 +228,7 @@ const VECTOR_HEALTHCHECK = { intervalSeconds: 10, timeoutSeconds: 2, retries: 3, + startPeriodSeconds: ANALYTICS_HEALTH_START_PERIOD_SECONDS, } as const; /** @@ -305,7 +307,11 @@ export function buildVectorContainerSpec(input: VectorContainerSpecInput): Start entrypoint: "sh", cmd: ["-c", buildVectorEntrypointScript(vectorYaml, input.logflareId, { slim })], binds: input.dockerSocketPlan.binds, - healthcheck: slim ? slimWgetHealthcheck("http://127.0.0.1:9001/health") : VECTOR_HEALTHCHECK, + healthcheck: slim + ? slimWgetHealthcheck("http://127.0.0.1:9001/health", { + startPeriodSeconds: ANALYTICS_HEALTH_START_PERIOD_SECONDS, + }) + : VECTOR_HEALTHCHECK, restartPolicy: "unless-stopped", securityOpt: input.dockerSocketPlan.securityOpt, networkId: input.networkId, diff --git a/apps/cli/src/commands/start/services/vector.service.unit.test.ts b/apps/cli/src/commands/start/services/vector.service.unit.test.ts index bbcbd27a46..76201e5d92 100644 --- a/apps/cli/src/commands/start/services/vector.service.unit.test.ts +++ b/apps/cli/src/commands/start/services/vector.service.unit.test.ts @@ -250,6 +250,7 @@ describe("buildVectorContainerSpec", () => { intervalSeconds: 10, timeoutSeconds: 2, retries: 3, + startPeriodSeconds: 60, }); expect(spec.restartPolicy).toBe("unless-stopped"); expect(spec.networkId).toBe("supabase_network_proj"); @@ -297,6 +298,7 @@ describe("buildVectorContainerSpec", () => { "--spider", "http://127.0.0.1:9001/health", ]); + expect(spec.healthcheck?.startPeriodSeconds).toBe(60); }); }); diff --git a/apps/cli/src/commands/start/start.errors.ts b/apps/cli/src/commands/start/start.errors.ts index 7b9a1f9cc3..8e15f97591 100644 --- a/apps/cli/src/commands/start/start.errors.ts +++ b/apps/cli/src/commands/start/start.errors.ts @@ -25,6 +25,7 @@ export class StartWorkdirError extends Data.TaggedError("StartWorkdirError")<{ /** Loading `config.toml` failed for a reason other than the file being absent (malformed TOML). */ export class StartConfigLoadError extends Data.TaggedError("StartConfigLoadError")<{ readonly message: string; + readonly suggestion?: string; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { return actionability.invalidConfig; diff --git a/apps/cli/src/commands/start/start.handler.ts b/apps/cli/src/commands/start/start.handler.ts index 17feaecd1b..63bce0dfbf 100644 --- a/apps/cli/src/commands/start/start.handler.ts +++ b/apps/cli/src/commands/start/start.handler.ts @@ -91,6 +91,7 @@ import { type ResolvedAuthEmail, } from "../../command-internal/local-config-values.ts"; import { + configLoadFailureSuggestion, describeConfigLoadFailure, loadLocalResolvedConfigContext, type LocalResolvedConfigContext, @@ -137,6 +138,7 @@ import { rollbackStart, } from "../../command-internal/db-bootstrap/rollback.ts"; import { resolveDbBootstrapConfig } from "../../command-internal/db-bootstrap/bootstrap-config.ts"; +import { warnIfPostgres14Deprecated } from "../../command-internal/db-image.ts"; import { startDatabase } from "../../command-internal/db-bootstrap/start-database.ts"; import { START_SERVICES } from "./start.services.ts"; import { @@ -146,6 +148,7 @@ import { import { ensureImagesCached } from "../../command-internal/db-bootstrap/image-prepull.ts"; import { awaitDockerHealthSettled, + HealthCheckTimeoutSeconds, healthCheckExecUnavailableWarning, waitForHealthyServices, type ExecFallbackProbe, @@ -187,6 +190,9 @@ import { buildSupavisorContainerSpec } from "./services/supavisor.service.ts"; /** The analytics API key's only possible value; never configurable. */ const ANALYTICS_API_KEY = "api-key"; +/** Multiplies the service health budget when Logflare or Vector start; see SIDE_EFFECTS.md. */ +const ANALYTICS_HEALTH_TIMEOUT_FACTOR = 2; + function asRecord(value: unknown): Record | undefined { return Predicate.isObject(value) ? value : undefined; } @@ -205,7 +211,10 @@ const startConfigFailure = (cause: unknown) => ? new StartInvalidConfigError({ message: `invalid config for ${cause.path}: ${cause.message}`, }) - : new StartConfigLoadError({ message: describeConfigLoadFailure(cause) }); + : new StartConfigLoadError({ + message: describeConfigLoadFailure(cause), + suggestion: configLoadFailureSuggestion(cause), + }); /** * Wraps a synchronous config resolver that throws on a malformed value into a typed @@ -543,6 +552,7 @@ export const start = Effect.fn("start")(function* (flags: StartFlags) { const dbTomlValues = yield* checkDbConfig(fs, path, cliSettings.workdir).pipe( Effect.withSpan("start.validateDbConfig"), ); + yield* warnIfPostgres14Deprecated(config.db.major_version); const dbContainerId = localDbContainerId(projectId); const filterValue = cliProjectFilterValue(projectId); @@ -877,6 +887,7 @@ export const start = Effect.fn("start")(function* (flags: StartFlags) { const apiSchemas = config.api.schemas; const apiExtraSearchPath = config.api.extra_search_path; const apiMaxRows = config.api.max_rows; + const apiDbPool = config.api.db_pool; // `smtp_port`/`pop3_port` have no TOML default, so `?? 0` preserves the "unconfigured" signal // `mailpit.service.ts`'s `!== 0` publish guard checks. @@ -1046,6 +1057,7 @@ export const start = Effect.fn("start")(function* (flags: StartFlags) { schemas: apiSchemas, extraSearchPath: apiExtraSearchPath, maxRows: apiMaxRows, + dbPool: apiDbPool, dbUrl: values.dbUrl, jwks, }), @@ -1499,8 +1511,8 @@ export const start = Effect.fn("start")(function* (flags: StartFlags) { // `rollbackStart` calls would miss a pure fiber interrupt between steps (see the `bringUp` // pipe's comment for why `onError`, not `tapError`, is required). yield* Effect.gen(function* () { - // 9. Bulk health check over every non-Postgres started container, at - // the generic 30s service timeout. + // 9. Bulk health check over every non-Postgres started container, at the service + // timeout (doubled when Logflare or Vector start; see SIDE_EFFECTS.md). if (output.format === "text") { yield* output.raw(START_WAITING_FOR_HEALTH_CHECKS_MESSAGE, "stderr"); } @@ -1534,8 +1546,16 @@ export const start = Effect.fn("start")(function* (flags: StartFlags) { localKongCa === undefined ? effect : effect.pipe(withStorageGatewayFetch(localKongCa)); // Keep the synthetic value out of project dotenv resolution and container environments. configureLoopbackProxyBypass(); + // Logflare runs its migrations before serving `/health`, and Vector waits on Logflare, so + // their readiness needs a longer budget than the other services. + const serviceTimeoutSeconds = yield* HealthCheckTimeoutSeconds; + const healthTimeoutSeconds = + started.has(logflareContainerName) || started.has(vectorContainerName) + ? serviceTimeoutSeconds * ANALYTICS_HEALTH_TIMEOUT_FACTOR + : serviceTimeoutSeconds; const healthResult = yield* withLocalKongCa( waitForHealthyServices(spawner, [...started.keys()], { + timeoutSeconds: healthTimeoutSeconds, postgrest: postgrestGateway, edgeRuntime: edgeRuntimeGateway, images: started, diff --git a/apps/cli/src/commands/start/start.integration.test.ts b/apps/cli/src/commands/start/start.integration.test.ts index 8b959221a1..3cbe215b7a 100644 --- a/apps/cli/src/commands/start/start.integration.test.ts +++ b/apps/cli/src/commands/start/start.integration.test.ts @@ -763,6 +763,36 @@ describe("start integration", () => { vi.unstubAllEnvs(); }); + describe("Postgres 14 deprecation", () => { + const alreadyRunning = (args: ReadonlyArray) => { + if (args[0] === "container" && args[1] === "inspect") return { stdout: [HEALTHY_STATE] }; + if (args[0] === "ps") return { stdout: [] }; + return { exitCode: 0 }; + }; + + it.effect("warns that Postgres 14 is end of life and will lose CLI support", () => + Effect.gen(function* () { + const { layer, out } = yield* setup({ + configContents: 'project_id = "demo"\n[db]\nmajor_version = 14\n', + route: alreadyRunning, + }); + + yield* start(flags()).pipe(Effect.provide(layer)); + expect(out.stderrText).toContain("Postgres 14 reached end of life"); + expect(out.stderrText).toContain("Upgrade your project to Postgres 17"); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + + it.effect("stays silent on a supported Postgres major", () => + Effect.gen(function* () { + const { layer, out } = yield* setup({ route: alreadyRunning }); + + yield* start(flags()).pipe(Effect.provide(layer)); + expect(out.stderrText).not.toContain("Postgres 14"); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + }); + describe("--exclude validation", () => { it.effect("warns on stderr for an invalid --exclude value, even when already running", () => Effect.gen(function* () { @@ -1627,6 +1657,27 @@ describe("start integration", () => { }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); + it.effect("fails a removed config key with its replacement as the suggestion", () => + Effect.gen(function* () { + const { layer, child } = yield* setup({ + configContents: 'project_id = "demo"\n\n[inbucket]\nenabled = true\n', + }); + + const exit = yield* Effect.exit(start(flags()).pipe(Effect.provide(layer))); + expect(Exit.isFailure(exit)).toBe(true); + if (Exit.isFailure(exit)) { + const error = Option.getOrUndefined(Cause.findErrorOption(exit.cause)); + expect(normalizeCliError(error)).toMatchObject({ + code: "StartConfigLoadError", + message: + "inbucket in supabase/config.toml is no longer supported. Use local_smtp instead.", + suggestion: "Update supabase/config.toml, then rerun the command.", + }); + } + expect(child.spawned).toEqual([]); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ); + it.effect("reports a config.json and config.jsonc conflict without an error-class prefix", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -1802,6 +1853,13 @@ describe("start integration", () => { "--health-start-interval": "1s", }); } + for (const service of ["analytics", "vector"]) { + expect(healthFlagsFor(child.spawned, service)).toMatchObject({ + "--health-interval": "10s", + "--health-start-period": "60s", + "--health-start-interval": "1s", + }); + } expect(healthFlagsFor(child.spawned, "rest")).toEqual({}); }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), ); @@ -3941,6 +3999,38 @@ content_path = "./supabase/templates/custom_notice.html" ); }); + it.live( + "gives Logflare a doubled health budget to finish booting", + () => + Effect.gen(function* () { + const route = defaultRoute(); + let analyticsInspects = 0; + const { layer, out, child } = yield* setup({ + route: (args) => { + if ( + args[0] === "container" && + args[1] === "inspect" && + (args[2] ?? "").includes("_analytics_") + ) { + analyticsInspects += 1; + if (analyticsInspects <= 2) return { stdout: [STARTING_STATE] }; + } + return route(args); + }, + httpClientLayer: unusedHttpClientLayer, + }); + + yield* start(flags({ exclude: ["postgrest", "edge-runtime"] })).pipe(Effect.provide(layer)); + expect(out.stderrText).toContain("Started"); + expect(rollbackWasAttempted(child.spawned)).toBe(false); + expect(analyticsInspects).toBe(3); + }).pipe( + Effect.provideService(HealthCheckTimeoutSeconds, 1), + Effect.provide([BunServices.layer, BunCrypto.layer]), + ), + 10_000, + ); + // Real time, not `it.effect`/`TestClock`: genuine async I/O deep inside the forked effect // (HTTP requests and `resolveDbImage`'s file read) needs real Node // event-loop turns to settle, so a virtualized clock would never let the fiber reach the @@ -5864,6 +5954,22 @@ content_path = "./supabase/templates/custom_notice.html" ).pipe(Effect.provide(BunServices.layer)), ); + it.effect("maps SUPABASE_API_DB_POOL to PostgREST's PGRST_DB_POOL", () => + withEnvVar( + "SUPABASE_API_DB_POOL", + "10", + Effect.gen(function* () { + const { layer, child } = yield* setup(); + + yield* start(flags()).pipe(Effect.provide(layer)); + const restCreate = child.spawned.find( + (s) => s.args[0] === "create" && containerNameFromCreateArgs(s.args).includes("_rest_"), + ); + expect(restCreate?.env["PGRST_DB_POOL"]).toBe("10"); + }).pipe(Effect.provide([BunServices.layer, BunCrypto.layer])), + ).pipe(Effect.provide(BunServices.layer)), + ); + it.effect( "fails with a typed config error, before any container is created, on an invalid SUPABASE_API_MAX_ROWS", () => diff --git a/apps/cli/src/commands/status/SIDE_EFFECTS.md b/apps/cli/src/commands/status/SIDE_EFFECTS.md index 8d7b2bda3a..b858903655 100644 --- a/apps/cli/src/commands/status/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/status/SIDE_EFFECTS.md @@ -86,6 +86,7 @@ convention used elsewhere in config loading, and take precedence over the corres | `0` | **`--ignore-health-check` is set** — skips the health assertion below entirely, so an unhealthy/not-running db never fails the command | | `1` | `supabase/config.toml` missing or malformed | | `1` | malformed CSV in an `--override-name`/`--exclude` value — fails during flag parsing, before the handler and telemetry, with the exact diagnostic text on stderr (e.g. `invalid argument "\"api.url=FOO" for "--override-name" flag: parse error on line 1, column 13: extraneous or missing " in quoted-field`; a blank-only value fails with `EOF`) — CLI-2005 | +| `1` | a stack-only flag (e.g. `--stack`) is given while the legacy backend is active — fails during flag parsing with `Unrecognized flag: ` plus a `Hint:` naming the opt-in (`SUPABASE_EXPERIMENTAL_STACK=1`, or `stack = true` under `[experimental]` with that variable unset); other unrecognized flags get no hint | | `1` | a malformed `--override-name` entry, or the removed `inbucket.url` key (the message names `mailpit.url`) | | `1` | listing running containers failed (Docker daemon unreachable, etc.) | | `1` | the db container inspect call failed (including "not found") — health assertion, skipped by `--ignore-health-check` above | diff --git a/apps/cli/src/commands/stop/SIDE_EFFECTS.md b/apps/cli/src/commands/stop/SIDE_EFFECTS.md index 333bbea781..69372de140 100644 --- a/apps/cli/src/commands/stop/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/stop/SIDE_EFFECTS.md @@ -90,18 +90,19 @@ and ensure it is on PATH") rather than a generic "failed to ..." string. ## Exit Codes -| Code | Condition | -| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `0` | success — containers/volumes/networks pruned | -| `1` | `--project-id` and `--all` both set (`StopMutuallyExclusiveError`) | -| `1` | another lifecycle command still holds the lock after 10 minutes (`ProjectLifecycleLockBusyError`); `--all` waits for every other lifecycle command | -| `1` | `config.toml` present but malformed (`StopConfigLoadError`), or a config value is invalid (`CliConfigValueError`, naming its source) — an **absent** file is not an error | -| `1` | listing containers failed (`StopListError`) | -| `1` | stopping one or more containers failed (`StopContainerError`) | -| `1` | `docker container prune` failed (`StopContainerPruneError`) | -| `1` | `docker volume prune` failed, only reached when volumes are being deleted (`StopVolumePruneError`) | -| `1` | `docker network prune` failed (`StopNetworkPruneError`) | -| `1` | `docker`/`podman` both absent from `PATH` (surfaces as one of the errors above) | +| Code | Condition | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `0` | success — containers/volumes/networks pruned | +| `1` | `--project-id` and `--all` both set (`StopMutuallyExclusiveError`) | +| `1` | a stack-only flag (e.g. `--stack`) is given while the legacy backend is active — fails during flag parsing with `Unrecognized flag: ` plus a `Hint:` naming the opt-in (`SUPABASE_EXPERIMENTAL_STACK=1`, or `stack = true` under `[experimental]` with that variable unset); other unrecognized flags get no hint | +| `1` | another lifecycle command still holds the lock after 10 minutes (`ProjectLifecycleLockBusyError`); `--all` waits for every other lifecycle command | +| `1` | `config.toml` present but malformed (`StopConfigLoadError`), or a config value is invalid (`CliConfigValueError`, naming its source) — an **absent** file is not an error | +| `1` | listing containers failed (`StopListError`) | +| `1` | stopping one or more containers failed (`StopContainerError`) | +| `1` | `docker container prune` failed (`StopContainerPruneError`) | +| `1` | `docker volume prune` failed, only reached when volumes are being deleted (`StopVolumePruneError`) | +| `1` | `docker network prune` failed (`StopNetworkPruneError`) | +| `1` | `docker`/`podman` both absent from `PATH` (surfaces as one of the errors above) | ## Telemetry Events Fired diff --git a/apps/cli/src/commands/storage/cp/SIDE_EFFECTS.md b/apps/cli/src/commands/storage/cp/SIDE_EFFECTS.md index cab5876e68..eb4c8b0c0a 100644 --- a/apps/cli/src/commands/storage/cp/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/storage/cp/SIDE_EFFECTS.md @@ -118,10 +118,14 @@ backend — same roles as `storage ls`. - The runtime default for `--content-type` is `""` (empty ⇒ auto-detect). - Relative local paths resolve against the original cwd. - **Stack backend (local target).** The Storage endpoint comes from the selected composition's - Storage member observation, and the service-role JWT is generated from the primary database's - observed JWT secret. The stack is opened by project identity through the `@supabase/stack` API, + Storage member observation, and the service-role JWT is the stack's saved service-role key + (`stack.credentials`). The stack is opened by project identity through the `@supabase/stack` API, which reads stack state under `SUPABASE_HOME`; `cp` opens saved state without launching - the owner or any service member. + the owner or any service member. A stack started with `[api.tls]` serves that endpoint over + `https`, and the request trusts the certificate saved in the stack's state at start, never + `config.toml`, so editing `api.tls` applies at the next start. A saved certificate with a + self-signed root is the only trusted CA; a CA-issued one is verified against Bun's default + trust store and `NODE_EXTRA_CA_CERTS`. - **Stack backend — capability policy.** Storage excluded from the composition errors with `StackStorageCapabilityError` and guidance to enable `[storage]`, then run `supabase start` without `--exclude storage`. Failed or manually stopped Storage is unusable. Dormant, starting, and ready Storage diff --git a/apps/cli/src/commands/storage/ls/SIDE_EFFECTS.md b/apps/cli/src/commands/storage/ls/SIDE_EFFECTS.md index addb64c44d..e72732465b 100644 --- a/apps/cli/src/commands/storage/ls/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/storage/ls/SIDE_EFFECTS.md @@ -109,10 +109,14 @@ No custom storage telemetry events. subcommand token (`storage ls --remote`, not `storage --remote ls`) — the same shape the `db` family uses. - **Stack backend (local target).** The Storage endpoint comes from the selected composition's - Storage member observation, and the service-role JWT is generated from the primary database's - observed JWT secret. The stack is opened by project identity through the `@supabase/stack` API, + Storage member observation, and the service-role JWT is the stack's saved service-role key + (`stack.credentials`). The stack is opened by project identity through the `@supabase/stack` API, which reads stack state under `SUPABASE_HOME`; `ls` opens saved state without launching - the owner or any service member. + the owner or any service member. A stack started with `[api.tls]` serves that endpoint over + `https`, and the request trusts the certificate saved in the stack's state at start, never + `config.toml`, so editing `api.tls` applies at the next start. A saved certificate with a + self-signed root is the only trusted CA; a CA-issued one is verified against Bun's default + trust store and `NODE_EXTRA_CA_CERTS`. - **Stack backend — capability policy.** Storage excluded from the composition errors with `StackStorageCapabilityError` and guidance to enable `[storage]`, then run `supabase start` without `--exclude storage`. Failed or manually stopped Storage is unusable. Dormant, starting, and ready Storage diff --git a/apps/cli/src/commands/storage/ls/ls.integration.test.ts b/apps/cli/src/commands/storage/ls/ls.integration.test.ts index 5e6f013ee9..2e2de9bc4a 100644 --- a/apps/cli/src/commands/storage/ls/ls.integration.test.ts +++ b/apps/cli/src/commands/storage/ls/ls.integration.test.ts @@ -24,12 +24,72 @@ import { StorageGatewayStatusError } from "../../../command-internal/storage-gat import { storageLs } from "./ls.handler.ts"; import type { StorageLsFlags } from "./ls.command.ts"; import { generateLocalJwt } from "../../../command-internal/local-jwt.ts"; +import { KONG_LOCAL_TLS_CERT } from "../../start/templates/kong-local-tls.ts"; const BUCKET = "/storage/v1/bucket"; const LIST = (bucket: string) => `/storage/v1/object/list/${bucket}`; const REVEALED_API_KEYS = `GET https://api.supabase.com/v1/projects/${VALID_REF}/api-keys?reveal=true`; const PROJECT_LOOKUP = `GET https://api.supabase.com/v1/projects/${VALID_REF}`; const CACHE_FILE = "supabase/.temp/linked-project.json"; +/* A `localhost` leaf issued by `TEST_CA_CERT`. */ +const CA_ISSUED_LEAF_CERT = `-----BEGIN CERTIFICATE----- +MIIBRjCB7qADAgECAhRCV8GkkgTi9ZTiuKqZY4sOezoM4TAKBggqhkjOPQQDAjAS +MRAwDgYDVQQDDAdUZXN0IENBMCAXDTI2MTEwOTEzNDE1OVoYDzIxMjYxMDE2MTM0 +MTU5WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASY7wtAjlIKwjqnCEZMUlfiwJGcStRssO45rBgo4R4OF2JMObn2mFxoFypp +qZgXQn194pdifFyurKHzU+X3JkAoox4wHDAaBgNVHREEEzARgglsb2NhbGhvc3SH +BH8AAAEwCgYIKoZIzj0EAwIDRwAwRAIgWNrL5BKuVMqo1U9Nh1Op8+FTKssMIjQN +Q2S/oIrjKrgCIA2gyf8CcItodnGLFYJwMhKdf0iCAlq+/qpFkOzY8s1I +-----END CERTIFICATE----- +`; +/* A `localhost` leaf issued by a CA that signed it with, and gave it, the CA's own key. */ +const CA_KEY_REUSING_LEAF_CERT = `-----BEGIN CERTIFICATE----- +MIIBVTCB/KADAgECAhR4kYYkrCXgog/zddslakRmyH+xizAKBggqhkjOPQQDAjAS +MRAwDgYDVQQDDAdUZXN0IENBMCAXDTI2MTEwOTE0MjgxOFoYDzIxMjYxMDE2MTQy +ODE4WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASzwQhCGwKjZuWyeTYilHQlNL/SvOWn/Zkx8PKMFo2qlf4KwyVvSpT1drHh +OCoVy5J6w6pe/q/tAHt1Cwl7YBRWoywwKjAMBgNVHRMBAf8EAjAAMBoGA1UdEQQT +MBGCCWxvY2FsaG9zdIcEfwAAATAKBggqhkjOPQQDAgNIADBFAiEA7zTomLOfHVOH +Pe4hUZWq4jAq9wMwTUAGndjSCuI+rDgCIGJT3tzvx13epP7hgX3XO5nN41kKl/H3 +PwqCAg+n5VDT +-----END CERTIFICATE----- +`; +/* A `localhost` leaf issued by another `localhost` CA, so its subject names its issuer. */ +const SAME_NAME_ISSUED_LEAF_CERT = `-----BEGIN CERTIFICATE----- +MIIBVjCB/qADAgECAhQEUnl3yH/LOMrhaw0GuaXKPkZ1qTAKBggqhkjOPQQDAjAU +MRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMjYxMTA5MTUzMjExWhgPMjEyNjEwMTYx +NTMyMTFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49 +AwEHA0IABJ7nnsKdr3XHkttuGUNcghIE5+up1e0frS1WYi45NtqUtA1WjajFx3z3 +qk92KYyevrDPXHD4G8IfMlBOpQD22h+jLDAqMBoGA1UdEQQTMBGCCWxvY2FsaG9z +dIcEfwAAATAMBgNVHRMBAf8EAjAAMAoGCCqGSM49BAMCA0cAMEQCIE2IdgjAjro+ +0FFQVLumGmqF6TCwA2sKzYwaHqepisN3AiBzNeA9prRBijsRZ4+iVlJTrinKJwZd +jFgn9/KcFeKqyA== +-----END CERTIFICATE----- +`; +/* A self-signed `localhost` leaf whose key usage has no `keyCertSign`. */ +const SELF_SIGNED_LEAF_CERT = `-----BEGIN CERTIFICATE----- +MIIBhzCCAS2gAwIBAgIUXkUA3O/35tpuViO2x3YAXbjuSIowCgYIKoZIzj0EAwIw +FDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTI2MTEwOTE0MDkyN1oYDzIxMjYxMDE2 +MTQwOTI3WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjO +PQMBBwNCAATY9WkehjE3fyap/oZ7nuygpBIVkjDMHG3sFfBRjXp9HMI5/20kSb9h +74eKvk1hoILB3w0Tw3dNyS0M0y5s6wYto1swWTAdBgNVHQ4EFgQUm7MD4rJsHvM/ +o7v6jkmkKeI6wtswDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBaAwGgYDVR0R +BBMwEYIJbG9jYWxob3N0hwR/AAABMAoGCCqGSM49BAMCA0gAMEUCICihwiiY67Td +draV8ipjMEBSwlmqeg3tYZk8jQA46nrzAiEAxNVbz9miV+3U6q9r2BIUMESRd52m +QG8UemIDJ94iGWk= +-----END CERTIFICATE----- +`; +const TEST_CA_CERT = `-----BEGIN CERTIFICATE----- +MIIBWjCCAQCgAwIBAgIUYsahU3X8ja50he4Tb9nzW7jQM0EwCgYIKoZIzj0EAwIw +EjEQMA4GA1UEAwwHVGVzdCBDQTAgFw0yNjExMDkxMzQxNTlaGA8yMTI2MTAxNjEz +NDE1OVowEjEQMA4GA1UEAwwHVGVzdCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEH +A0IABOFbj4eYzjEBwqSgHSCK9ftNcRuedMeV18a0fTWUKF206O6fLf2AGJz7UnhU +M31Hta1JQ1xKlh8Yl6piuW3M2e2jMjAwMB0GA1UdDgQWBBQOCeHtneH3r4od2nku +A3HN9apjkTAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIFv8EoMV +UlxVfYkPUQxovGMm3EYOzXaVvdmG/Z60dqtUAiEArBmXL7PqMcWLkPYJmEzoa5f4 +yUneyzDjVHiOKnszqQ4= +-----END CERTIFICATE----- +`; const writeAncestorConfig = Effect.fnUntraced(function* (root: string, toml: string) { const fs = yield* FileSystem.FileSystem; @@ -754,6 +814,50 @@ describe("stack backend", () => { }); }); + it.effect.each([ + { name: "trusting the embedded self-signed cert", cert: KONG_LOCAL_TLS_CERT, trusted: true }, + { + name: "trusting a leaf and root bundle", + cert: CA_ISSUED_LEAF_CERT + TEST_CA_CERT, + trusted: true, + }, + { name: "trusting a self-signed leaf", cert: SELF_SIGNED_LEAF_CERT, trusted: true }, + { name: "with default trust for a CA-issued leaf", cert: CA_ISSUED_LEAF_CERT, trusted: false }, + { + name: "with default trust for a CA-issued leaf on its CA's key", + cert: CA_KEY_REUSING_LEAF_CERT, + trusted: false, + }, + { + name: "with default trust for a leaf its same-named CA issued", + cert: SAME_NAME_ISSUED_LEAF_CERT, + trusted: false, + }, + ])( + "lists over HTTPS with the stack's saved certificate after an api.tls edit, $name", + ({ cert, trusted }) => { + /* `config.toml` now names a pair that does not exist; the stack keeps what it started with. */ + const { layer, out, requests } = setupStorage(tmp.current, { + toml: 'project_id = "test"\n[api.tls]\nenabled = true\ncert_path = "missing.crt"\nkey_path = "missing.key"\n', + local: true, + stackBackend: true, + stackApi: { storageState: "ready", apiTlsCert: cert }, + routes: [{ method: "GET", match: BUCKET, body: [{ name: "test", id: "test" }] }], + }); + return Effect.gen(function* () { + const exit = yield* storageLs(lsFlags()).pipe(Effect.provide(layer), Effect.exit); + expect(Exit.isSuccess(exit)).toBe(true); + expect(out.stdoutText).toBe("test/\n"); + expect(requests).toEqual([ + expect.objectContaining({ + url: expect.stringMatching(/^https:\/\/127\.0\.0\.1:59999\//u), + ca: trusted ? cert : undefined, + }), + ]); + }); + }, + ); + it.effect("proceeds to the gateway while Storage is stopping with wake retained", () => { const { layer, out } = setupStorage(tmp.current, { toml: 'project_id = "test"\n', diff --git a/apps/cli/src/commands/storage/mv/SIDE_EFFECTS.md b/apps/cli/src/commands/storage/mv/SIDE_EFFECTS.md index ef646a3c53..2099dc6ab5 100644 --- a/apps/cli/src/commands/storage/mv/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/storage/mv/SIDE_EFFECTS.md @@ -108,10 +108,14 @@ backend — same roles as `storage ls`. - Both `src` and `dst` must be `ss://` URLs (a stricter parse than the lenient one `cp` uses). - **Stack backend (local target).** The Storage endpoint comes from the selected composition's - Storage member observation, and the service-role JWT is generated from the primary database's - observed JWT secret. The stack is opened by project identity through the `@supabase/stack` API, + Storage member observation, and the service-role JWT is the stack's saved service-role key + (`stack.credentials`). The stack is opened by project identity through the `@supabase/stack` API, which reads stack state under `SUPABASE_HOME`; `mv` opens saved state without launching - the owner or any service member. + the owner or any service member. A stack started with `[api.tls]` serves that endpoint over + `https`, and the request trusts the certificate saved in the stack's state at start, never + `config.toml`, so editing `api.tls` applies at the next start. A saved certificate with a + self-signed root is the only trusted CA; a CA-issued one is verified against Bun's default + trust store and `NODE_EXTRA_CA_CERTS`. - **Stack backend — capability policy.** Storage excluded from the composition errors with `StackStorageCapabilityError` and guidance to enable `[storage]`, then run `supabase start` without `--exclude storage`. Failed or manually stopped Storage is unusable. Dormant, starting, and ready Storage diff --git a/apps/cli/src/commands/storage/rm/SIDE_EFFECTS.md b/apps/cli/src/commands/storage/rm/SIDE_EFFECTS.md index af2de3f945..c2b3240e36 100644 --- a/apps/cli/src/commands/storage/rm/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/storage/rm/SIDE_EFFECTS.md @@ -135,10 +135,14 @@ Requires `--yes`/`SUPABASE_YES` on the same terms as `json`. prefixes not returned as removed are then walked recursively when `-r` is set. - Object deletes are chunked at `DELETE_OBJECTS_LIMIT` (1000) per request. - **Stack backend (local target).** The Storage endpoint comes from the selected composition's - Storage member observation, and the service-role JWT is generated from the primary database's - observed JWT secret. The stack is opened by project identity through the `@supabase/stack` API, + Storage member observation, and the service-role JWT is the stack's saved service-role key + (`stack.credentials`). The stack is opened by project identity through the `@supabase/stack` API, which reads stack state under `SUPABASE_HOME`; `rm` opens saved state without launching - the owner or any service member. + the owner or any service member. A stack started with `[api.tls]` serves that endpoint over + `https`, and the request trusts the certificate saved in the stack's state at start, never + `config.toml`, so editing `api.tls` applies at the next start. A saved certificate with a + self-signed root is the only trusted CA; a CA-issued one is verified against Bun's default + trust store and `NODE_EXTRA_CA_CERTS`. - **Stack backend — capability policy.** Storage excluded from the composition errors with `StackStorageCapabilityError` and guidance to enable `[storage]`, then run `supabase start` without `--exclude storage`. Failed or manually stopped Storage is unusable. Dormant, starting, and ready Storage diff --git a/apps/cli/src/commands/vanity-subdomains/activate/SIDE_EFFECTS.md b/apps/cli/src/commands/vanity-subdomains/activate/SIDE_EFFECTS.md index 7666b32bfc..7ca7cfdd1e 100644 --- a/apps/cli/src/commands/vanity-subdomains/activate/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/vanity-subdomains/activate/SIDE_EFFECTS.md @@ -52,10 +52,10 @@ Target: hosted, consent default No — see [Command target](../../../../docs/com ## Telemetry Events Fired -| Event | When | Notable properties / groups | -| ----------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------ | -| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | -| `cli_upgrade_suggested` | 4xx whose body is the `entitlement_required` envelope | `feature_key=vanity_subdomain`, `org_slug` | +| Event | When | Notable properties / groups | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a 4xx whose body is the `entitlement_required` envelope | `feature_key=vanity_subdomain`, `org_slug` | ## Output diff --git a/apps/cli/src/commands/vanity-subdomains/activate/activate.handler.ts b/apps/cli/src/commands/vanity-subdomains/activate/activate.handler.ts index fc3e6dd81a..752a1b41f3 100644 --- a/apps/cli/src/commands/vanity-subdomains/activate/activate.handler.ts +++ b/apps/cli/src/commands/vanity-subdomains/activate/activate.handler.ts @@ -2,7 +2,6 @@ import { Effect, Option } from "effect"; import { CommandPlatformApi } from "../../../auth/command-platform-api.service.ts"; import { resolveProjectTarget } from "../../../command-internal/target/resolve-project-target.ts"; -import { gateResponse, suggestUpgrade } from "../../../command-internal/upgrade-suggest.ts"; import { LinkedProjectCache } from "../../../telemetry/linked-project-cache.service.ts"; import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; import { OutputFlag } from "../../../command-internal/global-flags.ts"; @@ -68,26 +67,7 @@ export const vanitySubdomainsActivate = Effect.fn("vanity-subdomains.activate")( }) .pipe( Effect.tapError(() => activating?.fail() ?? Effect.void), - Effect.catch((cause) => - mapActivateError(cause).pipe( - Effect.catchTag("VanitySubdomainsActivateUnexpectedStatusError", (mapped) => - Effect.gen(function* () { - const upgradeSuggested = yield* suggestUpgrade({ - projectRef: ref, - statusCode: mapped.status, - response: gateResponse(cause), - }); - return yield* new VanitySubdomainsActivateUnexpectedStatusError({ - status: mapped.status, - body: mapped.body, - message: mapped.message, - upgradeSuggested, - entitlement: mapped.entitlement, - }); - }), - ), - ), - ), + Effect.catch(mapActivateError), ); yield* activating?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/vanity-subdomains/check-availability/SIDE_EFFECTS.md b/apps/cli/src/commands/vanity-subdomains/check-availability/SIDE_EFFECTS.md index 06ced207b0..07267fddaa 100644 --- a/apps/cli/src/commands/vanity-subdomains/check-availability/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/vanity-subdomains/check-availability/SIDE_EFFECTS.md @@ -49,12 +49,10 @@ Target: hosted, no consent — see [Command target](../../../../docs/command-tar ## Telemetry Events Fired -| Event | When | Notable properties / groups | -| ---------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------- | -| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | - -This command may print an upgrade suggestion for a 4xx whose body is the `entitlement_required` envelope, but it does not fire -`cli_upgrade_suggested`. +| Event | When | Notable properties / groups | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a 4xx whose body is the `entitlement_required` envelope | `feature_key=vanity_subdomain`, `org_slug` | ## Output diff --git a/apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.handler.ts b/apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.handler.ts index d1a937f196..bf1b76a774 100644 --- a/apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.handler.ts +++ b/apps/cli/src/commands/vanity-subdomains/check-availability/check-availability.handler.ts @@ -2,7 +2,6 @@ import { Effect, Option } from "effect"; import { CommandPlatformApi } from "../../../auth/command-platform-api.service.ts"; import { resolveProjectTarget } from "../../../command-internal/target/resolve-project-target.ts"; -import { gateResponse, suggestUpgrade } from "../../../command-internal/upgrade-suggest.ts"; import { LinkedProjectCache } from "../../../telemetry/linked-project-cache.service.ts"; import { TelemetryState } from "../../../telemetry/telemetry-state.service.ts"; import { OutputFlag } from "../../../command-internal/global-flags.ts"; @@ -64,29 +63,7 @@ export const vanitySubdomainsCheckAvailability = Effect.fn("vanity-subdomains.ch }) .pipe( Effect.tapError(() => checking?.fail() ?? Effect.void), - Effect.catch((cause) => - mapCheckError(cause).pipe( - Effect.catchTag("VanitySubdomainsCheckUnexpectedStatusError", (mapped) => - Effect.gen(function* () { - // Unlike `activate`, this command suppresses the upgrade-suggestion - // analytics event. - const upgradeSuggested = yield* suggestUpgrade({ - projectRef: ref, - statusCode: mapped.status, - response: gateResponse(cause), - trackAnalytics: false, - }); - return yield* new VanitySubdomainsCheckUnexpectedStatusError({ - status: mapped.status, - body: mapped.body, - message: mapped.message, - upgradeSuggested, - entitlement: mapped.entitlement, - }); - }), - ), - ), - ), + Effect.catch(mapCheckError), ); yield* checking?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/vanity-subdomains/get/SIDE_EFFECTS.md b/apps/cli/src/commands/vanity-subdomains/get/SIDE_EFFECTS.md index 2d1c761edc..24a1398a2c 100644 --- a/apps/cli/src/commands/vanity-subdomains/get/SIDE_EFFECTS.md +++ b/apps/cli/src/commands/vanity-subdomains/get/SIDE_EFFECTS.md @@ -48,10 +48,10 @@ Target: hosted, no consent — see [Command target](../../../../docs/command-tar ## Telemetry Events Fired -| Event | When | Notable properties / groups | -| ----------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | -| `cli_upgrade_suggested` | 4xx carrying the `entitlement_required` envelope (gate open, so the request was made) | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`); envelope-only, no entitlements fallback | +| Event | When | Notable properties / groups | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| `cli_command_executed` | post-run, success or failure (via wrapper); not fired when the `--experimental` gate is closed | `exit_code`, `duration_ms`, `flags` | +| `cli_upgrade_suggested` | post-run (via wrapper), before `cli_command_executed`, on a 4xx carrying the `entitlement_required` envelope (gate open, so the request was made) | `feature_key` (from the envelope), `org_slug` (parsed from `upgrade_url`); envelope-only, no entitlements fallback | ## Output diff --git a/apps/cli/src/commands/vanity-subdomains/get/get.handler.ts b/apps/cli/src/commands/vanity-subdomains/get/get.handler.ts index f6fd34b390..ca6ff999aa 100644 --- a/apps/cli/src/commands/vanity-subdomains/get/get.handler.ts +++ b/apps/cli/src/commands/vanity-subdomains/get/get.handler.ts @@ -15,7 +15,6 @@ import { shapeStruct, } from "../../../command-internal/struct-output.encoders.ts"; import { mapHttpError } from "../../../command-internal/http-errors.ts"; -import { gateMapError } from "../../../command-internal/upgrade-suggest.ts"; import { VanitySubdomainsGetNetworkError, VanitySubdomainsGetUnexpectedStatusError, @@ -52,7 +51,7 @@ export const vanitySubdomainsGet = Effect.fn("vanity-subdomains.get")(function* output.format === "text" ? yield* output.task("Getting vanity subdomain...") : undefined; const response = yield* api.v1.getVanitySubdomainConfig({ ref }).pipe( Effect.tapError(() => fetching?.fail() ?? Effect.void), - Effect.catch(gateMapError({ projectRef: ref }, mapGetError)), + Effect.catch(mapGetError), ); yield* fetching?.clear ?? Effect.void; diff --git a/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.errors.ts b/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.errors.ts index 9f42ef2276..1b5bbe2858 100644 --- a/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.errors.ts +++ b/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.errors.ts @@ -69,14 +69,10 @@ export class VanitySubdomainsCheckUnexpectedStatusError extends Data.TaggedError readonly status: number; readonly body: string; readonly message: string; - readonly upgradeSuggested?: boolean; readonly entitlement?: PlanGateEntitlement; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { - return statusCodeActionability(this.status, { - upgradeSuggested: this.upgradeSuggested, - notFoundIsInvalidInput: true, - }); + return statusCodeActionability(this.status, { notFoundIsInvalidInput: true }); } } @@ -99,14 +95,10 @@ export class VanitySubdomainsActivateUnexpectedStatusError extends Data.TaggedEr readonly status: number; readonly body: string; readonly message: string; - readonly upgradeSuggested?: boolean; readonly entitlement?: PlanGateEntitlement; }> { get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { - return statusCodeActionability(this.status, { - upgradeSuggested: this.upgradeSuggested, - notFoundIsInvalidInput: true, - }); + return statusCodeActionability(this.status, { notFoundIsInvalidInput: true }); } } diff --git a/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.integration.test.ts b/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.integration.test.ts index 1c5717df04..a43f1619d1 100644 --- a/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.integration.test.ts +++ b/apps/cli/src/commands/vanity-subdomains/vanity-subdomains.integration.test.ts @@ -173,7 +173,7 @@ describe("vanity-subdomains get", () => { }).pipe(Effect.provide(layer)); }); - it.effect("suggests upgrade from entitlement_required envelope on 400", () => { + it.effect("fails with the entitlement_required envelope's entitlement on 400", () => { const out = mockOutput({ format: "text" }); const analytics = mockAnalytics(); const api = mockCommandPlatformApi({ @@ -192,20 +192,19 @@ describe("vanity-subdomains get", () => { const layer = runtimeWith({ out, api, analytics }); return Effect.gen(function* () { - const exit = yield* Effect.exit( + const error = yield* Effect.flip( vanitySubdomainsGet({ remote: Option.none(), projectRef: Option.none() }), ); - expect(Exit.isFailure(exit)).toBe(true); + expect(error).toMatchObject({ + entitlement: { + feature: "vanity_subdomain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); expect(api.requests).toHaveLength(1); assertPermissionDrift({ command: "vanity-subdomains get", requests: api.requests }); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "vanity_subdomain", org_slug: "env-org" }, - }, - ]); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); }).pipe(Effect.provide(layer)); }); @@ -493,23 +492,27 @@ describe("vanity-subdomains check-availability", () => { }).pipe(Effect.provide(layer)); }); - it.effect("suggests upgrade for gated checks without firing analytics", () => { + it.effect("fails gated checks with the envelope's entitlement", () => { const out = mockOutput({ format: "text" }); const api = mockCommandPlatformApi({ response: { status: 400, body: VANITY_GATE_ENVELOPE } }); const analytics = mockAnalytics(); const layer = runtimeWith({ out, api, analytics }); return Effect.gen(function* () { - const exit = yield* Effect.exit( + const error = yield* Effect.flip( vanitySubdomainsCheckAvailability({ remote: Option.none(), projectRef: Option.none(), desiredSubdomain: Option.some("example.com"), }), ); - expect(Exit.isFailure(exit)).toBe(true); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); + expect(error).toMatchObject({ + entitlement: { + feature: "vanity_subdomain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); + expect(out.stderrText).not.toContain("Upgrade your plan:"); expect(analytics.captured).toHaveLength(0); expect(requestLines(api)).toEqual([ `POST ${API_URL}/v1/projects/${VALID_REF}/vanity-subdomain/check-availability`, @@ -758,29 +761,28 @@ describe("vanity-subdomains activate", () => { }).pipe(Effect.provide(layer)); }); - it.effect("suggests upgrade and fires analytics for gated activation", () => { + it.effect("fails gated activation with the envelope's entitlement", () => { const out = mockOutput({ format: "text" }); const api = mockCommandPlatformApi({ response: { status: 400, body: VANITY_GATE_ENVELOPE } }); const analytics = mockAnalytics(); const layer = runtimeWith({ out, api, analytics }); return Effect.gen(function* () { - const exit = yield* Effect.exit( + const error = yield* Effect.flip( vanitySubdomainsActivate({ remote: Option.none(), projectRef: Option.none(), desiredSubdomain: Option.some("example.com"), }), ); - expect(Exit.isFailure(exit)).toBe(true); - expect(out.stderrText).toContain("Upgrade your plan:"); - expect(out.stderrText).toContain("/org/env-org/billing"); - expect(analytics.captured).toEqual([ - { - event: "cli_upgrade_suggested", - properties: { feature_key: "vanity_subdomain", org_slug: "env-org" }, + expect(error).toMatchObject({ + entitlement: { + feature: "vanity_subdomain", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", }, - ]); + }); + expect(out.stderrText).not.toContain("Upgrade your plan:"); + expect(analytics.captured).toHaveLength(0); expect(requestLines(api)).toEqual([ `POST ${API_URL}/v1/projects/${VALID_REF}/vanity-subdomain/activate`, ]); diff --git a/apps/cli/src/config/cli-config-codec-schemas.ts b/apps/cli/src/config/cli-config-codec-schemas.ts index 2b4d7908a3..19f6ec70bf 100644 --- a/apps/cli/src/config/cli-config-codec-schemas.ts +++ b/apps/cli/src/config/cli-config-codec-schemas.ts @@ -21,13 +21,17 @@ const parsed = (parse: (input: E) => T | undefined) => : Effect.succeed(value); }); -const parseUintUpTo = (max: bigint) => (raw: string) => { - const value = parseBase0Bigint(raw); - return value === undefined || value > max ? undefined : Number(value); -}; +const parseUintUpTo = + (max: bigint, min = 0n) => + (raw: string) => { + const value = parseBase0Bigint(raw); + return value === undefined || value < min || value > max ? undefined : Number(value); + }; -const integerUpTo = (max: number) => (value: number) => - Number.isInteger(value) && value >= 0 && value <= max ? value : undefined; +const integerUpTo = + (max: number, min = 0) => + (value: number) => + Number.isInteger(value) && value >= min && value <= max ? value : undefined; const parsePort = (raw: string) => /^0[0-9_]/.test(raw) ? undefined : parseUintUpTo(BigInt(MAX_PORT))(raw); @@ -40,10 +44,10 @@ const integerFromString = (parse: (raw: string) => number | undefined) => }), ); -const integerFromNumber = (max: number) => +const integerFromNumber = (max: number, min: number) => Schema.Finite.pipe( Schema.decodeTo(Schema.Finite, { - decode: parsed(integerUpTo(max)), + decode: parsed(integerUpTo(max, min)), encode: SchemaGetter.passthrough(), }), ); @@ -51,11 +55,12 @@ const integerFromNumber = (max: number) => const integerSchemas = ( parse: (raw: string) => number | undefined, max: number, + min = 0, ): CliConfigCodecSchemas => { const fromString = integerFromString(parse); return { fromString, - fromDocument: Schema.Union([fromString, integerFromNumber(max)]), + fromDocument: Schema.Union([fromString, integerFromNumber(max, min)]), }; }; @@ -81,6 +86,12 @@ export const boolSchemas: CliConfigCodecSchemas = { export const uintSchemas = integerSchemas(parseUintUpTo(MAX_UINT), Number.MAX_SAFE_INTEGER); +export const positiveIntSchemas = integerSchemas( + parseUintUpTo(MAX_UINT, 1n), + Number.MAX_SAFE_INTEGER, + 1, +); + export const portSchemas = integerSchemas(parsePort, MAX_PORT); export const stringSchemas: CliConfigCodecSchemas = { diff --git a/apps/cli/src/config/cli-config-failure-key.ts b/apps/cli/src/config/cli-config-failure-key.ts index 97b169e43f..7bbf903467 100644 --- a/apps/cli/src/config/cli-config-failure-key.ts +++ b/apps/cli/src/config/cli-config-failure-key.ts @@ -38,13 +38,11 @@ const isRemovedKeyError = taggedAs("CliConfigRemovedKe const isParseError = taggedAs("CliConfigParseError"); const isValueError = taggedAs("CliConfigValueError"); -const removedKeyPath = (displayKey: string): string | undefined => { - const path = displayKey.replaceAll(/[[\]]/g, ""); - return REMOVED_KEY_PATHS.find( +const removedKeyPath = (path: string): string | undefined => + REMOVED_KEY_PATHS.find( (canonical) => path === canonical || (path.startsWith("remotes.") && path.endsWith(`.${canonical}`)), ); -}; const knownPrefix = (segments: ReadonlyArray): string | undefined => { for (let length = segments.length; length > 0; length--) { diff --git a/apps/cli/src/config/cli-config-failure-key.unit.test.ts b/apps/cli/src/config/cli-config-failure-key.unit.test.ts index 0c916099e1..69c5390f0a 100644 --- a/apps/cli/src/config/cli-config-failure-key.unit.test.ts +++ b/apps/cli/src/config/cli-config-failure-key.unit.test.ts @@ -95,11 +95,11 @@ describe("cliConfigFailureKey for a removed key", () => { new CliConfigRemovedKeyError({ path: "supabase/config.toml", format: "toml", - removedKeys: keys.map((key) => ({ key, replacement: "[replacement]" })), + removedKeys: keys.map((key) => ({ key, replacement: "replacement" })), }); - expect(cliConfigFailureKey(removedKeys(`[${SECRET}]`, "[inbucket]"))).toBe("inbucket"); - expect(cliConfigFailureKey(removedKeys(`[${SECRET}]`))).toBeUndefined(); + expect(cliConfigFailureKey(removedKeys(SECRET, "inbucket"))).toBe("inbucket"); + expect(cliConfigFailureKey(removedKeys(SECRET))).toBeUndefined(); }); }); diff --git a/apps/cli/src/config/cli-config-key-annotations.ts b/apps/cli/src/config/cli-config-key-annotations.ts index 0562dbc514..a8ac6fa9f0 100644 --- a/apps/cli/src/config/cli-config-key-annotations.ts +++ b/apps/cli/src/config/cli-config-key-annotations.ts @@ -12,6 +12,7 @@ import { globListCodec, boolCodec, literalCodec, + positiveIntCodec, stringCodec, type CliConfigCodec, type CliConfigKeyContext, @@ -44,6 +45,7 @@ export const CLI_CONFIG_CODEC_OVERRIDES: Readonly { ).toBe('Invalid auth.jwt_expiry: "9007199254740993" is not a non-negative integer.'); }); + it("rejects a zero api.db_pool at the codec, naming its source", () => { + const dbPool = cliConfigRegistry.keyAt("api.db_pool"); + if (dbPool === undefined) throw new Error("api.db_pool is not registered"); + + expect(failureOf(dbPool, { shell: { SUPABASE_API_DB_POOL: "0" } }).message).toBe( + 'Invalid SUPABASE_API_DB_POOL="0" (sets api.db_pool): expected a positive integer.', + ); + expect(failureOf(dbPool, { config: { "api.db_pool": 0 } }).message).toBe( + 'Invalid api.db_pool: "0" is not a positive integer.', + ); + expect(valueOf(dbPool, { shell: { SUPABASE_API_DB_POOL: "1" } }).value).toEqual(Option.some(1)); + }); + it("lists the allowed values of an enum", () => { const backend = requiredCliConfigKey({ path: "analytics.backend", diff --git a/apps/cli/src/config/cli-config-values.integration.test.ts b/apps/cli/src/config/cli-config-values.integration.test.ts index 18c152e1d4..b759671b59 100644 --- a/apps/cli/src/config/cli-config-values.integration.test.ts +++ b/apps/cli/src/config/cli-config-values.integration.test.ts @@ -2251,8 +2251,8 @@ enabled = false expect(failure).toMatchObject({ _tag: "CliConfigRemovedKeyError", removedKeys: [ - { key: "[inbucket]", replacement: "[local_smtp]" }, - { key: "[auth.external.slack]", replacement: "[auth.external.slack_oidc]" }, + { key: "inbucket", replacement: "local_smtp" }, + { key: "auth.external.slack", replacement: "auth.external.slack_oidc" }, ], }); expect(loaded.materialized.config.local_smtp.enabled).toBe(true); @@ -2423,7 +2423,7 @@ describe("CliConfigValues failure telemetry", () => { const sink = { record: (values: CommandTelemetryAttributeValues) => Effect.sync(() => { - records.push(values); + if ("config_key" in values) records.push(values); attributes = { ...attributes, ...values }; }), }; @@ -2537,3 +2537,73 @@ describe("CliConfigValues failure telemetry", () => { ).pipe(Effect.provide(BunServices.layer), (effect) => withShell({}, effect), Effect.scoped), ); }); + +describe("CliConfigValues config format telemetry", () => { + const loadRecordingFormat = (root: string) => + Effect.gen(function* () { + let format: CommandTelemetryAttributeValues["config_format"]; + const exit = yield* CliConfigValues.use((values) => + values.load({ workdir: root, projectRef: Option.none() }), + ).pipe( + Effect.provide(configValuesLayer()), + Effect.provideService(CommandTelemetryAttributes, { + record: (values) => + Effect.sync(() => { + if ("config_format" in values) format = values.config_format; + }), + }), + Effect.exit, + ); + return { exit, format }; + }); + + const projectWith = (name: string, content: string) => + Effect.gen(function* () { + const root = yield* project(""); + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + yield* fs.remove(path.join(root, "supabase", "config.toml")); + yield* fs.writeFileString(path.join(root, "supabase", name), content); + return root; + }); + + it.live.each([ + { name: "config.toml", content: "[db]\nport = 54400\n", expected: "toml" }, + { name: "config.json", content: '{"db": {"port": 54400}}', expected: "json" }, + { + name: "config.jsonc", + content: '{\n // port\n "db": { "port": 54400, },\n}\n', + expected: "jsonc", + }, + ])("records $expected for a project with $name", ({ name, content, expected }) => + Effect.gen(function* () { + const root = yield* projectWith(name, content); + + const { exit, format } = yield* loadRecordingFormat(root); + + expect(Exit.isSuccess(exit)).toBe(true); + expect(format).toBe(expected); + }).pipe(Effect.provide(BunServices.layer), (effect) => withShell({}, effect), Effect.scoped), + ); + + it.live("records the format of a config file that fails to parse", () => + Effect.gen(function* () { + const root = yield* projectWith("config.jsonc", '{ "db": { "port": '); + + const { exit, format } = yield* loadRecordingFormat(root); + + expect(Exit.isFailure(exit)).toBe(true); + expect(format).toBe("jsonc"); + }).pipe(Effect.provide(BunServices.layer), (effect) => withShell({}, effect), Effect.scoped), + ); + + it.live("records no format when the project has no config file", () => + Effect.gen(function* () { + const root = yield* projectWith("unrelated.txt", ""); + + const { format } = yield* loadRecordingFormat(root); + + expect(format).toBeUndefined(); + }).pipe(Effect.provide(BunServices.layer), (effect) => withShell({}, effect), Effect.scoped), + ); +}); diff --git a/apps/cli/src/config/cli-config-values.layer.ts b/apps/cli/src/config/cli-config-values.layer.ts index ffd102a868..e064d27f71 100644 --- a/apps/cli/src/config/cli-config-values.layer.ts +++ b/apps/cli/src/config/cli-config-values.layer.ts @@ -28,7 +28,7 @@ import { CliConfigLoadError } from "../shared/config/cli-config-load.errors.ts"; import { DebugLogger } from "../shared/output/debug-logger.service.ts"; import { escapeControlCharacters } from "../shared/output/escape-control-characters.ts"; import { Output } from "../shared/output/output.service.ts"; -import { PropConfigKey } from "../shared/telemetry/event-catalog.ts"; +import { PropConfigFormat, PropConfigKey } from "../shared/telemetry/event-catalog.ts"; import { recordCommandTelemetry } from "../telemetry/command-telemetry-attributes.ts"; import { CLI_CONFIG_FAMILIES, CLI_CONFIG_REMOVED_ENV_NAMES } from "./cli-config-key-annotations.ts"; import { @@ -224,6 +224,18 @@ const materializedWrite = ( return key.normalize === undefined ? declared : key.toDocument(picked.value); }; +const cliConfigFileFormat = (filePath: string) => + filePath.endsWith(".jsonc") ? "jsonc" : filePath.endsWith(".json") ? "json" : "toml"; + +const recordConfigFormat = (filePath: string | undefined) => + filePath === undefined + ? Effect.void + : recordCommandTelemetry({ [PropConfigFormat]: cliConfigFileFormat(filePath) }); + +const failedConfigFilePath = ( + error: Effect.Error>, +): string | undefined => ("path" in error ? error.path : undefined); + export const cliConfigValuesLayer = Layer.effect( CliConfigValues, Effect.gen(function* () { @@ -280,7 +292,10 @@ export const cliConfigValuesLayer = Layer.effect( const parsed = target.ignoreConfigFile ? null - : yield* Cache.get(parsedDocuments, target.workdir); + : yield* Cache.get(parsedDocuments, target.workdir).pipe( + Effect.tapError((error) => recordConfigFormat(failedConfigFilePath(error))), + ); + yield* recordConfigFormat(parsed?.path); for (const deprecatedPath of parsed?.deprecatedPaths ?? []) { yield* printOnce(deprecatedKeyLine(deprecatedPath)); } diff --git a/apps/cli/src/shared/cli/run.ts b/apps/cli/src/shared/cli/run.ts index b7f61b0fea..74a648b875 100644 --- a/apps/cli/src/shared/cli/run.ts +++ b/apps/cli/src/shared/cli/run.ts @@ -392,12 +392,15 @@ export function shouldUseGlobalSignalInterrupt(args: ReadonlyArray): boo ); } -function formatterLayerFor( +function suggestionContextFor( rootCommand: Command.Command.Any, args: ReadonlyArray, - format: OutputFormat, -) { - const context = { rootCommand, args }; + stackRootCommand: Command.Command.Any | undefined, +): CliErrorSuggestionContext { + return { rootCommand, args, ...(stackRootCommand ? { stackRootCommand } : {}) }; +} + +function formatterLayerFor(context: CliErrorSuggestionContext, format: OutputFormat) { return format === "json" || format === "stream-json" ? CliOutput.layer(jsonCliOutputFormatter(context)) : CliOutput.layer(textCliOutputFormatter(context)); @@ -612,6 +615,8 @@ export interface RunCliOptions { readonly beforeParse?: Effect.Effect; /** The selected root's agent default, applied to failures `runCli` renders itself. */ readonly agentDefaultOutputFormat: OutputFormat; + /** The root the stack opt-in would select, so a rejected stack-only flag can name the opt-in. */ + readonly stackRootCommand?: Command.Command.Any; readonly analyticsLayer: Layer.Layer< Analytics, Config.ConfigError | PlatformError.PlatformError, @@ -665,9 +670,10 @@ export function cliProgramFor< ), ); const commandProgram = options.beforeParse ?? Effect.void; - const commandLayer = formatterLayerFor(rootCommand, args, outputFormat).pipe( - Layer.provideMerge(options.analyticsLayer), - ); + const commandLayer = formatterLayerFor( + suggestionContextFor(rootCommand, args, options.stackRootCommand), + outputFormat, + ).pipe(Layer.provideMerge(options.analyticsLayer)); const cliProgramLayer = telemetryRuntimeLayer.pipe( Layer.provideMerge(cliSettingsLayerFor(runtimeLayer)), Layer.provideMerge(cliProjectHomeLayerFor(runtimeLayer)), @@ -723,7 +729,7 @@ export const runCli = Effect.fnUntraced(function* < // Same shape `formatterLayerFor` builds below, so `normalizeCause`'s fallback path can reuse // `formatCliErrorsForDisplay` and surface the same subcommand-flag hint the formatters would. - const suggestionContext = { rootCommand, args }; + const suggestionContext = suggestionContextFor(rootCommand, args, options.stackRootCommand); const useGlobalSignalInterrupt = shouldUseGlobalSignalInterrupt(args); const outputFormat = yield* Effect.gen(function* () { const aiTool = yield* AiTool; diff --git a/apps/cli/src/shared/cli/subcommand-flag-suggestions.ts b/apps/cli/src/shared/cli/subcommand-flag-suggestions.ts index 83c4c6455a..2670340179 100644 --- a/apps/cli/src/shared/cli/subcommand-flag-suggestions.ts +++ b/apps/cli/src/shared/cli/subcommand-flag-suggestions.ts @@ -10,6 +10,8 @@ import { formatInvalidValueMessage } from "./invalid-value-message.ts"; export interface CliErrorSuggestionContext { readonly rootCommand: Command.Command.Any; readonly args: ReadonlyArray; + /** The root the stack opt-in would select; set only while the legacy backend is active. */ + readonly stackRootCommand?: Command.Command.Any; } export interface FormattedCliError { @@ -319,6 +321,19 @@ export function isRemoteFlagMisuse( ); } +/** Names the opt-in when the stack backend's version of the command accepts the rejected flag. */ +function buildStackOptInHint( + error: CliError.UnrecognizedOption, + context: CliErrorSuggestionContext, +): string | undefined { + if (!context.stackRootCommand || !error.command) return undefined; + const command = findCommand(context.stackRootCommand, error.command.slice(1)); + if (!command || !commandFlagsFor(command).some((flag) => flagMatchesOption(flag, error.option))) { + return undefined; + } + return `${optionToken(error.option)} needs the stack backend. Set SUPABASE_EXPERIMENTAL_STACK=1, or set stack = true under [experimental] in your project config and leave SUPABASE_EXPERIMENTAL_STACK unset.`; +} + function buildSubcommandFlagHint( error: CliError.UnrecognizedOption, context: CliErrorSuggestionContext, @@ -386,6 +401,17 @@ export function formatCliErrorsForDisplay( }); continue; } + const stackHint = buildStackOptInHint(error, context); + if (stackHint) { + changed = true; + formatted.push({ + _tag: error._tag, + message: `${error.message}\n\n Hint: ${stackHint}`, + source: error, + changed: true, + }); + continue; + } } if ( diff --git a/apps/cli/src/shared/cli/value-consuming-flags.ts b/apps/cli/src/shared/cli/value-consuming-flags.ts index 98524174dc..5b82208bff 100644 --- a/apps/cli/src/shared/cli/value-consuming-flags.ts +++ b/apps/cli/src/shared/cli/value-consuming-flags.ts @@ -74,6 +74,8 @@ export const VALUE_CONSUMING_LONG_FLAGS = new Set([ "role", "runtime", "search", + "secrets-scope", + "secrets-scope:custom", "size", "source", "sql", diff --git a/apps/cli/src/shared/compute/compute-api.ts b/apps/cli/src/shared/compute/compute-api.ts index 7ac9ea2100..f35f30eaf5 100644 --- a/apps/cli/src/shared/compute/compute-api.ts +++ b/apps/cli/src/shared/compute/compute-api.ts @@ -60,6 +60,7 @@ export interface ComputeRecord { readonly runtime?: string; readonly size: string; readonly exposure: string; + readonly secrets_scope?: ComputeResourceData["attributes"]["spec"]["secrets_scope"]; readonly instances: number; readonly backend?: string; }; @@ -85,14 +86,34 @@ export interface ComputeUploadSlot { readonly expiresAt: string; } +const COMPUTE_SECRETS_SCOPE = ["all", "supabase", "none"] as const; +type ComputeSecretsScope = (typeof COMPUTE_SECRETS_SCOPE)[number]; + /** The `spec` a deploy sends. Mirrors the API's own field names exactly. */ export interface ComputeDeploySpec { readonly runtime?: string; readonly size: string; readonly exposure: string; + readonly secrets_scope?: + | ComputeSecretsScope + | { + readonly secret_name: string; + }[]; readonly instances: number; } +export function parseComputeSecretsScopeToAPIFormat( + value: string | string[], +): ComputeDeploySpec["secrets_scope"] | undefined { + if (typeof value === "string" && COMPUTE_SECRETS_SCOPE.includes(value as ComputeSecretsScope)) { + return value as ComputeSecretsScope; + } + + if (Array.isArray(value) && value.every((i) => typeof i === "string")) { + return value.map((secret_name) => ({ secret_name })); + } +} + function toComputeRecord(data: ComputeResourceData): ComputeRecord { return { name: data.id, diff --git a/apps/cli/src/shared/compute/compute-config.ts b/apps/cli/src/shared/compute/compute-config.ts index 6924127004..7c0337e608 100644 --- a/apps/cli/src/shared/compute/compute-config.ts +++ b/apps/cli/src/shared/compute/compute-config.ts @@ -31,6 +31,7 @@ export interface ComputeEntry { readonly runtime?: string; readonly size?: string; readonly exposure?: string; + readonly secrets_scope?: string | ReadonlyArray; readonly instances?: number; readonly source?: string; readonly exclude?: ReadonlyArray; @@ -141,6 +142,9 @@ export function readComputeSection(compute: unknown): ComputeSection { // Left as written, empty included: `push` names the accepted values, and dropping an // unrecognized one here would silently deploy at the default exposure instead. exposure: recordedStringOrUndefined(value["exposure"]), + secrets_scope: + recordedStringOrUndefined(value["secrets_scope"]) ?? + patternsOrUndefined(value["secrets_scope"]), instances: instanceCountOrUndefined(value["instances"]), source: stringOrUndefined(value["source"]), exclude: patternsOrUndefined(value["exclude"]), diff --git a/apps/cli/src/shared/compute/compute-runtimes.ts b/apps/cli/src/shared/compute/compute-runtimes.ts index 6500b1d6e7..6866f89777 100644 --- a/apps/cli/src/shared/compute/compute-runtimes.ts +++ b/apps/cli/src/shared/compute/compute-runtimes.ts @@ -130,6 +130,62 @@ export function parseComputeExposure(value: string): ComputeExposure | undefined return isComputeExposure(canonical) ? canonical : undefined; } +/** + */ +export const COMPUTE_SECRETS_SCOPE = ["all", "supabase", "none"] as const; + +export const COMPUTE_SECRETS_SCOPE_ENUM = [...COMPUTE_SECRETS_SCOPE, "custom"] as const; + +export type ComputeSecretsScopeEnum = (typeof COMPUTE_SECRETS_SCOPE_ENUM)[number]; + +export type ComputeSecretsScope = (typeof COMPUTE_SECRETS_SCOPE)[number] | string[]; + +/** + */ +export const DEFAULT_COMPUTE_SECRETS_SCOPE: ComputeSecretsScope = "all"; + +/** */ +export const COMPUTE_SECRETS_SCOPE_DESCRIPTIONS: Record = { + all: "Gives access to all defined secrets", + supabase: "Exposes only the SUPABASE_* defaults", + none: "Hides all secrets", + custom: "Exposes only the specified secret names", +}; + +function isComputeSecretScope(value: string | string[]): value is ComputeSecretsScope { + if (typeof value === "string") { + return COMPUTE_SECRETS_SCOPE.some((scope) => scope === value); + } + + return Array.isArray(value) && value.every((secretName) => typeof secretName === "string"); +} + +/** As {@link parseComputeRuntime}, for secrets_scope. */ +export function parseComputeSecretsScope( + value: string | string[], +): ComputeSecretsScope | undefined { + const canonical = typeof value === "string" ? value.trim().toLowerCase() : value; + return isComputeSecretScope(canonical) ? canonical : undefined; +} + +export function parseSecretsScopeCustom(secretsNames: string) { + if (typeof secretsNames !== "string") { + return []; + } + + const secretsNamesArray = secretsNames + .split(",") + .map((name) => name.trim()) + .filter((name) => !!name); + + // Apply Set to create a distinct array with unique secret names + return [...new Set(secretsNamesArray)]; +} + +export function formatSecretsScope(secretsScope: string | string[]) { + return typeof secretsScope === "string" ? secretsScope : secretsScope.join(", "); +} + const VCPU_FOR_SIZE: Record = { "2gb": 1, "4gb": 2 }; /** The vCPU count that comes with `size` — not independently choosable. */ diff --git a/apps/cli/src/shared/compute/compute.errors.ts b/apps/cli/src/shared/compute/compute.errors.ts index c47fa65215..412c127903 100644 --- a/apps/cli/src/shared/compute/compute.errors.ts +++ b/apps/cli/src/shared/compute/compute.errors.ts @@ -114,6 +114,17 @@ export class UnknownComputeExposureError extends Data.TaggedError("UnknownComput } } +export class UnknownComputeSecretsScopeError extends Data.TaggedError( + "UnknownComputeSecretsScopeError", +)<{ + readonly detail: string; + readonly suggestion: string; +}> { + get [ErrorActionabilityId](): CliErrorActionabilityDeclaration { + return actionability.provideFlags; + } +} + export class MissingComputeExposureError extends Data.TaggedError("MissingComputeExposureError")<{ readonly detail: string; readonly suggestion: string; diff --git a/apps/cli/src/shared/init/project-init.templates.ts b/apps/cli/src/shared/init/project-init.templates.ts index a11639e381..287a362605 100644 --- a/apps/cli/src/shared/init/project-init.templates.ts +++ b/apps/cli/src/shared/init/project-init.templates.ts @@ -21,6 +21,9 @@ extra_search_path = ["public", "extensions"] # The maximum number of rows returned from a view, table, or stored procedure. Limits payload size # for accidental or malicious requests. max_rows = 1000 +# The maximum number of connections in the local PostgREST database pool. Left unset, the default +# pool size is unchanged. +# db_pool = 10 # Controls whether new tables, views, sequences and functions created in the \`public\` schema by # \`postgres\` are reachable through the Data API roles (\`anon\`, \`authenticated\`, \`service_role\`) # without explicit GRANTs, matching the cloud default. Set to \`false\` to require explicit GRANTs @@ -474,6 +477,13 @@ export const VSCODE_SETTINGS_TEMPLATE = `{ } `; +export const VSCODE_SCHEMA_TRUST_TEMPLATE = `{ + "json.schemaDownload.trustedDomains": { + "https://supabase.com/schemas/": true + } +} +`; + export const INTELLIJ_DENO_TEMPLATE = ` diff --git a/apps/cli/src/shared/init/project-init.templates.unit.test.ts b/apps/cli/src/shared/init/project-init.templates.unit.test.ts index d846e5eb6f..b411c451a2 100644 --- a/apps/cli/src/shared/init/project-init.templates.unit.test.ts +++ b/apps/cli/src/shared/init/project-init.templates.unit.test.ts @@ -16,6 +16,7 @@ import { INIT_GITIGNORE_TEMPLATE, INTELLIJ_DENO_TEMPLATE, VSCODE_EXTENSIONS_TEMPLATE, + VSCODE_SCHEMA_TRUST_TEMPLATE, VSCODE_SETTINGS_TEMPLATE, renderCliConfigTemplate, } from "./project-init.templates.ts"; @@ -110,6 +111,12 @@ const NATIVE_REQUIRE_CURRENT_PASSWORD = `secure_password_change = false # they signed in with a one-time password, magic link, or recovery link. # require_current_password = true`; +/* Only the native template documents `db_pool`. */ +const NATIVE_DB_POOL = `max_rows = 1000 +# The maximum number of connections in the local PostgREST database pool. Left unset, the default +# pool size is unchanged. +# db_pool = 10`; + const renderExpectedNativeEject = renderExpectedInitOutput.pipe( Effect.map((eject) => eject @@ -122,6 +129,7 @@ const renderExpectedNativeEject = renderExpectedInitOutput.pipe( .replace(SCAFFOLD_EMAIL_SIGNUP_COMMENT, NATIVE_EMAIL_SIGNUP_COMMENT) .replace(SCAFFOLD_SMS_SIGNUP_COMMENT, NATIVE_SMS_SIGNUP_COMMENT) .replace("secure_password_change = false", NATIVE_REQUIRE_CURRENT_PASSWORD) + .replace("max_rows = 1000", NATIVE_DB_POOL) .replace("rows returns from", "rows returned from") .replace("(SIWS, EIP-4361)", "(SIWS)") .replace( @@ -267,8 +275,11 @@ describe("project init templates", () => { }).pipe(Effect.provide(BunServices.layer)), ); - it("trusts the hosted schema URLs in the VS Code settings", () => { - const settings: unknown = JSON.parse(VSCODE_SETTINGS_TEMPLATE); + it.each([ + ["settings", VSCODE_SETTINGS_TEMPLATE], + ["schema trust", VSCODE_SCHEMA_TRUST_TEMPLATE], + ])("trusts the hosted schema URLs in the VS Code %s template", (_name, template) => { + const settings: unknown = JSON.parse(template); const trustedDomains = Predicate.isObject(settings) ? settings["json.schemaDownload.trustedDomains"] : undefined; diff --git a/apps/cli/src/shared/init/project-init.ts b/apps/cli/src/shared/init/project-init.ts index 72a440c99d..6d9cf6eb1a 100644 --- a/apps/cli/src/shared/init/project-init.ts +++ b/apps/cli/src/shared/init/project-init.ts @@ -1,5 +1,5 @@ import { Effect, FileSystem, Path, Predicate, Schema } from "effect"; -import { parseJsonc } from "@supabase/config/internal"; +import { parseJsonc, updateJsonDocument } from "@supabase/config/internal"; import { promptYesNo } from "../../command-internal/prompt-yes-no.ts"; import { sanitizeProjectId } from "../config/project-id.ts"; import { Output } from "../output/output.service.ts"; @@ -8,6 +8,7 @@ import { INIT_GITIGNORE_TEMPLATE, INTELLIJ_DENO_TEMPLATE, VSCODE_EXTENSIONS_TEMPLATE, + VSCODE_SCHEMA_TRUST_TEMPLATE, VSCODE_SETTINGS_TEMPLATE, renderCliConfigTemplate, } from "./project-init.templates.ts"; @@ -83,7 +84,8 @@ function mergeJsonObjects( return merged; } -function updateJsonFile(pathname: string, template: string) { +/** Merges `template` into the JSON(C) file at `pathname`, keeping existing comments unless a minimal edit is impossible; writes the template when the file is absent or empty. */ +function mergeJsonSettingsFile(pathname: string, template: string) { return Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; @@ -102,10 +104,62 @@ function updateJsonFile(pathname: string, template: string) { yield* parseJsonObject(pathname, existing), yield* parseJsonObject(pathname, template), ); - yield* writeJsonFile(pathname, merged); + const edited = updateJsonDocument(existing, merged); + if (edited === undefined) { + yield* writeJsonFile(pathname, merged); + return; + } + yield* fs.writeFileString(pathname, edited, { mode: INIT_FILE_MODE }); }); } +const SCHEMA_TRUST_KEY = "json.schemaDownload.trustedDomains"; +const SCHEMA_TRUST_DOMAIN = "https://supabase.com/schemas/"; + +/** Adds the hosted schema domain to an existing `.vscode/settings.json` unless it already lists it, + * failing rather than dropping the file's comments; resolves to whether the file changes (or would, + * with `dryRun`). */ +export const trustSupabaseSchemaDomain = Effect.fnUntraced(function* ( + cwd: string, + options?: { readonly dryRun?: boolean }, +) { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + + const settingsPath = path.join(cwd, ".vscode", "settings.json"); + if (!(yield* fs.exists(settingsPath))) { + return false; + } + const before = yield* fs.readFileString(settingsPath); + let after = VSCODE_SCHEMA_TRUST_TEMPLATE; + if (before.trim().length > 0) { + const existing = yield* parseJsonObject(settingsPath, before); + const trusted = existing[SCHEMA_TRUST_KEY]; + if (Predicate.isObject(trusted) && Object.hasOwn(trusted, SCHEMA_TRUST_DOMAIN)) { + return false; + } + const merged = mergeJsonObjects( + existing, + yield* parseJsonObject(settingsPath, VSCODE_SCHEMA_TRUST_TEMPLATE), + ); + const edited = updateJsonDocument(before, merged); + if (edited === undefined) { + return yield* new InitParseSettingsError({ + detail: `${settingsPath} could not be edited without dropping its comments, so it was left unchanged`, + suggestion: `Add "${SCHEMA_TRUST_DOMAIN}": true under "${SCHEMA_TRUST_KEY}" in ${settingsPath}.`, + }); + } + after = edited; + } + if (after === before) { + return false; + } + if (options?.dryRun !== true) { + yield* fs.writeFileString(settingsPath, after, { mode: INIT_FILE_MODE }); + } + return true; +}); + export const writeVscodeConfig = Effect.fnUntraced(function* ( cwd: string, options?: { readonly announce?: boolean }, @@ -119,8 +173,8 @@ export const writeVscodeConfig = Effect.fnUntraced(function* ( const settingsPath = path.join(vscodeDir, "settings.json"); yield* fs.makeDirectory(vscodeDir, { recursive: true, mode: INIT_DIR_MODE }); - yield* updateJsonFile(extensionsPath, VSCODE_EXTENSIONS_TEMPLATE); - yield* updateJsonFile(settingsPath, VSCODE_SETTINGS_TEMPLATE); + yield* mergeJsonSettingsFile(extensionsPath, VSCODE_EXTENSIONS_TEMPLATE); + yield* mergeJsonSettingsFile(settingsPath, VSCODE_SETTINGS_TEMPLATE); if (options?.announce ?? true) { yield* output.raw("Generated VS Code settings in .vscode/settings.json.\n"); diff --git a/apps/cli/src/shared/output/normalize-error.ts b/apps/cli/src/shared/output/normalize-error.ts index 0de304ffd2..9348edaa78 100644 --- a/apps/cli/src/shared/output/normalize-error.ts +++ b/apps/cli/src/shared/output/normalize-error.ts @@ -1,3 +1,5 @@ +import { styleText } from "node:util"; + import { Cause, Option } from "effect"; import { CliError } from "effect/cli"; import { unwrapNativeFailure } from "../telemetry/error-actionability.ts"; @@ -12,6 +14,10 @@ export type PlanGateEntitlement = { readonly upgrade_url: string; }; +/** The text-mode stderr line that tells the user a plan upgrade unlocks the denied feature. */ +export const upgradeHint = (upgradeUrl: string): string => + `Your organization does not have access to this feature. Upgrade your plan: ${styleText("bold", upgradeUrl)}`; + type NormalizedCliError = { readonly code: string; readonly message: string; diff --git a/apps/cli/src/shared/output/output.layer.ts b/apps/cli/src/shared/output/output.layer.ts index 6703f93178..0932006209 100644 --- a/apps/cli/src/shared/output/output.layer.ts +++ b/apps/cli/src/shared/output/output.layer.ts @@ -32,7 +32,7 @@ import { Tty } from "../runtime/tty.service.ts"; import { CommandTarget } from "./command-target.service.ts"; import { CONTEXT_CANCELED_MESSAGE, NonInteractiveError, StdoutClosedError } from "./errors.ts"; import { MachineErrorContext } from "./machine-error-context.service.ts"; -import type { PlanGateEntitlement } from "./normalize-error.ts"; +import { type PlanGateEntitlement, upgradeHint } from "./normalize-error.ts"; import { Output } from "./output.service.ts"; import type { OutputFormat, StreamEvent } from "./types.ts"; @@ -554,6 +554,9 @@ export const textOutputLayer = Layer.effect( activeSpinner.pauses = 0; activeSpinner = undefined; } + if (err.entitlement !== undefined) { + process.stderr.write(upgradeHint(err.entitlement.upgrade_url) + "\n"); + } // Bypasses clack's `log.error` framing (`│` guide + `■` icon): a // red-styled message on stderr, optionally followed by a suggestion. process.stderr.write(styleText("red", err.message) + "\n"); diff --git a/apps/cli/src/shared/output/output.layer.unit.test.ts b/apps/cli/src/shared/output/output.layer.unit.test.ts index d648802385..799263af05 100644 --- a/apps/cli/src/shared/output/output.layer.unit.test.ts +++ b/apps/cli/src/shared/output/output.layer.unit.test.ts @@ -28,6 +28,7 @@ import { import { commandTargetLayer } from "./command-target.layer.ts"; import { machineErrorContextLayer } from "./machine-error-context.layer.ts"; import { MachineErrorContext } from "./machine-error-context.service.ts"; +import { upgradeHint } from "./normalize-error.ts"; import { Output } from "./output.service.ts"; import { jsonOutputLayer, @@ -289,6 +290,42 @@ describe("Output", () => { ); }); + it.effect( + "fail prints the upgrade hint once, before the message, for a plan-gated denial", + () => { + const upgradeUrl = "https://supabase.com/dashboard/org/acme/billing"; + const writes: string[] = []; + const originalWrite = process.stderr.write.bind(process.stderr); + const originalArgv = process.argv; + process.stderr.write = ((chunk: string | Uint8Array) => { + writes.push(typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk)); + return true; + }) as typeof process.stderr.write; + process.argv = originalArgv.filter((arg) => arg !== "--debug"); + return Effect.gen(function* () { + const out = yield* Output; + yield* out.fail({ + code: "E_TEST", + message: "boom", + entitlement: { feature: "project_restore_size", upgrade_url: upgradeUrl }, + }); + expect(writes).toEqual([ + upgradeHint(upgradeUrl) + "\n", + "\x1B[31mboom\x1B[39m\n", + "Try rerunning the command with --debug to troubleshoot the error.\n", + ]); + }).pipe( + Effect.provide(layer), + Effect.ensuring( + Effect.sync(() => { + process.stderr.write = originalWrite; + process.argv = originalArgv; + }), + ), + ); + }, + ); + it.effect("fail omits the --debug suggestion when --debug is set", () => { const writes: string[] = []; const originalWrite = process.stderr.write.bind(process.stderr); diff --git a/apps/cli/src/shared/services/Dockerfile b/apps/cli/src/shared/services/Dockerfile index 2fc80e16fd..1ec2e357b4 100644 --- a/apps/cli/src/shared/services/Dockerfile +++ b/apps/cli/src/shared/services/Dockerfile @@ -5,9 +5,9 @@ # a catalog update. Everything else in this file (this comment, kong, pg14, the one-shot job # images) is hand- or Dependabot-managed. Keep a line between image lines: git conflicts on edits to # adjacent lines, and catalog PRs for neighbouring aliases are often open at the same time. -FROM supabase/postgres:17.11.0.018 AS pg +FROM supabase/postgres:17.11.0.019 AS pg -FROM supabase/postgres:15.19.0.018 AS pg15 +FROM supabase/postgres:15.19.0.019 AS pg15 # Postgres 14 has no slim build; bumped by hand (Dependabot ignores supabase/postgres). FROM supabase/postgres:14.1.0.89 AS pg14 # New always-on service alias: extend SERVICE_IMAGE_ALIASES in @@ -33,9 +33,9 @@ FROM supabase/supavisor:2.10.0 AS supavisor FROM supabase/gotrue:v2.197.0 AS gotrue -FROM supabase/realtime:v2.154.0 AS realtime +FROM supabase/realtime:v2.160.0 AS realtime -FROM supabase/storage-api:v1.90.1 AS storage +FROM supabase/storage-api:v1.94.2 AS storage FROM supabase/logflare:1.50.15 AS logflare # One-shot job images (not started as long-running containers); differ's alias diff --git a/apps/cli/src/shared/services/services.shared.ts b/apps/cli/src/shared/services/services.shared.ts index 810f331e2b..fe7a73a921 100644 --- a/apps/cli/src/shared/services/services.shared.ts +++ b/apps/cli/src/shared/services/services.shared.ts @@ -139,7 +139,7 @@ export function localServiceImagesFromDockerfile( const LOCAL_SERVICE_IMAGES = localServiceImagesFromSpecs(dockerfileServiceImages); /** - * Resolves PG13/14/15 against the Dockerfile's `pg15`/`pg14` stages — the single version table, + * Resolves PG14/15 against the Dockerfile's `pg15`/`pg14` stages — the single version table, * generated (`pg15`) or hand-pinned (`pg14`, no slim build) from the stack catalog. Always the * raw docker.io reference; slim translation happens downstream via the same `toSlimImage("pg", * …)` path every other slim-capable service uses, since a slim-capable service's Dockerfile tag @@ -147,7 +147,6 @@ const LOCAL_SERVICE_IMAGES = localServiceImagesFromSpecs(dockerfileServiceImages */ export function postgresImageForDbMajorVersion(majorVersion: number): string | undefined { switch (majorVersion) { - case 13: case 15: return dockerfileServiceImageRaw("pg15"); case 14: diff --git a/apps/cli/src/shared/services/services.shared.unit.test.ts b/apps/cli/src/shared/services/services.shared.unit.test.ts index 6dac6482f3..c7ff636b04 100644 --- a/apps/cli/src/shared/services/services.shared.unit.test.ts +++ b/apps/cli/src/shared/services/services.shared.unit.test.ts @@ -151,15 +151,13 @@ describe("services shared", () => { ]); }); - test("resolves PG13/14/15 from the Dockerfile's pg15/pg14 stages, regardless of the slim flag", () => { + test("resolves PG14/15 from the Dockerfile's pg15/pg14 stages, regardless of the slim flag", () => { const pg15 = dockerfileServiceImageRaw("pg15"); const pg14 = dockerfileServiceImageRaw("pg14"); - expect(postgresImageForDbMajorVersion(13)).toBe(pg15); expect(postgresImageForDbMajorVersion(15)).toBe(pg15); expect(postgresImageForDbMajorVersion(14)).toBe(pg14); // Always the raw docker.io reference; slim translation is a separate, downstream concern // (`toSlimImage`/`slimImageForCurrentPin`), so this function itself doesn't read the flag. - expect(postgresImageForDbMajorVersion(13)).toBe(pg15); expect(postgresImageForDbMajorVersion(15)).toBe(pg15); expect(postgresImageForDbMajorVersion(14)).toBe(pg14); }); diff --git a/apps/cli/src/shared/telemetry/__fixtures__/error-tags.txt b/apps/cli/src/shared/telemetry/__fixtures__/error-tags.txt index 6e1d61ac18..371f33a7d7 100644 --- a/apps/cli/src/shared/telemetry/__fixtures__/error-tags.txt +++ b/apps/cli/src/shared/telemetry/__fixtures__/error-tags.txt @@ -38,6 +38,7 @@ BranchesUnpauseNetworkError BranchesUnpauseUnexpectedStatusError BranchesUpdateNetworkError BranchesUpdateUnexpectedStatusError +CliConfigConvertError CliConfigFileConflictError CliConfigFlagConflictError CliConfigLoadError @@ -71,6 +72,13 @@ ComputeSourceMissingError ComputeStacksValidationError ComputeUnavailableError ComputeUploadFailedError +ConfigConvertAlreadyJsonError +ConfigConvertFileChangedError +ConfigConvertLoadConfigError +ConfigConvertOutputFlagUnsupportedError +ConfigConvertUnsupportedError +ConfigConvertWorkdirError +ConfigConvertWriteError ConfigDiffLoadConfigError ConfigDiffOutputFlagUnsupportedError ConfigDiffReadNetworkError @@ -568,6 +576,7 @@ TestNewInvalidNameError TestNewWriteError UnknownComputeExposureError UnknownComputeRuntimeError +UnknownComputeSecretsScopeError UnknownComputeSizeError UnlinkRefReadError UnlinkTempRemovalError diff --git a/apps/cli/src/shared/telemetry/error-actionability.ts b/apps/cli/src/shared/telemetry/error-actionability.ts index d5a8c3cd02..d99a897811 100644 --- a/apps/cli/src/shared/telemetry/error-actionability.ts +++ b/apps/cli/src/shared/telemetry/error-actionability.ts @@ -640,9 +640,9 @@ function stackKindDeclaration(value: unknown): CliErrorActionabilityDeclaration } /** - * The declaration for a failure confirmed plan-gated by the entitlement - * check (`suggestUpgrade`). Shared so every gated surface groups under - * the same fingerprint family. + * The declaration for a failure confirmed plan-gated, by its `entitlement` + * or by the entitlement check (`suggestUpgrade`). Shared so every gated + * surface groups under the same fingerprint family. */ export const planLimitGatedActionability: CliErrorActionabilityDeclaration = { ...actionability.planLimit, @@ -1146,7 +1146,12 @@ function classifyAtDepth(error: unknown, depth: number): CliErrorActionability { if (depth >= MAX_CAUSE_DEPTH) { return toActionability(actionability.unknown, "error", "CauseChainLimit"); } - const declared = readDeclaration(error); + // `mapHttpError` attaches `entitlement` only from a 4xx `entitlement_required` body, so it + // marks a plan-gated denial on any status error class, declared field or not. + const declared = + isErrorRecord(error) && isErrorRecord(error["entitlement"]) + ? planLimitGatedActionability + : readDeclaration(error); if (declared !== undefined) { const stableTaggedName = readStableTaggedPrototypeName(error); const tag = readErrorTag(error); diff --git a/apps/cli/src/shared/telemetry/error-actionability.unit.test.ts b/apps/cli/src/shared/telemetry/error-actionability.unit.test.ts index f9fb5a2b38..714544354d 100644 --- a/apps/cli/src/shared/telemetry/error-actionability.unit.test.ts +++ b/apps/cli/src/shared/telemetry/error-actionability.unit.test.ts @@ -147,6 +147,20 @@ describe("classifyCliErrorActionability", () => { expect(statusCodeActionability(undefined).error_category).toBe("network"); }); + it("classifies a status error carrying a plan-gate entitlement as plan_limit", () => { + const gated = Object.assign(new DeclaredStatusError({ status: 402 }), { + entitlement: { + feature: "project_restore_size", + upgrade_url: "https://supabase.com/dashboard/org/acme/billing", + }, + }); + expect(classifyCliErrorActionability(gated)).toMatchObject({ + error_category: "plan_limit", + error_fingerprint: "tag:DeclaredStatusError:plan_limit", + suggestion_type: "upgrade_plan", + }); + }); + it("rejects malformed declarations and arbitrary remediation text", () => { class InvalidDeclaration extends Data.Error { get [ErrorActionabilityId]() { diff --git a/apps/cli/src/shared/telemetry/event-catalog.ts b/apps/cli/src/shared/telemetry/event-catalog.ts index cfd281e979..21041fba92 100644 --- a/apps/cli/src/shared/telemetry/event-catalog.ts +++ b/apps/cli/src/shared/telemetry/event-catalog.ts @@ -47,6 +47,8 @@ export const PropOrioleDb = "orioledb"; export const PropStackRuntime = "stack_runtime"; // Set only on failures classified `invalid_config` whose config key is known. export const PropConfigKey = "config_key"; +// Set only once a command reads its project's config file. +export const PropConfigFormat = "config_format"; // Set only once `functions serve` on the Docker runtime reaches its final outcome. export const PropServeEndReason = "serve_end_reason"; // Set only when the Edge Runtime container's exit code is known at that outcome. diff --git a/apps/cli/src/telemetry/command-telemetry-attributes.ts b/apps/cli/src/telemetry/command-telemetry-attributes.ts index 58a1ef7ecc..39116c3dab 100644 --- a/apps/cli/src/telemetry/command-telemetry-attributes.ts +++ b/apps/cli/src/telemetry/command-telemetry-attributes.ts @@ -2,6 +2,7 @@ import { Context, Effect } from "effect"; import type { StackRuntime } from "../command-internal/stack-runtime.ts"; import type { ServeEndReason } from "../shared/functions/serve.ts"; import { + PropConfigFormat, PropConfigKey, PropEdgeRuntimeExitCode, PropOrioleDb, @@ -12,6 +13,7 @@ import { /** Properties that code below a command handler adds to its `cli_command_executed` event. */ export interface CommandTelemetryAttributeValues { readonly [PropConfigKey]?: string; + readonly [PropConfigFormat]?: "toml" | "json" | "jsonc"; readonly [PropOrioleDb]?: boolean; readonly [PropStackRuntime]?: StackRuntime; readonly [PropServeEndReason]?: ServeEndReason; diff --git a/apps/cli/src/telemetry/command-telemetry.ts b/apps/cli/src/telemetry/command-telemetry.ts index dd4c16b7c7..7f31681a60 100644 --- a/apps/cli/src/telemetry/command-telemetry.ts +++ b/apps/cli/src/telemetry/command-telemetry.ts @@ -6,6 +6,7 @@ import { getCommandRuntimeSpanName, } from "../shared/runtime/command-runtime.service.ts"; import { failureBesideClosedStdout } from "../shared/output/errors.ts"; +import { normalizeCause } from "../shared/output/normalize-error.ts"; import { Output } from "../shared/output/output.service.ts"; import { CreateTicketFlag, @@ -31,10 +32,13 @@ import { DbAdvisorsFailOnError } from "../commands/db/advisors/advisors.errors.t import { DbLintFailOnError } from "../commands/db/lint/lint.errors.ts"; import { EventCommandExecuted, + EventUpgradeSuggested, PropConfigKey, PropDurationMs, PropErrorCategory, PropExitCode, + PropFeatureKey, + PropOrgSlug, PropOutputFormat, PropStackBackend, } from "../shared/telemetry/event-catalog.ts"; @@ -103,6 +107,11 @@ interface CommandTelemetryOptions = never> readonly aliases?: Readonly>; } +function orgSlugFromUpgradeUrl(upgradeUrl: string): string { + const match = /\/org\/([^/]+)/.exec(upgradeUrl); + return match?.[1] ?? ""; +} + /** * Rejects an out-of-enum `-o`/`--output` value before the command runs, so no * `cli_command_executed` event fires for a rejected flag. `OutputFlag` is read optionally, since @@ -573,6 +582,22 @@ function withCommandAnalyticsImplementation + Cause.hasInterruptsOnly(cause) ? Effect.failCause(cause) : Effect.void, + ), + ); + } yield* analytics .capture(EventCommandExecuted, { diff --git a/apps/cli/src/telemetry/command-telemetry.unit.test.ts b/apps/cli/src/telemetry/command-telemetry.unit.test.ts index 35e9c205ba..18107bc3cb 100644 --- a/apps/cli/src/telemetry/command-telemetry.unit.test.ts +++ b/apps/cli/src/telemetry/command-telemetry.unit.test.ts @@ -25,6 +25,7 @@ import { PropWorkflow, } from "../shared/telemetry/event-catalog.ts"; import { ProcessControl } from "../shared/runtime/process-control.service.ts"; +import { BranchesCreateUnexpectedStatusError } from "../commands/branches/branches.errors.ts"; import { ConfigDiffLoadConfigError } from "../commands/config/diff/diff.errors.ts"; import { CliConfigValueError } from "../config/cli-config.errors.ts"; import { DbDumpRunError } from "../commands/db/dump/dump.errors.ts"; @@ -1418,6 +1419,56 @@ describe("withCommandTelemetry", () => { ); }); + describe("plan-gated denials", () => { + const gatedFailure = new BranchesCreateUnexpectedStatusError({ + status: 402, + body: "{}", + message: "unexpected create branch status 402", + entitlement: { + feature: "branching_limit", + upgrade_url: "https://supabase.com/dashboard/org/env-org/billing", + }, + }); + const runGated = () => { + const analytics = mockContextualAnalytics(); + return Effect.fail(gatedFailure).pipe( + withCommandTelemetry(), + Effect.provide( + Layer.mergeAll( + analytics.layer, + mockProcessControl().layer, + mockOutput({ format: "json" }).layer, + Stdio.layerTest({ args: Effect.succeed(["branches", "create"]) }), + commandRuntimeLayer(["branches", "create"]).pipe(Layer.provide(BunCrypto.layer)), + ), + ), + Effect.exit, + Effect.map(() => analytics.captured), + ); + }; + + it.live("fires cli_upgrade_suggested once, before cli_command_executed", () => + runGated().pipe( + Effect.tap((captured) => + Effect.sync(() => { + expect(captured.map((event) => event.event)).toEqual([ + "cli_upgrade_suggested", + "cli_command_executed", + ]); + expect(captured[0]?.properties).toMatchObject({ + feature_key: "branching_limit", + org_slug: "env-org", + }); + expect(captured[1]?.properties).toMatchObject({ + exit_code: 1, + error_category: "plan_limit", + }); + }), + ), + ), + ); + }); + it.live("skips analytics capture when analytics are disabled", () => { const analytics = mockContextualAnalytics(); diff --git a/apps/cli/tests/contract/cases.ts b/apps/cli/tests/contract/cases.ts index d1774884ac..f40a736c72 100644 --- a/apps/cli/tests/contract/cases.ts +++ b/apps/cli/tests/contract/cases.ts @@ -7,6 +7,7 @@ import { ContractReset, ContractTarget, type ContractTargetError, + ContractTrust, inviteTemplateMarker, } from "./target.ts"; @@ -18,6 +19,7 @@ interface ContractCase { ContractCallError | ContractTargetError | HttpClientError.HttpClientError | Schema.SchemaError, | ContractTarget | ContractReset + | ContractTrust | HttpClient.HttpClient | Socket.WebSocketConstructor | Scope.Scope @@ -53,11 +55,40 @@ const sdk = ( : Effect.fail(new ContractCallError({ message: `${operation} failed`, cause: result.error })), ); +/* Bun's WebSocket trusting the setup's certificate, for Realtime over `wss:`. */ +const trustingWebSocket = (ca: string) => + class extends WebSocket { + constructor(url: string | URL, protocols?: string | Array) { + super(url, { tls: { ca }, ...(protocols === undefined ? {} : { protocols }) }); + } + }; + const contractClient = (key: "PUBLISHABLE_KEY" | "ANON_KEY" | "SECRET_KEY") => - ContractTarget.useSync((target) => - createClient(target.API_URL, target[key], { + Effect.gen(function* () { + const target = yield* ContractTarget; + const ca = yield* ContractTrust; + const base = yield* FetchHttpClient.Fetch; + return createClient(target.API_URL, target[key], { auth: { persistSession: false, autoRefreshToken: false }, - }), + ...(ca === undefined + ? {} + : { + global: { + fetch: Object.assign( + (input: Parameters[0], init?: BunFetchRequestInit) => + base(input, { ...init, tls: { ca } }), + { preconnect: base.preconnect }, + ), + }, + realtime: { transport: trustingWebSocket(ca) }, + }), + }); + }); + +/** The fetch options every contract HTTP request takes: the setup's certificate, plus `extra`. */ +const requestInit = (extra: BunFetchRequestInit = {}) => + ContractTrust.useSync((ca): BunFetchRequestInit => + ca === undefined ? extra : { ...extra, tls: { ca } }, ); const unique = (prefix: string) => @@ -160,6 +191,8 @@ const signUpConfirmationLink = Effect.fn("Contract.signUpConfirmationLink")(func .replaceAll("&", "&") .match(/https?:\/\/[^\s"'<>]+\/verify\?[^\s"'<>]+/); if (link === null) return yield* mailError("no verify link"); + /* Under TLS, Auth links name the HTTPS host URL. */ + if ((yield* ContractTrust) !== undefined) expect(link[0]).toMatch(/^https:\/\//u); return link[0]; }); @@ -178,7 +211,10 @@ const authCases: ReadonlyArray = [ run: Effect.gen(function* () { const email = `${yield* unique("confirmed")}@example.com`; const verified = yield* HttpClient.get(yield* signUpConfirmationLink(email)).pipe( - Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }), + Effect.provideServiceEffect( + FetchHttpClient.RequestInit, + requestInit({ redirect: "manual" }), + ), ); expect(verified.status).toBe(303); expect(verified.headers.location).toContain("access_token="); @@ -317,7 +353,7 @@ const invokesEcho = (key: "PUBLISHABLE_KEY" | "ANON_KEY") => Effect.gen(function* () { const client = yield* contractClient(key); const data = yield* sdk("invoke echo", (signal) => client.functions.invoke("echo", { signal })); - expect(data).toEqual({ ok: true }); + expect(data).toMatchObject({ ok: true }); }); const functionsCases: ReadonlyArray = [ @@ -331,6 +367,17 @@ const functionsCases: ReadonlyArray = [ run: invokesEcho("ANON_KEY"), timeout: COLD_LAUNCH_TIMEOUT_MS, }, + { + name: "Functions sees SUPABASE_DB_URL for the postgres role", + run: Effect.gen(function* () { + const client = yield* contractClient("PUBLISHABLE_KEY"); + const data = yield* sdk("invoke echo", (signal) => + client.functions.invoke("echo", { signal }), + ); + expect(data).toMatchObject({ dbUser: "postgres" }); + }), + timeout: COLD_LAUNCH_TIMEOUT_MS, + }, { name: "Functions rejects a request without Authorization when verify_jwt is on", run: Effect.gen(function* () { @@ -379,6 +426,18 @@ const seedingCases: ReadonlyArray = [ name: "start applies migrations in byte order, then seeds in sql_paths order, then config buckets", run: appliesInOrder, }, + { + name: "start seeds config vector buckets", + run: Effect.gen(function* () { + const client = yield* contractClient("SECRET_KEY"); + const { vectorBuckets } = yield* sdk("list vector buckets", () => + client.storage.vectors.listBuckets(), + ); + expect(vectorBuckets.map(({ vectorBucketName }) => vectorBucketName)).toContain( + "config-vectors", + ); + }), + }, ]; const resetCases: ReadonlyArray = [ @@ -416,13 +475,20 @@ const contractCases: ReadonlyArray = [ /** Runs every contract case against one setup's running stack. */ export const describeContract = ( setup: string, - target: Layer.Layer, + target: Layer.Layer, ) => - layer(Layer.mergeAll(target, FetchHttpClient.layer, Socket.layerWebSocketConstructorGlobal), { - /* Guards the stack start, including first image pulls or native artifact downloads. */ - timeout: "5 minutes", - excludeTestServices: true, - })(`consumer contract (${setup})`, (it) => { + layer( + Layer.mergeAll( + Layer.effect(FetchHttpClient.RequestInit, requestInit()), + FetchHttpClient.layer, + Socket.layerWebSocketConstructorGlobal, + ).pipe(Layer.provideMerge(target)), + { + /* Guards the stack start, including first image pulls or native artifact downloads. */ + timeout: "5 minutes", + excludeTestServices: true, + }, + )(`consumer contract (${setup})`, (it) => { for (const { name, run, timeout } of contractCases) it.effect(name, () => run, timeout ?? 60_000); }); diff --git a/apps/cli/tests/contract/contract.docker-tls.integration.test.ts b/apps/cli/tests/contract/contract.docker-tls.integration.test.ts new file mode 100644 index 0000000000..120507d94a --- /dev/null +++ b/apps/cli/tests/contract/contract.docker-tls.integration.test.ts @@ -0,0 +1,31 @@ +import { BunServices } from "@effect/platform-bun"; +import { describe, expect, it } from "@effect/vitest"; +import { Effect } from "effect"; +import { containerPeer, isLoopback } from "../../../../packages/stack/tests/api-tls.ts"; +import { describeContract } from "./cases.ts"; +import { refusedTlsStart, stackTarget } from "./target.ts"; + +/* Where this host's Docker containers arrive from, measured on its own, picks the expectation. */ +const peer = await Effect.runPromise( + containerPeer({ engine: "docker", argv: [] }).pipe(Effect.provide(BunServices.layer)), +); + +/* Plain HTTP on a TLS API port is for loopback peers only, so where this engine's containers + arrive from elsewhere, start refuses api.tls instead of serving consumers. */ +if (isLoopback(peer)) + describeContract("stack/container over api.tls, embedded pair", stackTarget("docker", "default")); +else + describe(`stack/container over api.tls, embedded pair, containers from ${peer}`, () => { + it.live( + "fails start with unsupported networking and leaves no service running", + () => + Effect.gen(function* () { + const { message, ids, running } = yield* refusedTlsStart; + expect(message).toContain("api.tls: unsupported networking on "); + expect(message).toContain("; its services stopped: "); + expect(ids).toHaveLength(1); + expect(running).toEqual([{ code: 0, stderr: "", names: [] }]); + }), + 300_000, + ); + }); diff --git a/apps/cli/tests/contract/contract.native-tls.integration.test.ts b/apps/cli/tests/contract/contract.native-tls.integration.test.ts new file mode 100644 index 0000000000..58db884c71 --- /dev/null +++ b/apps/cli/tests/contract/contract.native-tls.integration.test.ts @@ -0,0 +1,4 @@ +import { describeContract } from "./cases.ts"; +import { stackTarget } from "./target.ts"; + +describeContract("stack/native over api.tls, project pair", stackTarget("native", "custom")); diff --git a/apps/cli/tests/contract/target.ts b/apps/cli/tests/contract/target.ts index f20f7f7653..30aba2e6e2 100644 --- a/apps/cli/tests/contract/target.ts +++ b/apps/cli/tests/contract/target.ts @@ -27,6 +27,7 @@ import { stackTargetResolverLayer, } from "../../src/command-internal/stack-target.ts"; import { stackStart } from "../../src/commands/experimental/stack/start/start.handler.ts"; +import { KONG_LOCAL_TLS_CERT } from "../../src/commands/start/templates/kong-local-tls.ts"; import { start } from "../../src/commands/start/start.handler.ts"; import { CliArgs } from "../../src/shared/cli/cli-args.service.ts"; import { sanitizeProjectId } from "../../src/shared/config/project-id.ts"; @@ -53,10 +54,25 @@ interface LegacyPorts { const port = (value: number | undefined) => (value === undefined ? "" : `port = ${value}\n`); -const config = (projectId: string, ports: LegacyPorts | undefined) => `project_id = "${projectId}" +/** `default` serves `api.tls` with legacy's embedded pair; `custom` with a project pair. */ +type ContractTls = "default" | "custom"; + +const tlsSection = (tls: ContractTls | undefined) => + tls === undefined + ? "" + : `[api.tls] +enabled = true +${tls === "custom" ? 'cert_path = "certs/api.crt"\nkey_path = "certs/api.key"\n' : ""}`; + +const config = ( + projectId: string, + ports: LegacyPorts | undefined, + tls?: ContractTls, +) => `project_id = "${projectId}" [api] ${port(ports?.api)} +${tlsSection(tls)} [db] ${port(ports?.db)} [db.pooler] @@ -88,6 +104,11 @@ objects_path = "./buckets/public" [storage.buckets.config-private] public = false +[storage.vector.buckets.config-vectors] + +[storage.analytics] +enabled = true + [edge_runtime] enabled = true @@ -104,8 +125,8 @@ enabled = false /* Migrations and seeds log to contract_log in run order: 0, 10, 2026, 9, skipping notes.sql and nested/, then zz once, then aa and mm. 10 creates config-public private, so the last seed mm seeing public=false and a public bucket at the end prove config buckets seed after every seed. */ -const projectFiles = (projectId: string, ports: LegacyPorts | undefined) => ({ - "config.toml": config(projectId, ports), +const projectFiles = (projectId: string, ports: LegacyPorts | undefined, tls?: ContractTls) => ({ + "config.toml": config(projectId, ports, tls), "migrations/9_after_10.sql": `insert into public.contract_log (source) values ('migration 9'); `, "migrations/20260101000000_contract.sql": `create table public.contract_items (id int primary key, label text not null); @@ -133,7 +154,9 @@ insert into public.contract_log (source) select format('migration 0 sees auth=%s `, "buckets/public/a.txt": "seeded object\n", "buckets/public/nested/b.txt": "nested object\n", - "functions/echo/index.ts": `Deno.serve(() => Response.json({ ok: true })); + "functions/echo/index.ts": `Deno.serve(() => + Response.json({ ok: true, dbUser: URL.parse(Deno.env.get("SUPABASE_DB_URL") ?? "")?.username ?? null }), +); `, "templates/shared/invite.html": `

${inviteTemplateMarker}

Accept `, @@ -144,10 +167,11 @@ const writeContractProject = Effect.fn("Contract.writeProject")(function* ( root: string, projectId: string, ports?: LegacyPorts, + tls?: ContractTls, ) { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; - for (const [name, content] of Object.entries(projectFiles(projectId, ports))) { + for (const [name, content] of Object.entries(projectFiles(projectId, ports, tls))) { const file = path.join(root, "supabase", name); yield* fs.makeDirectory(path.dirname(file), { recursive: true }); yield* fs.writeFileString(file, content); @@ -168,6 +192,32 @@ const ContractEnv = Schema.StructWithRest( [Schema.Record(Schema.String, Schema.String)], ); +/** The certificate a client trusts for the setup's HTTPS API, or `undefined` over plain HTTP. */ +export class ContractTrust extends Context.Service()( + "supabase/tests/ContractTrust", +) {} + +/* A pair standing in for a project's own `cert_path`/`key_path`, valid for 127.0.0.1. */ +const customPair = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const certs = path.join( + import.meta.dirname, + "..", + "..", + "..", + "..", + "packages", + "stack", + "tests", + "certs", + ); + return { + cert: yield* fs.readFileString(path.join(certs, "trusted.crt")), + key: yield* fs.readFileString(path.join(certs, "localhost.key")), + }; +}); + /** The env `start` reports for one running local setup, every reported name kept. */ export class ContractTarget extends Context.Service()( "supabase/tests/ContractTarget", @@ -203,6 +253,35 @@ const startedEnv = ( ), ); +/* `[api.tls]` must reach the started stack: an https API_URL that a client without the trusted + certificate can't verify, so plain URLs never pass the TLS suites. */ +const servesApiTls = Effect.fn("Contract.servesApiTls")(function* (apiUrl: string) { + if (!apiUrl.startsWith("https://")) + return yield* new ContractTargetError({ + message: `start with [api.tls] reported API_URL ${apiUrl}`, + cause: undefined, + }); + const fetch = yield* FetchHttpClient.Fetch; + const untrusted = yield* Effect.tryPromise({ + try: (signal) => fetch(`${apiUrl}/rest/v1/`, { signal }).then(({ status }) => status), + catch: (cause) => + new ContractTargetError({ + message: cause instanceof Error ? cause.message : String(cause), + cause, + }), + }).pipe( + Effect.match({ + onSuccess: (status) => `HTTP ${status}`, + onFailure: (error) => error.message, + }), + ); + if (!/certificate/iu.test(untrusted)) + return yield* new ContractTargetError({ + message: `a client without the [api.tls] certificate got ${untrusted}`, + cause: undefined, + }); +}); + /* Interrupts a stuck start so its own rollback runs before the layer guard tears the fixture down. */ const guardStart = (start: Effect.Effect) => Effect.timeoutOrElse(start, { @@ -236,57 +315,136 @@ const sharedLayers = (output: ReturnType, args: string[]) => ); }; +/** + * One stack project in-process with automatic ports, its stacks destroyed when the scope closes: + * `start` runs `stack start` there. + */ +const stackProject = Effect.fn("Contract.stackProject")(function* ( + runtime: "native" | "docker", + tls?: ContractTls, +) { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const host = yield* RuntimeInfo; + const root = yield* fs.makeTempDirectoryScoped({ + prefix: `contract-${runtime}-`, + /* Linux Edge Runtime overlays /tmp with a private worker filesystem, so native functions need a visible host path. */ + ...(runtime === "native" && host.platform === "linux" ? { directory: host.homeDir } : {}), + }); + yield* writeContractProject(root, sanitizeProjectId(path.basename(root)), undefined, tls); + const trust = + tls === undefined + ? undefined + : tls === "default" + ? KONG_LOCAL_TLS_CERT + : yield* customPair.pipe( + Effect.tap(({ cert, key }) => + Effect.all([ + fs.makeDirectory(path.join(root, "supabase", "certs"), { recursive: true }), + fs.writeFileString(path.join(root, "supabase", "certs", "api.crt"), cert), + fs.writeFileString(path.join(root, "supabase", "certs", "api.key"), key), + ]), + ), + Effect.map(({ cert }) => cert), + ); + const cacheRoot = path.join(root, "cache", "stack"); + const stateRoot = path.join(root, "stacks"); + yield* fs.makeDirectory(stackArtifactCacheRoot, { recursive: true }); + yield* fs.makeDirectory(path.dirname(cacheRoot), { recursive: true }); + yield* fs.symlink(stackArtifactCacheRoot, cacheRoot); + const output = mockOutput({ format: "json" }); + const layers = Layer.mergeAll( + sharedLayers(output, ["stack", "start"]), + stackTargetResolverLayer.pipe( + Layer.provideMerge( + Layer.mergeAll(mockCommandSettings({ workdir: root, supabaseHome: root }), stackApiLayer), + ), + ), + stackCatalogSetupLayer, + ); + const context = yield* Layer.build(layers.pipe(Layer.provideMerge(hostServices))); + yield* Effect.addFinalizer(() => + StackApi.use((stackApi) => destroyTestStacks(stackApi, stateRoot, cacheRoot)).pipe( + Effect.provide(context), + ), + ); + const start = stackStart({ + exclude: [], + stack: Option.none(), + stackId: Option.none(), + runtime, + preparation: "background", + frozen: false, + eager: false, + }).pipe(Effect.provide(context), guardStart); + const stackIds = StackApi.use((stackApi) => stackApi.discover({ stateRoot })).pipe( + Effect.map((found) => found.map(({ definition }) => definition.id)), + Effect.provide(context), + ); + return { context, output, trust, start, stackIds }; +}); + /** Starts one stack in-process with automatic ports and destroys it when the scope closes. */ -export const stackTarget = (runtime: "native" | "docker") => +export const stackTarget = (runtime: "native" | "docker", tls?: ContractTls) => Layer.effectContext( Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const path = yield* Path.Path; - const host = yield* RuntimeInfo; - const root = yield* fs.makeTempDirectoryScoped({ - prefix: `contract-${runtime}-`, - /* Linux Edge Runtime overlays /tmp with a private worker filesystem, so native functions need a visible host path. */ - ...(runtime === "native" && host.platform === "linux" ? { directory: host.homeDir } : {}), - }); - yield* writeContractProject(root, sanitizeProjectId(path.basename(root))); - const cacheRoot = path.join(root, "cache", "stack"); - yield* fs.makeDirectory(stackArtifactCacheRoot, { recursive: true }); - yield* fs.makeDirectory(path.dirname(cacheRoot), { recursive: true }); - yield* fs.symlink(stackArtifactCacheRoot, cacheRoot); - const output = mockOutput({ format: "json" }); - const layers = Layer.mergeAll( - sharedLayers(output, ["stack", "start"]), - stackTargetResolverLayer.pipe( - Layer.provideMerge( - Layer.mergeAll( - mockCommandSettings({ workdir: root, supabaseHome: root }), - stackApiLayer, - ), - ), - ), - stackCatalogSetupLayer, - ); - const context = yield* Layer.build(layers.pipe(Layer.provideMerge(hostServices))); - yield* Effect.addFinalizer(() => - StackApi.use((stackApi) => - destroyTestStacks(stackApi, path.join(root, "stacks"), cacheRoot), - ).pipe(Effect.provide(context)), - ); - yield* stackStart({ - exclude: [], - stack: Option.none(), - stackId: Option.none(), - runtime, - preparation: "background", - frozen: false, - eager: false, - }).pipe(Effect.provide(context), guardStart); + const { context, output, trust, start } = yield* stackProject(runtime, tls); + yield* start; const { env } = yield* startedEnv(output, Schema.Struct({ env: ContractEnv })); + if (trust !== undefined) yield* servesApiTls(env.API_URL).pipe(Effect.provide(context)); const reset = resetOn("stack").pipe(Effect.provide(context)); - return Context.make(ContractTarget, env).pipe(Context.add(ContractReset, reset)); + return Context.make(ContractTarget, env).pipe( + Context.add(ContractReset, reset), + Context.add(ContractTrust, trust), + ); }), ).pipe(Layer.provide(hostServices)); +/** + * Runs `stack start` for a container stack serving `[api.tls]` with legacy's embedded pair, + * expecting it to fail: answers its error, the project's stack ids, and the service containers of + * each still running afterwards (the stack-wide volume helper outlives its services by design). + */ +export const refusedTlsStart = Effect.gen(function* () { + const { start, stackIds } = yield* stackProject("docker", "default"); + const error = yield* Effect.flip(start); + const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const ids = yield* stackIds; + const running = yield* Effect.forEach(ids, (id) => + spawnContainerCli( + spawner, + [ + "ps", + "--filter", + `label=com.supabase.stack=${id}`, + "--filter", + "label=com.supabase.service", + "--format", + "{{.Names}}", + ], + { stdin: "ignore", stdout: "pipe", stderr: "pipe" }, + ).pipe( + Effect.flatMap((child) => + Effect.all( + [ + child.stdout.pipe(Stream.decodeText, Stream.mkString), + child.stderr.pipe(Stream.decodeText, Stream.mkString), + child.exitCode, + ], + { concurrency: "unbounded" }, + ), + ), + Effect.scoped, + Effect.map(([names, stderr, code]) => ({ + code: Number(code), + stderr, + names: names.split("\n").filter((name) => name.length > 0), + })), + ), + ); + return { message: error.message, ids, running }; +}).pipe(Effect.scoped, Effect.provide(hostServices)); + /* Works around a legacy start readiness gap: Realtime seeds through a throwaway node on :4000 before it execs the server, so its healthcheck can pass early. Wait for the line the stack treats as ready. */ const realtimeServerListening = Effect.fn("Contract.realtimeServerListening")(function* ( @@ -397,6 +555,9 @@ export const legacyTarget = Layer.effectContext( ); const env = yield* startedEnv(output, ContractEnv); const reset = resetOn("legacy").pipe(Effect.provide(context)); - return Context.make(ContractTarget, env).pipe(Context.add(ContractReset, reset)); + return Context.make(ContractTarget, env).pipe( + Context.add(ContractReset, reset), + Context.add(ContractTrust, undefined), + ); }), ).pipe(Layer.provide(hostServices)); diff --git a/apps/cli/tests/helpers/notebooks.ts b/apps/cli/tests/helpers/notebooks.ts index de0b5a09c7..35a0a2d508 100644 --- a/apps/cli/tests/helpers/notebooks.ts +++ b/apps/cli/tests/helpers/notebooks.ts @@ -162,6 +162,7 @@ function notebookMetadata(options: { readonly id: string; readonly name: string updated_at: "2026-01-01T00:00:00Z", owner: null, updated_by: null, + url: `https://supabase.com/dashboard/project/${NOTEBOOKS_PROJECT_REF}/notebooks/${options.id}`, }, }; } diff --git a/apps/cli/tests/helpers/storage.ts b/apps/cli/tests/helpers/storage.ts index b0dfc9f729..162763957f 100644 --- a/apps/cli/tests/helpers/storage.ts +++ b/apps/cli/tests/helpers/storage.ts @@ -1,5 +1,17 @@ import { BunCrypto, BunServices } from "@effect/platform-bun"; -import { ConfigProvider, Effect, FileSystem, Layer, Option, Path, Redacted, Stream } from "effect"; +import { + ConfigProvider, + Context, + Effect, + FileSystem, + Layer, + Option, + Path, + Predicate, + Redacted, + Stream, +} from "effect"; +import * as FetchHttpClient from "effect/http/FetchHttpClient"; import * as HttpClient from "effect/http/HttpClient"; import * as HttpClientResponse from "effect/http/HttpClientResponse"; import type { @@ -58,6 +70,8 @@ interface RecordedStorageRequest { readonly url: string; readonly headers: Record; readonly body: unknown; + /** The CA the request's `FetchHttpClient.RequestInit` trusts, when it sets one. */ + readonly ca: unknown; } export interface SetupStorageOptions { @@ -105,6 +119,8 @@ export interface SetupStorageStackApiOptions { | "failed" | "disabled"; readonly storageError?: string; + /** The certificate the stack saved at its last start with `api.tls`; its API serves HTTPS. */ + readonly apiTlsCert?: string; } const STORAGE_STACK_ID = "e".repeat(64); @@ -157,6 +173,7 @@ const observation = ( readonly protocol: "tcp" | "http"; readonly host: string; readonly port: number; + readonly scheme?: "https"; }, error?: string, ): Observation => ({ @@ -234,7 +251,13 @@ export function buildStorageStackApi( storageWakeEnabled, options.storageEndpoint === false ? undefined - : { name: "http", protocol: "http", host: "127.0.0.1", port: 59999 }, + : { + name: "http", + protocol: "http", + host: "127.0.0.1", + port: 59999, + ...(options.apiTlsCert === undefined ? {} : { scheme: "https" as const }), + }, options.storageError, ); const database = { @@ -258,6 +281,11 @@ export function buildStorageStackApi( id === database.id ? Effect.succeed(database) : Effect.succeed(storage), list: Effect.succeed(storageEnabled ? [database, storage] : [database]), }, + apiTls: { + get: Effect.succeed( + options.apiTlsCert === undefined ? undefined : { cert: options.apiTlsCert }, + ), + }, credentials: { get: Effect.succeed(stackCredentials) }, composition: { plan: () => Effect.succeed([]), @@ -320,7 +348,11 @@ function recordingStorageHttp(routes: ReadonlyArray) { const layer = Layer.succeed( HttpClient.HttpClient, - HttpClient.make((request) => { + HttpClient.make((request, _url, _signal, fiber) => { + const init = Context.getOption(fiber.context, FetchHttpClient.RequestInit).pipe( + Option.getOrUndefined, + ); + const tls = Predicate.hasProperty(init, "tls") ? init.tls : undefined; let body: unknown; if (request.body._tag === "Uint8Array") { try { @@ -334,6 +366,7 @@ function recordingStorageHttp(routes: ReadonlyArray) { url: request.url, headers: { ...request.headers }, body, + ca: Predicate.hasProperty(tls, "ca") ? tls.ca : undefined, }); let index = -1; for (let i = 0; i < routes.length; i++) { diff --git a/apps/docs/public/schemas/config/v1.json b/apps/docs/public/schemas/config/v1.json index daade99aaa..bef9de6fb4 100644 --- a/apps/docs/public/schemas/config/v1.json +++ b/apps/docs/public/schemas/config/v1.json @@ -3,6 +3,7 @@ "$id": "https://supabase.com/schemas/config/v1.json", "title": "Supabase CLI config (CliConfig)", "description": "The Supabase CLI's local project config document (supabase/config.toml or supabase/config.json).", + "allowTrailingCommas": true, "type": "object", "properties": { "project_id": { @@ -153,6 +154,19 @@ } ] }, + "db_pool": { + "description": "Maximum number of connections in the local PostgREST database pool. Left unset, the default pool size is unchanged.", + "anyOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "string", + "pattern": "^env\\((.*)\\)$" + } + ] + }, "auto_expose_new_tables": { "description": "Controls whether newly-created tables, views, sequences and functions in the `public` schema by `postgres` are reachable through the Data API roles (`anon`, `authenticated`, `service_role`) without explicit GRANTs. When unset, new entities are auto-exposed, matching the cloud default. Set to `false` to revoke the default Data API privileges so new entities require explicit GRANTs, matching a cloud project with the \"Default privileges for new entities\" toggle turned off.", "anyOf": [ @@ -4230,6 +4244,26 @@ "description": "How the compute is reached: `public` gives it an internet-facing URL,\n`private` keeps it reachable only from inside the project. Every deploy\nsends a complete spec, so the value recorded here is what keeps a private\ncompute private; `--exposure` overrides it for one deploy. Defaults to\n`public`.", "examples": ["private"] }, + "secrets_scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^env\\((.*)\\)$" + } + ], + "description": "controls whether secrets are available: `all` gives access to all defined secrets,\n`supabase` exposes only the `SUPABASE_*` defaults, `none` hides all\nsecrets, `string[]` gives only the secrets named in the list.", + "default": "all", + "examples": ["all", ["STRIPE_KEY", "LLM_APIKEY"]] + }, "instances": { "description": "Number of instances to run. Every deploy sends a complete spec, so a count\nrecorded here is what keeps a scaled compute scaled; `--instances` overrides\nit for one deploy. Defaults to 1.", "examples": [3], @@ -4745,6 +4779,19 @@ } ] }, + "db_pool": { + "description": "Maximum number of connections in the local PostgREST database pool. Left unset, the default pool size is unchanged.", + "anyOf": [ + { + "type": "integer", + "minimum": 1 + }, + { + "type": "string", + "pattern": "^env\\((.*)\\)$" + } + ] + }, "auto_expose_new_tables": { "description": "Controls whether newly-created tables, views, sequences and functions in the `public` schema by `postgres` are reachable through the Data API roles (`anon`, `authenticated`, `service_role`) without explicit GRANTs. When unset, new entities are auto-exposed, matching the cloud default. Set to `false` to revoke the default Data API privileges so new entities require explicit GRANTs, matching a cloud project with the \"Default privileges for new entities\" toggle turned off.", "anyOf": [ @@ -8822,6 +8869,26 @@ "description": "How the compute is reached: `public` gives it an internet-facing URL,\n`private` keeps it reachable only from inside the project. Every deploy\nsends a complete spec, so the value recorded here is what keeps a private\ncompute private; `--exposure` overrides it for one deploy. Defaults to\n`public`.", "examples": ["private"] }, + "secrets_scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "string", + "pattern": "^env\\((.*)\\)$" + } + ], + "description": "controls whether secrets are available: `all` gives access to all defined secrets,\n`supabase` exposes only the `SUPABASE_*` defaults, `none` hides all\nsecrets, `string[]` gives only the secrets named in the list.", + "default": "all", + "examples": ["all", ["STRIPE_KEY", "LLM_APIKEY"]] + }, "instances": { "description": "Number of instances to run. Every deploy sends a complete spec, so a count\nrecorded here is what keeps a scaled compute scaled; `--instances` overrides\nit for one deploy. Defaults to 1.", "examples": [3], diff --git a/apps/docs/public/schemas/project-config/v1.json b/apps/docs/public/schemas/project-config/v1.json index 258c28fb1e..3acdaba01b 100644 --- a/apps/docs/public/schemas/project-config/v1.json +++ b/apps/docs/public/schemas/project-config/v1.json @@ -34,6 +34,11 @@ "description": "The maximum number of rows returned from a view, table, or stored procedure. Limits payload size for accidental or malicious requests.", "default": 1000 }, + "db_pool": { + "type": "integer", + "minimum": 1, + "description": "Maximum number of connections in the local PostgREST database pool. Left unset, the default pool size is unchanged." + }, "auto_expose_new_tables": { "type": "boolean", "description": "Controls whether newly-created tables, views, sequences and functions in the `public` schema by `postgres` are reachable through the Data API roles (`anon`, `authenticated`, `service_role`) without explicit GRANTs. When unset, new entities are auto-exposed, matching the cloud default. Set to `false` to revoke the default Data API privileges so new entities require explicit GRANTs, matching a cloud project with the \"Default privileges for new entities\" toggle turned off." @@ -1807,6 +1812,22 @@ "description": "How the compute is reached: `public` gives it an internet-facing URL,\n`private` keeps it reachable only from inside the project. Every deploy\nsends a complete spec, so the value recorded here is what keeps a private\ncompute private; `--exposure` overrides it for one deploy. Defaults to\n`public`.", "examples": ["private"] }, + "secrets_scope": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "description": "controls whether secrets are available: `all` gives access to all defined secrets,\n`supabase` exposes only the `SUPABASE_*` defaults, `none` hides all\nsecrets, `string[]` gives only the secrets named in the list.", + "default": "all", + "examples": ["all", ["STRIPE_KEY", "LLM_APIKEY"]] + }, "instances": { "type": "integer", "minimum": 0, diff --git a/packages/api/src/generated/contracts.ts b/packages/api/src/generated/contracts.ts index 510fd4908e..0afe0cd6c2 100644 --- a/packages/api/src/generated/contracts.ts +++ b/packages/api/src/generated/contracts.ts @@ -400,12 +400,12 @@ export const V1AcceptInviteExternalJitAccessInput = Schema.Struct({ .check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), token: Schema.String.check( @@ -457,12 +457,12 @@ export const V1AcceptInviteExternalJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -708,12 +708,12 @@ export const V1AuthorizeJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -750,6 +750,19 @@ export const V1AuthorizeUserInput = Schema.Struct({ }), ), ), + project_ref: Schema.optionalKey( + Schema.String.check( + Schema.isMinCodePoints(20).annotate({ expected: "a string with at least 20 code points" }), + ) + .check( + Schema.isMaxCodePoints(20).annotate({ expected: "a string with at most 20 code points" }), + ) + .check( + Schema.isPattern(new RegExp("^[a-z]+$", "u")).annotate({ + expected: "a string matching the RegExp ^[a-z]+$", + }), + ), + ), target_flow: Schema.optionalKey(Schema.String), resource: Schema.optionalKey(Schema.String.annotate({ format: "uri" })), }); @@ -3518,6 +3531,7 @@ export const V1GetAuthServiceConfigOutput = Schema.Struct({ saml_external_url: Schema.Union([Schema.String, Schema.Null]), saml_allow_encrypted_assertions: Schema.Union([Schema.Boolean, Schema.Null]), security_sb_forwarded_for_enabled: Schema.Union([Schema.Boolean, Schema.Null]), + external_email_magic_link_disabled: Schema.Union([Schema.Boolean, Schema.Null]), security_captcha_enabled: Schema.Union([Schema.Boolean, Schema.Null]), security_captcha_provider: Schema.Union([ Schema.Union([Schema.Literals(["turnstile", "hcaptcha"]), Schema.Null]), @@ -3623,12 +3637,12 @@ export const V1GetAuthServiceConfigOutput = Schema.Struct({ Schema.String.annotate({ format: "email" }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), Schema.Null, @@ -4055,12 +4069,12 @@ export const V1GetJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -5549,7 +5563,17 @@ export const V1GetProjectUsageApiCountOutput = Schema.Struct({ result: Schema.optionalKey( Schema.Array( Schema.Struct({ - timestamp: Schema.String.annotate({ format: "date-time" }), + timestamp: Schema.String.check( + Schema.isPattern( + new RegExp( + "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z)|(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?)$", + "u", + ), + ).annotate({ + expected: + "a string matching the RegExp ^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z)|(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?)$", + }), + ), total_auth_requests: Schema.Number.check( Schema.isFinite().annotate({ expected: "a finite number" }), ), @@ -6155,12 +6179,12 @@ export const V1InviteExternalJitAccessInput = Schema.Struct({ .check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), roles: Schema.Array( @@ -6196,12 +6220,12 @@ export const V1InviteExternalJitAccessInput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -6217,12 +6241,12 @@ export const V1InviteExternalJitAccessOutput = Schema.Struct({ email: Schema.String.annotate({ format: "email" }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), invite_id: Schema.String.annotate({ format: "uuid" }).check( @@ -6267,12 +6291,12 @@ export const V1InviteExternalJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -6716,12 +6740,12 @@ export const V1ListJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -6779,12 +6803,12 @@ export const V1ListJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -8551,12 +8575,12 @@ export const V1UpdateAuthServiceConfigInput = Schema.Struct({ Schema.String.annotate({ format: "email" }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), Schema.Null, @@ -8704,6 +8728,7 @@ export const V1UpdateAuthServiceConfigInput = Schema.Struct({ security_sb_forwarded_for_enabled: Schema.optionalKey( Schema.Union([Schema.Boolean, Schema.Null]), ), + external_email_magic_link_disabled: Schema.optionalKey(Schema.Boolean), security_captcha_enabled: Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), security_captcha_provider: Schema.optionalKey( Schema.Union([Schema.Literals(["turnstile", "hcaptcha"]), Schema.Null]), @@ -9681,6 +9706,7 @@ export const V1UpdateAuthServiceConfigOutput = Schema.Struct({ saml_external_url: Schema.Union([Schema.String, Schema.Null]), saml_allow_encrypted_assertions: Schema.Union([Schema.Boolean, Schema.Null]), security_sb_forwarded_for_enabled: Schema.Union([Schema.Boolean, Schema.Null]), + external_email_magic_link_disabled: Schema.Union([Schema.Boolean, Schema.Null]), security_captcha_enabled: Schema.Union([Schema.Boolean, Schema.Null]), security_captcha_provider: Schema.Union([ Schema.Union([Schema.Literals(["turnstile", "hcaptcha"]), Schema.Null]), @@ -9786,12 +9812,12 @@ export const V1UpdateAuthServiceConfigOutput = Schema.Struct({ Schema.String.annotate({ format: "email" }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), Schema.Null, @@ -10016,12 +10042,12 @@ export const V1UpdateJitAccessInput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -10078,12 +10104,12 @@ export const V1UpdateJitAccessOutput = Schema.Struct({ cidr: Schema.String.annotate({ format: "cidrv6" }).check( Schema.isPattern( new RegExp( - "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", + "a string matching the RegExp ^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$", }), ), }), @@ -12093,6 +12119,10 @@ export const V2CreateNotebookOutput = Schema.Struct({ }).annotate({ description: "User who last wrote to the notebook." }), Schema.Null, ]), + url: Schema.String.annotate({ + description: "Dashboard link for this notebook.", + format: "uri", + }), content: Schema.Struct({ schema_version: Schema.Number.check( Schema.isFinite().annotate({ expected: "a finite number" }), @@ -12231,12 +12261,12 @@ export const V2CreateOrganizationInvitationsInput = Schema.Struct({ }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), role: Schema.Literals([ @@ -12302,6 +12332,7 @@ export const V2CreateOrganizationInvitationsOutput = Schema.Struct({ "notebook_sort_invalid", "organization_invitation_email_delivery_failed", "organization_invitations_partially_failed", + "organization_inviter_email_missing", "organization_role_name_invalid", "organization_role_not_entitled", "pagination_cursor_invalid", @@ -12367,12 +12398,12 @@ export const V2CreateOrganizationInvitationsOutput = Schema.Struct({ }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), }), @@ -12391,12 +12422,12 @@ export const V2CreateOrganizationInvitationsOutput = Schema.Struct({ }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), }), @@ -12616,12 +12647,12 @@ export const V2DeleteOrganizationInvitationsInput = Schema.Struct({ }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), }), @@ -12641,12 +12672,12 @@ export const V2DeleteOrganizationInvitationsOutput = Schema.Struct({ }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), }), @@ -12994,6 +13025,10 @@ export const V2GetNotebookOutput = Schema.Struct({ }).annotate({ description: "User who last wrote to the notebook." }), Schema.Null, ]), + url: Schema.String.annotate({ + description: "Dashboard link for this notebook.", + format: "uri", + }), content: Schema.Struct({ schema_version: Schema.Number.check( Schema.isFinite().annotate({ expected: "a finite number" }), @@ -14114,6 +14149,10 @@ export const V2ListNotebooksOutput = Schema.Struct({ }).annotate({ description: "User who last wrote to the notebook." }), Schema.Null, ]), + url: Schema.String.annotate({ + description: "Dashboard link for this notebook.", + format: "uri", + }), }), }), ), @@ -14421,12 +14460,12 @@ export const V2ListOrganizationMembersInput = Schema.Struct({ Schema.String.annotate({ format: "email" }).check( Schema.isPattern( new RegExp( - "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "u", ), ).annotate({ expected: - "a string matching the RegExp ^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "a string matching the RegExp ^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", }), ), ), @@ -15257,20 +15296,24 @@ export const V2OrganizationsSlugWebhooksEndpointsGetOutput = Schema.Struct({ ), links: Schema.Struct({ first: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the first page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the first page if available." }), + Schema.Null, + ]), ), - prev: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the previous page.", - }), - next: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the next page.", - }), + prev: Schema.Union([ + Schema.String.annotate({ description: "URL path to the previous page." }), + Schema.Null, + ]), + next: Schema.Union([ + Schema.String.annotate({ description: "URL path to the next page." }), + Schema.Null, + ]), last: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the last page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the last page if available." }), + Schema.Null, + ]), ), }), }); @@ -15607,20 +15650,24 @@ export const V2OrganizationsSlugWebhooksEndpointsIdDeliveriesGetOutput = Schema. ), links: Schema.Struct({ first: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the first page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the first page if available." }), + Schema.Null, + ]), ), - prev: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the previous page.", - }), - next: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the next page.", - }), + prev: Schema.Union([ + Schema.String.annotate({ description: "URL path to the previous page." }), + Schema.Null, + ]), + next: Schema.Union([ + Schema.String.annotate({ description: "URL path to the next page." }), + Schema.Null, + ]), last: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the last page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the last page if available." }), + Schema.Null, + ]), ), }), }); @@ -16724,20 +16771,24 @@ export const V2ProjectsRefWebhooksEndpointsGetOutput = Schema.Struct({ ), links: Schema.Struct({ first: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the first page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the first page if available." }), + Schema.Null, + ]), ), - prev: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the previous page.", - }), - next: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the next page.", - }), + prev: Schema.Union([ + Schema.String.annotate({ description: "URL path to the previous page." }), + Schema.Null, + ]), + next: Schema.Union([ + Schema.String.annotate({ description: "URL path to the next page." }), + Schema.Null, + ]), last: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the last page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the last page if available." }), + Schema.Null, + ]), ), }), }); @@ -17086,20 +17137,24 @@ export const V2ProjectsRefWebhooksEndpointsIdDeliveriesGetOutput = Schema.Struct ), links: Schema.Struct({ first: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the first page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the first page if available." }), + Schema.Null, + ]), ), - prev: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the previous page.", - }), - next: Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the next page.", - }), + prev: Schema.Union([ + Schema.String.annotate({ description: "URL path to the previous page." }), + Schema.Null, + ]), + next: Schema.Union([ + Schema.String.annotate({ description: "URL path to the next page." }), + Schema.Null, + ]), last: Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - description: "URL path to the last page if available.", - }), + Schema.Union([ + Schema.String.annotate({ description: "URL path to the last page if available." }), + Schema.Null, + ]), ), }), }); @@ -18431,6 +18486,10 @@ export const V2UpdateNotebookOutput = Schema.Struct({ }).annotate({ description: "User who last wrote to the notebook." }), Schema.Null, ]), + url: Schema.String.annotate({ + description: "Dashboard link for this notebook.", + format: "uri", + }), content: Schema.Struct({ schema_version: Schema.Number.check( Schema.isFinite().annotate({ expected: "a finite number" }), @@ -18941,6 +19000,7 @@ export const operationDefinitions = { "code_challenge", "code_challenge_method", "organization_slug", + "project_ref", "target_flow", "resource", ], @@ -21117,6 +21177,7 @@ export const operationDefinitions = { "saml_enabled", "saml_external_url", "security_sb_forwarded_for_enabled", + "external_email_magic_link_disabled", "security_captcha_enabled", "security_captcha_provider", "security_captcha_secret", diff --git a/packages/api/src/generated/openapi.json b/packages/api/src/generated/openapi.json index bf7ec1b0d8..95fa84583f 100644 --- a/packages/api/src/generated/openapi.json +++ b/packages/api/src/generated/openapi.json @@ -131,6 +131,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "Persistent branches are not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -732,6 +742,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "The instance size is not available on the organization plan, or the organization has overdue invoices", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -1040,6 +1060,19 @@ "type": "string" } }, + { + "name": "project_ref", + "required": false, + "in": "query", + "description": "Project ref", + "schema": { + "minLength": 20, + "maxLength": 20, + "pattern": "^[a-z]+$", + "example": "abcdefghijklmnopqrst", + "type": "string" + } + }, { "name": "target_flow", "required": false, @@ -1954,6 +1987,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "Custom JWT templates for secret API keys are not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -2164,6 +2207,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "Custom JWT templates for secret API keys are not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -2477,6 +2530,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "Branching or persistent branches are not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -5959,6 +6022,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "An auth setting in the request is not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -6426,6 +6499,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "The restore is not available on the organization plan, or the organization has overdue invoices or a service restriction", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -7059,7 +7142,7 @@ "in": "query", "schema": { "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "example": "2025-03-01T00:00:00Z", "type": "string" } @@ -7070,7 +7153,7 @@ "in": "query", "schema": { "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "example": "2025-03-01T23:59:59Z", "type": "string" } @@ -8972,7 +9055,14 @@ "description": "Unauthorized" }, "402": { - "description": "Maximum number of functions reached for Plan" + "description": "Maximum number of functions reached for Plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } }, "403": { "description": "Forbidden action" @@ -9044,7 +9134,14 @@ "description": "Unauthorized" }, "402": { - "description": "Maximum number of functions reached for Plan" + "description": "Maximum number of functions reached for Plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } }, "403": { "description": "Forbidden action" @@ -9137,7 +9234,14 @@ "description": "Unauthorized" }, "402": { - "description": "Maximum number of functions reached for Plan" + "description": "Maximum number of functions reached for Plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } }, "403": { "description": "Forbidden action" @@ -9672,6 +9776,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "Disk modifications are not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -9885,6 +9999,16 @@ "401": { "description": "Unauthorized" }, + "402": { + "description": "A storage feature or file size limit in the request is not available on the organization plan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlanGateErrorBody" + } + } + } + }, "403": { "description": "Forbidden action" }, @@ -14412,7 +14536,7 @@ "primary_email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" } }, "type": "object" @@ -15202,7 +15326,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -15226,50 +15350,22 @@ "first": { "description": "URL path to the first page if available.", "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "prev": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the previous page.", - "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0" + "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0", + "type": ["string", "null"] }, "next": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the next page.", - "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20" + "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20", + "type": ["string", "null"] }, "last": { "description": "URL path to the last page if available.", "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=30", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] } }, "required": ["prev", "next"] @@ -15979,7 +16075,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -16821,7 +16917,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -17557,7 +17653,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -18385,7 +18481,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -19329,7 +19425,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -20154,29 +20250,15 @@ ] }, "error_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "error_message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "attempt_timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of the attempt." }, "event": { @@ -20241,7 +20323,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of event publication." } }, @@ -20271,50 +20353,22 @@ "first": { "description": "URL path to the first page if available.", "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "prev": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the previous page.", - "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7" + "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": ["string", "null"] }, "next": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the next page.", - "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4" + "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": ["string", "null"] }, "last": { "description": "URL path to the last page if available.", "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] } }, "required": ["prev", "next"] @@ -22044,29 +22098,15 @@ ] }, "error_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "error_message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "attempt_timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of the attempt." }, "event": { @@ -22131,7 +22171,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of event publication." } }, @@ -23690,7 +23730,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -23714,50 +23754,22 @@ "first": { "description": "URL path to the first page if available.", "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "prev": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the previous page.", - "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0" + "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=0", + "type": ["string", "null"] }, "next": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the next page.", - "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20" + "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=20", + "type": ["string", "null"] }, "last": { "description": "URL path to the last page if available.", "example": "/v2/organization/slug/webhooks/endpoints?page[limit]=10&page[offset]=30", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] } }, "required": ["prev", "next"] @@ -24465,7 +24477,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -25305,7 +25317,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -26039,7 +26051,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -26865,7 +26877,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -27807,7 +27819,7 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of endpoint's creation." } }, @@ -28630,29 +28642,15 @@ ] }, "error_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "error_message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "attempt_timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of the attempt." }, "event": { @@ -28717,7 +28715,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of event publication." } }, @@ -28747,50 +28745,22 @@ "first": { "description": "URL path to the first page if available.", "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "prev": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the previous page.", - "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7" + "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": ["string", "null"] }, "next": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], "description": "URL path to the next page.", - "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4" + "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": ["string", "null"] }, "last": { "description": "URL path to the last page if available.", "example": "/v2/organizations/slug/webhooks/endpoints/{id}/deliveries?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] } }, "required": ["prev", "next"] @@ -30516,29 +30486,15 @@ ] }, "error_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "error_message": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] + "type": ["string", "null"] }, "attempt_timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of the attempt." }, "event": { @@ -30603,7 +30559,7 @@ "timestamp": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Timestamp of event publication." } }, @@ -32166,17 +32122,17 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "review_requested_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "with_data": { "type": "boolean" @@ -32188,7 +32144,7 @@ "deletion_scheduled_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "preview_project_status": { "type": "string", @@ -32225,6 +32181,36 @@ "with_data" ] }, + "PlanGateErrorBody": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Human-readable explanation of the plan gate" + }, + "error": { + "description": "Present on entitlement denials. Other errors with this status code (validation, billing state) carry only message.", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Machine-readable marker for plan-gated denials", + "enum": ["entitlement_required"] + }, + "feature": { + "type": "string", + "description": "Entitlement feature key that failed the check" + }, + "upgrade_url": { + "description": "Billing page URL for the organization, present when the org is resolvable", + "type": "string" + } + }, + "required": ["code", "feature"] + } + }, + "required": ["message"] + }, "BranchDeleteResponse_Output": { "type": "object", "properties": { @@ -33341,13 +33327,13 @@ "inserted_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "nullable": true }, "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "nullable": true } }, @@ -33808,7 +33794,7 @@ "description": "When the change in `pending_config` was requested. Send it as `requested_at` to the review endpoint.", "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "status": { "type": "string", @@ -33817,12 +33803,12 @@ "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "applied_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": ["entitlement", "config", "status"] @@ -33949,12 +33935,12 @@ "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "applied_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "status": { "type": "string", @@ -33974,7 +33960,7 @@ "requested_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "description": "The `pending_requested_at` of the change being reviewed. Only that change is resolved: if another one has replaced it, the request gets a 409." } }, @@ -34304,36 +34290,6 @@ }, "required": ["status"] }, - "PlanGateErrorBody": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "Human-readable explanation of the plan gate" - }, - "error": { - "description": "Present on entitlement denials. Other errors with this status code (validation, billing state) carry only message.", - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "Machine-readable marker for plan-gated denials", - "enum": ["entitlement_required"] - }, - "feature": { - "type": "string", - "description": "Entitlement feature key that failed the check" - }, - "upgrade_url": { - "description": "Billing page URL for the organization, present when the org is resolvable", - "type": "string" - } - }, - "required": ["code", "feature"] - } - }, - "required": ["message"] - }, "VanitySubdomainBody": { "type": "object", "properties": { @@ -34949,12 +34905,12 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": ["id", "algorithm", "status", "public_jwk", "created_at", "updated_at"] @@ -35209,12 +35165,12 @@ "created_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": ["id", "algorithm", "status", "public_jwk", "created_at", "updated_at"] @@ -36041,6 +35997,10 @@ "type": "boolean", "nullable": true }, + "external_email_magic_link_disabled": { + "type": "boolean", + "nullable": true + }, "security_captcha_enabled": { "type": "boolean", "nullable": true @@ -36137,7 +36097,7 @@ "sms_test_otp_valid_until": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "nullable": true }, "sms_textlocal_api_key": { @@ -36191,7 +36151,7 @@ "smtp_admin_email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "nullable": true }, "smtp_host": { @@ -36435,6 +36395,7 @@ "saml_external_url", "saml_allow_encrypted_assertions", "security_sb_forwarded_for_enabled", + "external_email_magic_link_disabled", "security_captcha_enabled", "security_captcha_provider", "security_captcha_secret", @@ -36505,7 +36466,7 @@ "smtp_admin_email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "nullable": true }, "smtp_host": { @@ -36709,6 +36670,9 @@ "type": "boolean", "nullable": true }, + "external_email_magic_link_disabled": { + "type": "boolean" + }, "security_captcha_enabled": { "type": "boolean", "nullable": true @@ -36823,8 +36787,8 @@ "nullable": true }, "security_update_password_require_current_password": { - "type": "boolean", "description": "Require the user's current password when updating their password.", + "type": "boolean", "nullable": true }, "security_refresh_token_reuse_interval": { @@ -36887,7 +36851,7 @@ "sms_test_otp_valid_until": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "nullable": true }, "sms_textlocal_api_key": { @@ -38041,7 +38005,7 @@ "observed_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$" } }, "required": [ @@ -38125,8 +38089,7 @@ "properties": { "timestamp": { "type": "string", - "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z)|(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?)$" }, "total_auth_requests": { "type": "number" @@ -38539,7 +38502,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38630,7 +38593,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38708,7 +38671,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38779,7 +38742,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38849,7 +38812,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38891,7 +38854,7 @@ "type": "string", "minLength": 1, "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "roles": { "type": "array", @@ -38930,7 +38893,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -38971,7 +38934,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "invite_id": { "type": "string", @@ -39014,7 +38977,7 @@ "cidr": { "type": "string", "format": "cidrv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$" } }, "required": ["cidr"] @@ -39039,7 +39002,7 @@ "type": "string", "minLength": 1, "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$" }, "token": { "type": "string", @@ -40355,8 +40318,8 @@ "type": "object", "properties": { "private_only": { - "type": "boolean", "description": "Whether to only allow private channels", + "type": "boolean", "nullable": true }, "connection_pool": { @@ -40423,8 +40386,8 @@ "nullable": true }, "suspend": { - "type": "boolean", "description": "Disables the Realtime service for this project when true. Set to false to re-enable it.", + "type": "boolean", "nullable": true }, "presence_enabled": { @@ -40434,7 +40397,7 @@ "admin_suspended_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "description": "If set, the Realtime service has been suspended by an admin.", "nullable": true } @@ -41297,7 +41260,7 @@ "completed_on": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "nullable": true } }, @@ -41329,7 +41292,7 @@ "updated_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "description": "Timestamp of when the backup schedule was last updated.", "example": "2026-05-04T14:40:44+00:00" } @@ -42074,7 +42037,7 @@ }, "required": ["data"] }, - "ErrorResponseBodyAPIErrorObject": { + "APIErrorObject": { "type": "object", "properties": { "id": { @@ -42111,6 +42074,7 @@ "notebook_sort_invalid", "organization_invitation_email_delivery_failed", "organization_invitations_partially_failed", + "organization_inviter_email_missing", "organization_role_name_invalid", "organization_role_not_entitled", "pagination_cursor_invalid", @@ -42225,7 +42189,7 @@ "type": "object", "properties": { "error": { - "$ref": "#/components/schemas/ErrorResponseBodyAPIErrorObject" + "$ref": "#/components/schemas/APIErrorObject" } }, "required": ["error"] @@ -43157,7 +43121,7 @@ "observed_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$" + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$" } }, "required": [ @@ -44040,6 +44004,11 @@ "required": ["id", "username"], "description": "User who last wrote to the notebook.", "nullable": true + }, + "url": { + "type": "string", + "format": "uri", + "description": "Dashboard link for this notebook." } }, "required": [ @@ -44049,7 +44018,8 @@ "inserted_at", "updated_at", "owner", - "updated_by" + "updated_by", + "url" ] } }, @@ -44060,27 +44030,27 @@ "type": "object", "properties": { "first": { - "type": "string", "description": "URL path to the first page if available.", "example": "/v2/projects/{ref}/notebooks?page[size]=10", + "type": "string", "nullable": true }, "prev": { - "type": "string", "description": "URL path to the previous page.", "example": "/v2/projects/{ref}/notebooks?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": "string", "nullable": true }, "next": { - "type": "string", "description": "URL path to the next page.", "example": "/v2/projects/{ref}/notebooks?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": "string", "nullable": true }, "last": { - "type": "string", "description": "URL path to the last page if available.", "example": "/v2/projects/{ref}/notebooks?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", + "type": "string", "nullable": true } }, @@ -44150,6 +44120,11 @@ "description": "User who last wrote to the notebook.", "nullable": true }, + "url": { + "type": "string", + "format": "uri", + "description": "Dashboard link for this notebook." + }, "content": { "type": "object", "properties": { @@ -44382,6 +44357,7 @@ "updated_at", "owner", "updated_by", + "url", "content" ] } @@ -45065,7 +45041,7 @@ "shared_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "description": "The time and date at which the AWS Resource Share Association was requested from Supabase. `null` means that the association was not yet requested while the PrivateLink Association is pending.", "nullable": true }, @@ -45193,7 +45169,7 @@ "shared_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$", "description": "The time and date at which the AWS Resource Share Association was requested from Supabase. `null` means that the association was not yet requested while the PrivateLink Association is pending.", "nullable": true }, @@ -45641,7 +45617,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "description": "Email address of the invitation receipient.", "example": "hello@example.com" }, @@ -45725,6 +45701,7 @@ "notebook_sort_invalid", "organization_invitation_email_delivery_failed", "organization_invitations_partially_failed", + "organization_inviter_email_missing", "organization_role_name_invalid", "organization_role_not_entitled", "pagination_cursor_invalid", @@ -45829,7 +45806,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "description": "Email address of the invitation receipient.", "example": "hello@example.com" } @@ -45859,7 +45836,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "description": "Email address of the invitation receipient.", "example": "hello@example.com" } @@ -45894,7 +45871,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "description": "Email address of the invitation receipient.", "example": "hello@example.com" } @@ -45927,7 +45904,7 @@ "email": { "type": "string", "format": "email", - "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", + "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$", "description": "Email address of the invitation receipient.", "example": "hello@example.com" } @@ -45963,13 +45940,13 @@ "type": "object", "properties": { "username": { - "type": "string", "description": "Member's username", + "type": "string", "nullable": true }, "primary_email": { - "type": "string", "description": "Member's primary email", + "type": "string", "nullable": true }, "mfa_enabled": { @@ -45981,8 +45958,8 @@ "description": "Whether this member is a Single Sign-On user" }, "avatar_url": { - "type": "string", "description": "Member's avatar URL", + "type": "string", "nullable": true }, "roles": { @@ -46039,27 +46016,27 @@ "type": "object", "properties": { "first": { - "type": "string", "description": "URL path to the first page if available.", "example": "/v2/organizations/my-org/members?page[size]=10", + "type": "string", "nullable": true }, "prev": { - "type": "string", "description": "URL path to the previous page.", "example": "/v2/organizations/my-org/members?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": "string", "nullable": true }, "next": { - "type": "string", "description": "URL path to the next page.", "example": "/v2/organizations/my-org/members?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": "string", "nullable": true }, "last": { - "type": "string", "description": "URL path to the last page if available.", "example": "/v2/organizations/my-org/members?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", + "type": "string", "nullable": true } }, @@ -46321,27 +46298,27 @@ "type": "object", "properties": { "first": { - "type": "string", "description": "URL path to the first page if available.", "example": "/v2/organizations/my-org/projects?page[size]=10", + "type": "string", "nullable": true }, "prev": { - "type": "string", "description": "URL path to the previous page.", "example": "/v2/organizations/my-org/projects?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": "string", "nullable": true }, "next": { - "type": "string", "description": "URL path to the next page.", "example": "/v2/organizations/my-org/projects?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": "string", "nullable": true }, "last": { - "type": "string", "description": "URL path to the last page if available.", "example": "/v2/organizations/my-org/projects?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", + "type": "string", "nullable": true } }, @@ -46473,27 +46450,27 @@ "type": "object", "properties": { "first": { - "type": "string", "description": "URL path to the first page if available.", "example": "/v2/organizations/my-org/integrations/github/connections?page[size]=10", + "type": "string", "nullable": true }, "prev": { - "type": "string", "description": "URL path to the previous page.", "example": "/v2/organizations/my-org/integrations/github/connections?page[size]=10&page[before]=019adf7d-4513-74c5-bb9a-f1bc0f7a95d7", + "type": "string", "nullable": true }, "next": { - "type": "string", "description": "URL path to the next page.", "example": "/v2/organizations/my-org/integrations/github/connections?page[size]=10&page[after]=019adf7d-4513-7062-b292-78b86cc470a4", + "type": "string", "nullable": true }, "last": { - "type": "string", "description": "URL path to the last page if available.", "example": "/v2/organizations/my-org/integrations/github/connections?page[size]=10&page[after]=019adf7d-4513-71ba-b264-21900edb4295", + "type": "string", "nullable": true } }, @@ -46551,13 +46528,13 @@ "start_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Start of the occurrence, inclusive." }, "end_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "End of the occurrence, exclusive." } }, @@ -46573,13 +46550,13 @@ "start_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "Start of the occurrence, inclusive." }, "end_at": { "type": "string", "format": "date-time", - "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$", + "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$", "description": "End of the occurrence, exclusive." } }, @@ -46596,170 +46573,6 @@ } }, "required": ["data"] - }, - "APIErrorObject": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string", - "enum": [ - "bad_request", - "forbidden", - "internal_server_error", - "not_found", - "payment_required", - "rate_limit_exceeded", - "request_timeout", - "request_too_large", - "unauthorized", - "validation_failed", - "agentic_credential_not_found", - "backup_unsupported", - "branch_admin_required", - "compute_build_context_too_large", - "compute_build_in_progress", - "compute_deploy_rate_limit_exceeded", - "compute_instance_limit_exceeded", - "compute_instance_not_found", - "compute_not_enabled", - "compute_request_rejected", - "compute_unavailable", - "notebook_cell_duplicate", - "notebook_cell_unknown", - "notebook_disabled", - "notebook_not_found", - "notebook_sort_invalid", - "organization_invitation_email_delivery_failed", - "organization_invitations_partially_failed", - "organization_role_name_invalid", - "organization_role_not_entitled", - "pagination_cursor_invalid", - "project_branch_resync_unsupported", - "project_not_found", - "project_privatelink_disabled", - "project_transfer_disabled", - "delivery_not_found", - "endpoint_disabled", - "endpoint_event_type_not_subscribed", - "endpoint_not_found", - "endpoint_url_unresolvable", - "webhooks_access_disabled" - ] - }, - "message": { - "type": "string" - }, - "description": { - "type": "string" - }, - "links": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "object", - "properties": { - "href": { - "type": "string" - }, - "rel": { - "type": "string" - }, - "title": { - "type": "string" - }, - "type": { - "type": "string" - }, - "describedby": { - "type": "string" - }, - "meta": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - }, - "required": ["href"] - } - }, - "meta": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - }, - "issues": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "code": { - "type": "string" - }, - "message": { - "type": "string" - }, - "description": { - "type": "string" - }, - "links": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": { - "type": "object", - "properties": { - "href": { - "type": "string" - }, - "rel": { - "type": "string" - }, - "title": { - "type": "string" - }, - "type": { - "type": "string" - }, - "describedby": { - "type": "string" - }, - "meta": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - }, - "required": ["href"] - } - }, - "meta": { - "type": "object", - "propertyNames": { - "type": "string" - }, - "additionalProperties": {} - } - }, - "required": ["code", "message"] - } - } - }, - "required": ["code", "message"] } } } diff --git a/packages/config/AGENTS.md b/packages/config/AGENTS.md index ae9425aab5..8c56f33c73 100644 --- a/packages/config/AGENTS.md +++ b/packages/config/AGENTS.md @@ -46,9 +46,9 @@ artifacts (`./schema.json`, `./project-schema.json`). `AppliedConfigEdit` types — the config diff engine itself, `diffProjectConfig` and its `ConfigChange`/`ConfigChangeClass`/`ConfigChangeCounts`/`ConfigChangeSet`/ `DiffProjectConfigOptions` types, lives on `.`, not here — see above), - `dualScopeProjectConfigPaths`, the raw `[remotes.*]` helpers `remoteNameForProjectRef`/ - `remoteProjectIdEntries`, the atomic single-file writer `writeCliConfigDocumentText`/ - `CliConfigWriteError`, and the two pipeline stages `loadCliConfig` is built from — + `updateJsonDocument` (comment-preserving JSON/JSONC rewrite), `convertCliConfigTomlToJsonc` (`supabase config convert`: a pure, verified `config.toml` → `config.jsonc` converter that carries comments over; an Effect failing with `CliConfigConvertError`) with its `MovedTomlComment` type, `dualScopeProjectConfigPaths`, the raw `[remotes.*]` helpers `remoteNameForProjectRef`/ + `remoteProjectIdEntries`, the atomic single-file writers `writeCliConfigDocumentText` (replace) and + `createCliConfigDocumentText` (create, never replacing)/`CliConfigWriteError`, and the two pipeline stages `loadCliConfig` is built from — `parseCliConfigDocumentFile` (discover and parse) with `mergeParsedCliConfig` (merge the `[remotes.*]` block a caller-supplied `selectRemote` picks) and `decodeMergedCliConfig` (interpolate `env()` against a caller-supplied env record, then decode and validate, optionally on an overlaid document) — kept off `./effect`'s public surface deliberately (no consumer outside diff --git a/packages/config/docs/cli-config-loading.md b/packages/config/docs/cli-config-loading.md index 01a9f72482..b5834f63d3 100644 --- a/packages/config/docs/cli-config-loading.md +++ b/packages/config/docs/cli-config-loading.md @@ -97,7 +97,7 @@ to check only that exact directory, with no ancestor climb. Within one discovered `supabase/` directory, `config.json` or `config.jsonc` takes precedence over `config.toml` when both exist. Discovery never fails on a `config.json` + `config.jsonc` pair; loading -and saving do. +and saving do. `supabase config convert` migrates a `config.toml` project to `config.jsonc`. This produces a `CliProjectPaths` (the type is exported from `@supabase/config`): diff --git a/packages/config/src/api.ts b/packages/config/src/api.ts index 082a8a7a31..fc554bb50b 100644 --- a/packages/config/src/api.ts +++ b/packages/config/src/api.ts @@ -56,6 +56,16 @@ export const api = Schema.Struct({ tags, links, }).pipe(Schema.withDecodingDefaultKey(Effect.succeed(defaultMaxRows))), + db_pool: Schema.optionalKey( + Schema.Int.annotate({ expected: "a whole number of connections" }) + .check(Schema.isGreaterThanOrEqualTo(1).annotate({ expected: "one or more connections" })) + .annotate({ + description: + "Maximum number of connections in the local PostgREST database pool. Left unset, the default pool size is unchanged.", + tags, + links, + }), + ), auto_expose_new_tables: Schema.optionalKey( Schema.Boolean.annotate({ description: diff --git a/packages/config/src/base.ts b/packages/config/src/base.ts index 72eaf53d81..e32f6d951d 100644 --- a/packages/config/src/base.ts +++ b/packages/config/src/base.ts @@ -83,11 +83,13 @@ export const CliConfigSchema = Schema.Struct({ remotes: RemotesSchema.pipe(Schema.withDecodingDefault(Effect.succeed({}))), }); +/** `allowTrailingCommas` keeps VS Code from flagging the trailing commas in generated `config.jsonc`. */ export function toCliConfigJsonSchema() { - return toPublishedJsonSchemaDocument(CliConfigSchema, { + const { $schema, ...rest } = toPublishedJsonSchemaDocument(CliConfigSchema, { onExcessProperty: "error", acceptEnvReferences: true, }); + return { $schema, allowTrailingCommas: true, ...rest }; } export type CliConfig = typeof CliConfigSchema.Type; diff --git a/packages/config/src/compute.ts b/packages/config/src/compute.ts index 57ed4b5427..b934ca51ab 100644 --- a/packages/config/src/compute.ts +++ b/packages/config/src/compute.ts @@ -44,6 +44,18 @@ const computeEntry = Schema.Struct({ tags, }), ), + secrets_scope: Schema.optionalKey( + Schema.Union([Schema.String, Schema.Array(Schema.String)]), + ).annotate({ + description: dedent` + controls whether secrets are available: \`all\` gives access to all defined secrets, + \`supabase\` exposes only the \`SUPABASE_*\` defaults, \`none\` hides all + secrets, \`string[]\` gives only the secrets named in the list. + `, + examples: ["all", ["STRIPE_KEY", "LLM_APIKEY"]], + default: "all", + tags, + }), instances: Schema.optionalKey( // Bounded to match the Management API's input schema; an out-of-range value would // be dropped rather than sent, deploying a different count than the config asked for. diff --git a/packages/config/src/config-convert-comments.ts b/packages/config/src/config-convert-comments.ts new file mode 100644 index 0000000000..8aac3b9614 --- /dev/null +++ b/packages/config/src/config-convert-comments.ts @@ -0,0 +1,615 @@ +import * as SmolToml from "smol-toml"; +import { + commentedKvLines, + INDENT, + toJsoncComment, + unsupportedReason, + withComma, +} from "./config-convert-values.ts"; +import { scanTomlDocument } from "./toml-scan.ts"; + +type CommentedLine = + | { readonly kind: "prose"; readonly text: string } + | { readonly kind: "kv"; readonly path: ReadonlyArray; readonly value: unknown }; + +export interface CommentedNode { + readonly at: number; + readonly lead: Array; + readonly own: Array; + readonly children: Map; + elements?: Array; +} + +export interface PlacedComment { + readonly at: number; + readonly source: Array; + readonly blankBefore: boolean; +} + +export interface RenderedComment { + readonly at: number; + readonly lines: Array; + readonly blankBefore: boolean; +} + +/** The part of a converted table that commented-out examples attach to. */ +export interface CommentHost { + readonly kind: "table"; + readonly entries: ReadonlyMap; + readonly placed: Array; + readonly forest: CommentedNode; +} + +type CommentLine = + | { readonly kind: "prose"; readonly raw: string } + | { + readonly kind: "kv"; + readonly raw: string; + readonly path: ReadonlyArray; + readonly value: unknown; + } + | { + readonly kind: "header"; + readonly raw: string; + readonly path: ReadonlyArray; + readonly isArray: boolean; + }; + +type HeaderLine = Extract; + +export function newCommentedNode(at: number): CommentedNode { + return { at, lead: [], own: [], children: new Map() }; +} + +function commentOut(lines: ReadonlyArray): Array { + return lines.map((line) => `// ${line}`); +} + +function placedLines(line: CommentedLine): Array { + return line.kind === "prose" + ? [line.text] + : commentOut(withComma(commentedKvLines(line.path, line.value, ""), ",")); +} + +type CommentedMember = + | CommentedLine + | { readonly kind: "child"; readonly key: string; readonly node: CommentedNode }; + +/** Orders a node's members, nesting dotted keys under a shared object when a sibling key or a + * commented table already uses their first segment, so uncommenting never yields duplicate keys. */ +function commentedMembers(node: CommentedNode): Array { + const counts = new Map(); + for (const line of node.own) { + if (line.kind === "kv" && line.path.length > 1) { + const key = line.path[0] ?? ""; + counts.set(key, (counts.get(key) ?? 0) + 1); + } + } + const extra = new Map>(); + const groups = new Map(); + const members: Array = []; + let prose: Array = []; + const flushProse = () => { + members.push(...prose); + prose = []; + }; + for (const line of node.own) { + if (line.kind === "prose") { + prose.push(line); + continue; + } + const key = line.path.length > 1 ? (line.path[0] ?? "") : undefined; + const child = key === undefined ? undefined : node.children.get(key); + if ( + key === undefined || + child?.elements !== undefined || + (child === undefined && (counts.get(key) ?? 0) < 2) + ) { + flushProse(); + members.push(line); + continue; + } + const rest: CommentedLine = { kind: "kv", path: line.path.slice(1), value: line.value }; + if (child !== undefined) { + extra.set(key, [...(extra.get(key) ?? []), ...prose, rest]); + prose = []; + continue; + } + let group = groups.get(key); + if (group === undefined) { + flushProse(); + group = newCommentedNode(node.at); + groups.set(key, group); + members.push({ kind: "child", key, node: group }); + } + group.own.push(...prose, rest); + prose = []; + } + flushProse(); + for (const [key, child] of node.children) { + const added = extra.get(key); + members.push({ + kind: "child", + key, + node: added === undefined ? child : { ...child, own: [...child.own, ...added] }, + }); + } + return members; +} + +function placedBlockLines( + lines: ReadonlyArray, + children: ReadonlyMap = new Map(), +): Array { + const node = newCommentedNode(0); + node.own.push(...lines); + for (const [key, child] of children) { + node.children.set(key, child); + } + return commentedMembers(node).flatMap((member) => + member.kind === "child" + ? [ + ...member.node.lead, + ...commentOut(withComma(commentedChild(member.key, member.node, ""), ",")), + ] + : placedLines(member), + ); +} + +type HostItem = + | { + readonly kind: "placed"; + readonly at: number; + readonly blankBefore: boolean; + readonly input: ReadonlyArray; + readonly source: Array; + readonly children: Map; + } + | { + readonly kind: "forest"; + readonly at: number; + readonly key: string; + readonly node: CommentedNode; + }; + +/** Renders a table's commented examples in source order, merging commented dotted keys into the + * first example that uses their first segment, so uncommenting several never yields duplicate keys. */ +export function hostComments(host: CommentHost): Array { + const items: Array = [ + ...host.placed.map((block): HostItem => ({ + kind: "placed", + at: block.at, + blankBefore: block.blankBefore, + input: block.source, + source: [], + children: new Map(), + })), + ...[...host.forest.children].map(([key, node]): HostItem => ({ + kind: "forest", + at: node.at, + key, + node, + })), + ]; + items.sort((a, b) => a.at - b.at); + const owners = new Map(); + const merged = new Set(); + for (const item of items) { + if (item.kind === "forest") { + const owner = owners.get(item.key); + if (owner?.kind === "placed" && item.node.elements === undefined) { + owner.children.set(item.key, item.node); + merged.add(item); + } else if (owner === undefined && item.node.elements === undefined) { + owners.set(item.key, item); + } + continue; + } + let prose: Array = []; + for (const line of item.input) { + if (line.kind === "prose") { + prose.push(line); + continue; + } + const key = line.path.length > 1 ? line.path[0] : undefined; + const owner = key === undefined ? undefined : owners.get(key); + if (owner?.kind === "forest") { + owner.node.own.push(...prose, { kind: "kv", path: line.path.slice(1), value: line.value }); + } else if (owner !== undefined && owner !== item) { + owner.source.push(...prose, line); + } else { + if (key !== undefined && owner === undefined) { + owners.set(key, item); + } + item.source.push(...prose, line); + } + prose = []; + } + item.source.push(...prose); + } + return items.flatMap((item): Array => { + if (merged.has(item)) { + return []; + } + if (item.kind === "forest") { + const { key, node } = item; + return [ + { + at: item.at, + blankBefore: true, + lines: [...node.lead, ...commentOut(withComma(commentedChild(key, node, ""), ","))], + }, + ]; + } + const lines = placedBlockLines(item.source, item.children); + return lines.length === 0 ? [] : [{ at: item.at, blankBefore: item.blankBefore, lines }]; + }); +} + +function commentedBody(node: CommentedNode, indent: string): Array { + const members = commentedMembers(node).flatMap((member) => + member.kind === "prose" + ? [{ data: false, lines: [`${indent}${member.text}`] }] + : member.kind === "kv" + ? [{ data: true, lines: commentedKvLines(member.path, member.value, indent) }] + : [ + ...(member.node.lead.length > 0 + ? [{ data: false, lines: member.node.lead.map((line) => `${indent}${line}`) }] + : []), + { data: true, lines: commentedChild(member.key, member.node, indent) }, + ], + ); + const lastData = members.map((member) => member.data).lastIndexOf(true); + return members.flatMap((member, index) => + member.data && index < lastData ? withComma(member.lines, ",") : member.lines, + ); +} + +function commentedObject(node: CommentedNode, indent: string, prefix: string): Array { + const body = commentedBody(node, `${indent}${INDENT}`); + return body.length === 0 + ? [`${indent}${prefix}{}`] + : [`${indent}${prefix}{`, ...body, `${indent}}`]; +} + +function commentedChild(key: string, node: CommentedNode, indent: string): Array { + const name = JSON.stringify(key); + const elements = node.elements; + if (elements === undefined) { + return commentedObject(node, indent, `${name}: `); + } + const elementIndent = `${indent}${INDENT}`; + const items = elements.flatMap((element, index) => [ + ...element.lead.map((line) => `${elementIndent}${line}`), + ...withComma( + commentedObject(element, elementIndent, ""), + index < elements.length - 1 ? "," : "", + ), + ]); + return [`${indent}${name}: [`, ...items, `${indent}]`]; +} + +function parseToml(text: string): Record | undefined { + try { + return SmolToml.parse(text); + } catch { + return undefined; + } +} + +function hasSpacedDot(text: string): boolean { + return /\s\.|\.\s/.test(text.replace(/"[^"]*"|'[^']*'/g, "q")); +} + +/** Whether a run of source comments holds a commented key or table header. */ +export function holdsExample(rawLines: ReadonlyArray): boolean { + return rawLines.some((raw) => classifyComment(raw).kind !== "prose"); +} + +function classifyComment(raw: string): CommentLine { + const prose: CommentLine = { kind: "prose", raw }; + const body = raw.trim().slice(1).replace(/^ /, ""); + const scan = scanTomlDocument(body); + const token = "error" in scan || scan.tokens.length !== 1 ? undefined : scan.tokens[0]; + if ( + token === undefined || + (token.kind !== "header" && token.kind !== "kv") || + token.commentStart !== undefined || + parseToml(body) === undefined + ) { + return prose; + } + if (token.kind === "header") { + return hasSpacedDot(body) + ? prose + : { kind: "header", raw, path: token.path, isArray: token.isArrayOfTables }; + } + if (hasSpacedDot(body.slice(0, token.valueStart))) { + return prose; + } + const value = parseToml(`v = ${body.slice(token.valueStart, token.valueEnd)}`)?.["v"]; + if (token.valueComments.length > 0 || unsupportedReason(value) !== undefined) { + return prose; + } + return { kind: "kv", raw, path: token.path, value }; +} + +function mergeCommented( + forest: CommentedNode, + missing: ReadonlyArray, + isArray: boolean, + at: number, + lead: ReadonlyArray, + own: ReadonlyArray, +): CommentedNode | undefined { + let node = forest; + let leadNode: CommentedNode | undefined; + for (const [index, segment] of missing.entries()) { + const holder = node.elements?.at(-1) ?? node; + const last = index === missing.length - 1; + const existing = holder.children.get(segment); + if (existing === undefined) { + const child = newCommentedNode(at); + if (last && isArray) { + child.elements = [newCommentedNode(at)]; + } + holder.children.set(segment, child); + leadNode ??= child; + node = child; + } else if (last && isArray) { + if (existing.elements === undefined) { + return undefined; + } + leadNode = newCommentedNode(at); + existing.elements.push(leadNode); + node = existing; + } else if (last && existing.elements !== undefined) { + return undefined; + } else { + node = existing; + } + } + const target = node.elements?.at(-1) ?? node; + if (leadNode === undefined) { + target.own.push(...lead.map((text): CommentedLine => ({ kind: "prose", text })), ...own); + } else { + leadNode.lead.push(...lead); + target.own.push(...own); + } + return target; +} + +/** Where the keys of a commented table example go, so a later group separated from it only by + * blank lines continues the same example. */ +export type OpenBlock = + | { readonly kind: "table"; readonly host: CommentHost } + | { readonly kind: "forest"; readonly node: CommentedNode } + | { readonly kind: "verbatim"; readonly host: CommentHost }; + +function proseLine(text: string): CommentedLine { + return { kind: "prose", text }; +} + +function toCommentedLine(line: CommentLine): CommentedLine { + return line.kind === "kv" + ? { kind: "kv", path: line.path, value: line.value } + : { kind: "prose", text: toJsoncComment(line.raw) }; +} + +function continueBlock(block: OpenBlock, lines: ReadonlyArray, at: number): void { + if (block.kind === "forest") { + block.node.own.push(...lines.map(toCommentedLine)); + return; + } + if (block.kind === "table") { + placeResolved(block.host, [], lines, at, true); + return; + } + block.host.placed.push({ + at, + source: lines.map((line) => proseLine(toJsoncComment(line.raw))), + blankBefore: true, + }); +} + +/** Places commented lines in `table`, moving each dotted key to the deepest existing table on its + * path; prose travels with the key below it. Returns the block placed in `table` itself. */ +function placeResolved( + table: CommentHost, + lead: ReadonlyArray, + lines: ReadonlyArray, + at: number, + blankBefore: boolean, +): PlacedComment | undefined { + const byHost = new Map>([[table, []]]); + let firstHost: CommentHost | undefined; + let lastHost = table; + let prose: Array = [...lead]; + for (const line of lines) { + if (line.kind !== "kv") { + prose.push(toCommentedLine(line)); + continue; + } + const { host, path } = deepestTable(table, line.path); + byHost.set(host, [ + ...(byHost.get(host) ?? []), + ...prose, + { kind: "kv", path, value: line.value }, + ]); + firstHost ??= host; + lastHost = host; + prose = []; + } + byHost.get(lastHost)?.push(...prose); + firstHost ??= table; + let own: PlacedComment | undefined; + for (const [host, source] of byHost) { + if (source.length === 0) { + continue; + } + const block = { at, source, blankBefore: host === firstHost && blankBefore }; + host.placed.push(block); + if (host === table) { + own = block; + } + } + return own; +} + +function placeBlock( + root: CommentHost, + header: HeaderLine, + lead: ReadonlyArray, + body: ReadonlyArray, + at: number, +): { readonly stored: number; readonly open?: OpenBlock } { + const hasKeys = body.some((line) => line.kind === "kv"); + if (!hasKeys && header.path.length === 1) { + return { stored: 0 }; + } + let table = root; + let depth = 0; + for (const segment of header.path) { + const child = table.entries.get(segment); + if (child === undefined) { + break; + } + if (child.kind !== "table") { + return { stored: 0 }; + } + table = child; + depth++; + } + const leadText = lead.map((line) => toJsoncComment(line.raw)); + const stored = lead.length + body.length + 1; + if (depth === header.path.length) { + if (header.isArray || !hasKeys) { + return { stored: 0 }; + } + placeResolved(table, leadText.map(proseLine), body, at, true); + return { stored, open: { kind: "table", host: table } }; + } + const own = body.map(toCommentedLine); + const node = mergeCommented( + table.forest, + header.path.slice(depth), + header.isArray, + at, + leadText, + own, + ); + return node === undefined ? { stored: 0 } : { stored, open: { kind: "forest", node } }; +} + +/** Resolves a commented dotted key to the deepest existing table on its path, so uncommenting it + * adds a sibling instead of a duplicate member that would replace that table. */ +function deepestTable( + table: CommentHost, + path: ReadonlyArray, +): { readonly host: CommentHost; readonly path: ReadonlyArray } { + let host = table; + let depth = 0; + while (depth < path.length - 1) { + const child = host.entries.get(path[depth] ?? ""); + if (child?.kind !== "table") { + break; + } + host = child; + depth++; + } + return { host, path: path.slice(depth) }; +} + +/** + * Translates one run of consecutive source comments. Keys up to the last one before any header + * land in `effective`, the table in effect at that point, or in `continues`, the commented example + * the previous run left open; each commented header lands at its path; `tail` is the prose left + * over for the caller to attach, and `carried` counts the source lines stored. + */ +export function translateGroup( + root: CommentHost, + effective: CommentHost, + rawLines: ReadonlyArray, + first: number, + options: { + readonly blankBefore: boolean; + readonly leadsNextMember: boolean; + readonly continues?: OpenBlock | undefined; + }, +): { readonly carried: number; readonly tail: Array; readonly open?: OpenBlock } { + const classified = rawLines.map(classifyComment); + const headerAt = classified.findIndex((line) => line.kind === "header"); + const leading = classified.slice(0, headerAt < 0 ? undefined : headerAt); + const kept = leading.map((line) => line.kind).lastIndexOf("kv") + 1; + if (options.continues !== undefined && kept > 0) { + const taken = headerAt < 0 && !options.leadsNextMember ? leading.length : kept; + continueBlock(options.continues, leading.slice(0, taken), first); + if (headerAt < 0) { + return { + carried: taken, + tail: leading.slice(taken).map((line) => toJsoncComment(line.raw)), + open: options.continues, + }; + } + return translateHeaders(root, effective, classified, headerAt, first, options, { + carried: taken, + pending: leading.slice(taken), + }); + } + const keyed = placeResolved(effective, [], leading.slice(0, kept), first, options.blankBefore); + const pending = leading.slice(kept); + if (headerAt < 0) { + const tail = pending.map((line) => toJsoncComment(line.raw)); + if (keyed !== undefined && !options.leadsNextMember) { + keyed.source.push(...tail.map(proseLine)); + return { carried: kept + tail.length, tail: [] }; + } + return { carried: kept, tail }; + } + return translateHeaders(root, effective, classified, headerAt, first, options, { + carried: kept, + pending, + }); +} + +function translateHeaders( + root: CommentHost, + effective: CommentHost, + classified: ReadonlyArray, + headerAt: number, + first: number, + options: { readonly leadsNextMember: boolean }, + state: { readonly carried: number; readonly pending: ReadonlyArray }, +): { readonly carried: number; readonly tail: Array; readonly open?: OpenBlock } { + let { carried, pending } = state; + let open: OpenBlock | undefined; + const rest = classified.slice(headerAt); + const starts = rest.flatMap((line, offset) => (line.kind === "header" ? [offset] : [])); + for (const [position, start] of starts.entries()) { + const header = rest[start]; + if (header?.kind !== "header") { + continue; + } + const section = rest.slice(start + 1, starts[position + 1] ?? rest.length); + const isLast = position === starts.length - 1; + const bodyLength = + isLast && !options.leadsNextMember + ? section.length + : section.map((line) => line.kind).lastIndexOf("kv") + 1; + const body = section.slice(0, bodyLength); + const lead = pending; + pending = section.slice(bodyLength); + const at = first + headerAt + start; + const placed = placeBlock(root, header, lead, body, at); + if (placed.stored > 0) { + carried += placed.stored; + open = placed.open; + } else { + const lines = [...lead, header, ...body].map((line) => toJsoncComment(line.raw)); + effective.placed.push({ at, source: lines.map(proseLine), blankBefore: true }); + carried += lines.length; + open = { kind: "verbatim", host: effective }; + } + } + return { carried, tail: pending.map((line) => toJsoncComment(line.raw)), open }; +} diff --git a/packages/config/src/config-convert-values.ts b/packages/config/src/config-convert-values.ts new file mode 100644 index 0000000000..30dab82518 --- /dev/null +++ b/packages/config/src/config-convert-values.ts @@ -0,0 +1,130 @@ +import * as SmolToml from "smol-toml"; +import { isPlainRecord } from "./config-edit.ts"; + +export const INDENT = " "; + +export interface ArrayDecor { + readonly items: ReadonlyArray<{ readonly lead: Array; readonly trail?: string }>; + readonly tail: Array; +} + +export function toJsoncComment(raw: string): string { + return `//${raw.trim().slice(1)}`.trimEnd(); +} + +export function unsupportedReason(value: unknown): string | undefined { + if (value instanceof SmolToml.TomlDate) { + return "TOML date and time values have no JSON equivalent. Quote the value as a string, then rerun"; + } + if (typeof value === "bigint" || (typeof value === "number" && !Number.isFinite(value))) { + return "integers beyond the safe range and inf/nan floats have no JSON equivalent"; + } + if (Array.isArray(value)) { + return value.map(unsupportedReason).find((reason) => reason !== undefined); + } + if (isPlainRecord(value)) { + return Object.values(value) + .map(unsupportedReason) + .find((reason) => reason !== undefined); + } + return undefined; +} + +export function isScalar(value: unknown): boolean { + return !Array.isArray(value) && !isPlainRecord(value); +} + +function scalarText(value: unknown): string { + return typeof value === "string" ? JSON.stringify(value) : String(value); +} + +export function withComma(lines: Array, comma: string): Array { + const last = lines.length - 1; + return lines.map((line, index) => (index === last ? `${line}${comma}` : line)); +} + +export function indented(indent: string, lines: ReadonlyArray): Array { + return lines.map((line) => (line === "" ? "" : `${indent}${line}`)); +} + +function renderDecoratedArray( + value: ReadonlyArray, + indent: string, + decor: ArrayDecor, +): Array { + const inner = `${indent}${INDENT}`; + const items = value.flatMap((item, index) => { + const entry = decor.items[index]; + const comma = index < value.length - 1 ? "," : ""; + const trail = entry?.trail === undefined ? "" : ` ${entry.trail}`; + return [...indented(inner, entry?.lead ?? []), `${inner}${scalarText(item)}${comma}${trail}`]; + }); + return ["[", ...items, ...indented(inner, decor.tail), `${indent}]`]; +} + +export function renderValue( + value: unknown, + indent: string, + spread: boolean, + decor?: ArrayDecor, +): Array { + const inner = `${indent}${INDENT}`; + if (Array.isArray(value)) { + if (value.length === 0) { + return ["[]"]; + } + if (decor !== undefined) { + return renderDecoratedArray(value, indent, decor); + } + if (!spread && value.every(isScalar)) { + return [`[${value.map(scalarText).join(", ")}]`]; + } + const items = value.flatMap((item: unknown, index) => { + const [first = "", ...rest] = renderValue(item, inner, false); + return withComma([`${inner}${first}`, ...rest], index < value.length - 1 ? "," : ""); + }); + return ["[", ...items, `${indent}]`]; + } + if (isPlainRecord(value)) { + const keys = Object.keys(value); + if (keys.length === 0) { + return ["{}"]; + } + const items = keys.flatMap((key, index) => { + const [first = "", ...rest] = renderValue(value[key], inner, false); + return withComma( + [`${inner}${JSON.stringify(key)}: ${first}`, ...rest], + index < keys.length - 1 ? "," : "", + ); + }); + return ["{", ...items, `${indent}}`]; + } + return [scalarText(value)]; +} + +function inlineValue(value: unknown): string { + if (Array.isArray(value)) { + return `[${value.map(inlineValue).join(", ")}]`; + } + if (isPlainRecord(value)) { + const keys = Object.keys(value); + return keys.length === 0 + ? "{}" + : `{ ${keys.map((key) => `${JSON.stringify(key)}: ${inlineValue(value[key])}`).join(", ")} }`; + } + return scalarText(value); +} + +export function commentedKvLines( + path: ReadonlyArray, + value: unknown, + indent: string, +): Array { + const [name = "", ...rest] = path; + if (rest.length > 0) { + const nested = rest.reduceRight((inner, key) => ({ [key]: inner }), value); + return [`${indent}${JSON.stringify(name)}: ${inlineValue(nested)}`]; + } + const [head = "", ...tail] = renderValue(value, indent, false); + return [`${indent}${JSON.stringify(name)}: ${head}`, ...tail]; +} diff --git a/packages/config/src/config-convert.property.unit.test.ts b/packages/config/src/config-convert.property.unit.test.ts new file mode 100644 index 0000000000..cc00394937 --- /dev/null +++ b/packages/config/src/config-convert.property.unit.test.ts @@ -0,0 +1,268 @@ +import { describe, expect, test } from "vitest"; +import { Effect } from "effect"; +import { printParseErrorCode, visit } from "jsonc-parser"; +import * as SmolToml from "smol-toml"; +import { convertCliConfigTomlToJsonc } from "./config-convert.ts"; +import { parseJsonc } from "./jsonc.ts"; +import { scanTomlDocument } from "./toml-scan.ts"; + +const SEEDS = [1, 7, 42, 2024]; +const CASES_PER_SEED = 500; + +const REAL_HEADERS = ["[a]", "[a.b]", "[a.c]", "[f.g]", "[s.t]", "[s]"]; +const REAL_KVS = ["x = 1", "y = 2", "b.k = 3", "c.m = 4", "q = 5"]; +const COMMENTED_KVS = ["# z = 3", "# w = 4", "# b.v = 5", "# d.e = 6", "# d.h = 7", "# c.n = 8"]; +const COMMENTED_KVS_TAIL = [...COMMENTED_KVS, "# t.u = 9"]; +const COMMENTED_HEADERS = [ + "# [a.d]", + "# [s]", + "# [s.t]", + "# [a.b]", + "# [d]", + "# [a.d.e2]", + "# [a]", +]; +const PROSE = ["# note", "# Another note.", "# Uses the [a] table."]; + +const EXAMPLE_LINE = /^# (\[\[?[^\]]+\]\]?|[\w."'-]+ = .+)$/; + +function mulberry32(seed: number): () => number { + let state = seed >>> 0; + return () => { + state = (state + 0x6d2b79f5) >>> 0; + let t = state; + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +function generateSource(rand: () => number): string { + const pick = (items: ReadonlyArray): string => + items[Math.floor(rand() * items.length)] ?? ""; + const lines: string[] = []; + const count = 3 + Math.floor(rand() * 9); + for (let i = 0; i < count; i++) { + const roll = rand(); + if (roll < 0.15) { + lines.push(pick(REAL_HEADERS)); + } else if (roll < 0.35) { + lines.push(pick(REAL_KVS)); + } else if (roll < 0.6) { + if (rand() < 0.3) lines.push(pick(PROSE)); + lines.push(pick(COMMENTED_KVS_TAIL)); + } else if (roll < 0.8) { + if (rand() < 0.3) lines.push(pick(PROSE)); + lines.push(pick(COMMENTED_HEADERS), pick(COMMENTED_KVS)); + } else if (roll < 0.9) { + lines.push(""); + } else { + lines.push(pick(PROSE), ""); + } + } + return `${lines.join("\n")}\n`; +} + +/** Known limitations: a real key after a commented header, and one commented key path declared twice. */ +function hitsAcceptedLimitation(source: string): boolean { + let realTable = ""; + let commentedTable = ""; + let afterCommentedHeader = false; + const commentedPaths = new Set(); + for (const line of source.split("\n")) { + const commentedHeader = /^# \[([^\]]+)\]$/.exec(line); + const commentedKey = /^# ([\w.]+) = /.exec(line); + if (commentedHeader !== null) { + commentedTable = commentedHeader[1] ?? ""; + afterCommentedHeader = true; + } else if (line.startsWith("[")) { + realTable = line.slice(1, -1); + commentedTable = ""; + afterCommentedHeader = false; + } else if (commentedKey !== null) { + const path = [realTable, commentedTable, commentedKey[1]].join("|"); + if (commentedPaths.has(path)) return true; + commentedPaths.add(path); + } else if (/^[a-z]/.test(line) && afterCommentedHeader) { + return true; + } + } + return false; +} + +function isExampleBody(body: string): boolean { + const scan = scanTomlDocument(body); + if ("error" in scan || scan.tokens.length !== 1) return false; + const kind = scan.tokens[0]?.kind; + if (kind !== "header" && kind !== "kv") return false; + try { + SmolToml.parse(body); + return true; + } catch { + return false; + } +} + +function uncommentToml(source: string): string { + return source + .split(/(?<=\n)/) + .map((line) => { + const match = /^(\s*)# ?(.*?)(\r?\n)?$/.exec(line); + if (match === null) return line; + const [, indent = "", body = "", newline = ""] = match; + return isExampleBody(body) ? `${indent}${body}${newline}` : line; + }) + .join(""); +} + +function uncommentJsonc(text: string): string { + return text.replace(/^(\s*)\/\/ (?=\s*["{}[\]])/gm, "$1"); +} + +function strictParse(text: string): { value: unknown; problems: string[] } { + const problems: string[] = []; + const stack: Array | null> = []; + visit( + text, + { + onObjectBegin: () => { + stack.push(new Set()); + }, + onObjectEnd: () => { + stack.pop(); + }, + onArrayBegin: () => { + stack.push(null); + }, + onArrayEnd: () => { + stack.pop(); + }, + onObjectProperty: (key, offset) => { + const keys = stack[stack.length - 1]; + if (keys === undefined || keys === null) return; + if (keys.has(key)) problems.push(`duplicate key "${key}" at offset ${offset}`); + keys.add(key); + }, + onError: (code, offset) => { + const line = text.slice(0, offset).split("\n").length; + problems.push(`${printParseErrorCode(code)} on line ${line}`); + }, + }, + { allowTrailingComma: true, disallowComments: false }, + ); + let value: unknown; + try { + value = parseJsonc(text); + } catch (error) { + problems.push(`parseJsonc: ${error instanceof Error ? error.message : String(error)}`); + } + return { value, problems }; +} + +function withoutSchema(value: unknown): unknown { + if (typeof value !== "object" || value === null || Array.isArray(value)) return value; + return Object.fromEntries(Object.entries(value).filter(([key]) => key !== "$schema")); +} + +function commentedMembers(lines: ReadonlyArray): Array { + const members: Array = []; + for (let start = 0; start < lines.length; start++) { + const match = /^(\s*)\/\/ "[^"]+": (.*)$/.exec(lines[start] ?? ""); + if (match === null) continue; + const [, indent = "", rest = ""] = match; + let end = start; + if (/[{[],?$/.test(rest) && !/[}\]],?$/.test(rest)) { + const close = new RegExp(`^${indent}// [}\\]],?$`); + while (end < lines.length && !close.test(lines[end] ?? "")) end++; + if (end === lines.length) return members.concat([[start, -1]]); + } + members.push([start, end]); + start = end; + } + return members; +} + +function proseComments(source: string): string[] { + return source + .split("\n") + .filter((line) => line.startsWith("# ") && !EXAMPLE_LINE.test(line)) + .map((line) => line.slice(2).trimEnd()); +} + +function checkCase(source: string): string[] { + const failures: string[] = []; + const outcome = Effect.runSync(Effect.result(convertCliConfigTomlToJsonc(source))); + if (outcome._tag === "Failure") { + return [`conversion refused: ${outcome.failure.reason}: ${outcome.failure.detail}`]; + } + const { text } = outcome.success; + + const base = strictParse(text); + if (base.problems.length > 0) failures.push(`output is not strict JSONC: ${base.problems}`); + + const emitted = text.split("\n").map((line) => line.trim().replace(/^(\/\/\s*)+/, "")); + const prose = proseComments(source); + for (const comment of new Set(prose)) { + const expected = prose.filter((line) => line === comment).length; + const actual = emitted.filter((line) => line === comment).length; + if (actual !== expected) { + failures.push(`comment "${comment}" appears ${actual} times, expected ${expected}`); + } + } + + const allJsonc = strictParse(uncommentJsonc(text)); + if (allJsonc.problems.length > 0) { + failures.push(`uncommenting every example breaks the JSONC: ${allJsonc.problems}`); + } else { + const expected = withoutSchema(SmolToml.parse(uncommentToml(source))); + try { + expect(withoutSchema(allJsonc.value)).toEqual(expected); + } catch (error) { + failures.push( + `uncommented JSONC differs from uncommented TOML: ${error instanceof Error ? error.message : String(error)}`, + ); + } + } + + const lines = text.split("\n"); + for (const [start, end] of commentedMembers(lines)) { + if (end === -1) { + failures.push(`commented member on line ${start + 1} has no closing delimiter`); + continue; + } + const doc = lines + .map((line, index) => + index >= start && index <= end ? line.replace(/^(\s*)\/\/ ?/, "$1") : line, + ) + .join("\n"); + const { problems } = strictParse(doc); + if (problems.length > 0) { + failures.push( + `uncommenting lines ${start + 1}-${end + 1} (${lines[start]?.trim()}): ${problems}`, + ); + } + } + return failures; +} + +describe("convertCliConfigTomlToJsonc: seeded property checks", () => { + for (const seed of SEEDS) { + test(`seed ${seed}: conversion keeps comments once, round-trips examples, and uncomments cleanly`, () => { + const rand = mulberry32(seed); + let checked = 0; + for (let i = 0; i < CASES_PER_SEED; i++) { + const source = generateSource(rand); + if (hitsAcceptedLimitation(source)) continue; + try { + SmolToml.parse(source); + SmolToml.parse(uncommentToml(source)); + } catch { + continue; + } + checked++; + expect(checkCase(source), `seed ${seed}, TOML source:\n${source}`).toEqual([]); + } + expect(checked).toBeGreaterThan(CASES_PER_SEED / 4); + }); + } +}); diff --git a/packages/config/src/config-convert.ts b/packages/config/src/config-convert.ts new file mode 100644 index 0000000000..5785e1b04c --- /dev/null +++ b/packages/config/src/config-convert.ts @@ -0,0 +1,600 @@ +import { Data, Effect } from "effect"; +import * as SmolToml from "smol-toml"; +import { + type CommentedNode, + holdsExample, + hostComments, + newCommentedNode, + type OpenBlock, + type PlacedComment, + translateGroup, +} from "./config-convert-comments.ts"; +import { + type ArrayDecor, + INDENT, + indented, + isScalar, + renderValue, + toJsoncComment, + unsupportedReason, +} from "./config-convert-values.ts"; +import { deepEqualValue } from "./config-edit.ts"; +import { parseJsonc } from "./jsonc.ts"; +import { CLI_CONFIG_SCHEMA_URL } from "./schema-metadata.ts"; +import { SCHEMA_DIRECTIVE_LINE } from "./schema-version.ts"; +import { + scanScalarArrayLayout, + scanTomlDocument, + type TomlArrayLayout, + type TomlHeaderToken, + type TomlKeyToken, + type TomlToken, +} from "./toml-scan.ts"; + +export interface MovedTomlComment { + readonly line: number; + readonly text: string; + readonly anchor: ReadonlyArray; +} + +export interface CliConfigConverted { + readonly text: string; + readonly schemaRef: string; + readonly schemaSource: "directive" | "key" | "default"; + readonly commentCount: number; + readonly movedComments: ReadonlyArray; +} + +/** The converter refused the document; `sourceLine` is the 1-based `config.toml` line when known. */ +export class CliConfigConvertError extends Data.TaggedError("CliConfigConvertError")<{ + readonly reason: "parse_error" | "unsupported_value" | "verification_mismatch"; + readonly detail: string; + readonly sourceLine?: number; +}> {} + +interface Decor { + readonly lead: Array; + blankBefore: boolean; + inline?: string; + at: number; +} + +interface LeafNode extends Decor { + readonly kind: "leaf"; + readonly value: unknown; + readonly spread: boolean; + array?: ArrayDecor; + readonly hoisted: Array; + readonly trail: Array; +} + +interface TableNode extends Decor { + readonly kind: "table"; + entries: Map; + readonly inner: Array; + readonly placed: Array; + readonly forest: CommentedNode; +} + +interface ArrayOfTablesNode { + readonly kind: "aot"; + readonly elements: Array; +} + +type ConfigNode = LeafNode | TableNode | ArrayOfTablesNode; + +function refusal( + reason: CliConfigConvertError["reason"], + detail: string, + sourceLine?: number, +): CliConfigConvertError { + return new CliConfigConvertError({ + reason, + detail, + ...(sourceLine === undefined ? {} : { sourceLine }), + }); +} + +function newTable(): TableNode { + return { + kind: "table", + entries: new Map(), + lead: [], + blankBefore: false, + at: -1, + inner: [], + placed: [], + forest: newCommentedNode(-1), + }; +} + +function entryAt(node: ConfigNode): number { + return node.kind === "aot" ? (node.elements[0]?.at ?? -1) : node.at; +} + +function renderTableBody(table: TableNode, indent: string): Array { + const entries = [...table.entries]; + const pending = hostComments(table); + const body = indented(indent, table.inner); + const flushBefore = (limit: number) => { + for (let item = pending[0]; item !== undefined && item.at < limit; item = pending[0]) { + pending.shift(); + body.push( + ...(item.blankBefore && body.length > 0 ? [""] : []), + ...indented(indent, item.lines), + ); + } + }; + for (const [index, [key, node]] of entries.entries()) { + flushBefore(entryAt(node)); + const comma = index < entries.length - 1 || pending.length > 0 ? "," : ""; + const first = index === 0 && body.length === table.inner.length; + body.push(...renderEntry(key, node, indent, comma, first)); + } + flushBefore(Number.POSITIVE_INFINITY); + return body; +} + +function renderTableOpen( + table: TableNode, + prefix: string, + indent: string, + comma: string, +): Array { + const inline = table.inline === undefined ? "" : ` ${table.inline}`; + const body = renderTableBody(table, `${indent}${INDENT}`); + if (body.length === 0) { + return [`${indent}${prefix}{}${comma}${inline}`]; + } + return [`${indent}${prefix}{${inline}`, ...body, `${indent}}${comma}`]; +} + +function renderEntry( + key: string, + node: ConfigNode, + indent: string, + comma: string, + first: boolean, +): Array { + const name = JSON.stringify(key); + const blank = (decor: Decor) => (decor.blankBefore && !first ? [""] : []); + if (node.kind === "leaf") { + const [head = "", ...rest] = renderValue(node.value, indent, node.spread, node.array); + const lines = [`${indent}${name}: ${head}`, ...rest]; + lines[lines.length - 1] += `${comma}${node.inline === undefined ? "" : ` ${node.inline}`}`; + return [ + ...blank(node), + ...indented(indent, node.lead), + ...indented(indent, node.hoisted), + ...lines, + ...indented(indent, node.trail), + ]; + } + if (node.kind === "table") { + return [ + ...blank(node), + ...indented(indent, node.lead), + ...renderTableOpen(node, `${name}: `, indent, comma), + ]; + } + const elementIndent = `${indent}${INDENT}`; + const elements = node.elements.flatMap((element, index) => [ + ...(index > 0 && element.blankBefore ? [""] : []), + ...indented(elementIndent, element.lead), + ...renderTableOpen(element, "", elementIndent, index < node.elements.length - 1 ? "," : ""), + ]); + const head = node.elements[0]; + return [ + ...(head === undefined ? [] : blank(head)), + `${indent}${name}: [`, + ...elements, + `${indent}]${comma}`, + ]; +} + +function isMember(token: TomlToken | undefined): token is TomlHeaderToken | TomlKeyToken { + return token?.kind === "header" || token?.kind === "kv"; +} + +const descend = Effect.fnUntraced(function* ( + parent: TableNode, + segment: string, + line: number, + created: Array, +) { + const existing = parent.entries.get(segment); + if (existing === undefined) { + const table = newTable(); + parent.entries.set(segment, table); + created.push(table); + return table; + } + if (existing.kind === "table") { + return existing; + } + const last = + existing.kind === "aot" ? existing.elements[existing.elements.length - 1] : undefined; + if (last === undefined) { + return yield* refusal("parse_error", `"${segment}" is defined twice`, line); + } + return last; +}); + +const walk = Effect.fnUntraced(function* ( + root: TableNode, + path: ReadonlyArray, + line: number, + created: Array, +) { + let table = root; + for (const segment of path) { + table = yield* descend(table, segment, line, created); + } + return table; +}); + +function arrayDecor( + layout: TomlArrayLayout, + text: string, + comment: (raw: string) => string, +): ArrayDecor { + const raw = (span: { readonly start: number; readonly end: number }) => + comment(text.slice(span.start, span.end)); + return { + items: layout.items.map((item) => ({ + lead: item.leading.map(raw), + ...(item.trailing === undefined ? {} : { trail: raw(item.trailing) }), + })), + tail: layout.tail.map(raw), + }; +} + +/** Index of the `#:schema` comment among the leading comments and blank lines, matching the loader. */ +function leadingSchemaDirectiveIndex(tokens: ReadonlyArray, text: string): number { + for (const [index, token] of tokens.entries()) { + if (token.kind === "blank") { + continue; + } + if (token.kind !== "comment") { + return -1; + } + if (schemaDirectiveRef(text, token) !== undefined) { + return index; + } + } + return -1; +} + +function schemaDirectiveRef(text: string, token: TomlToken | undefined): string | undefined { + return token === undefined + ? undefined + : SCHEMA_DIRECTIVE_LINE.exec(text.slice(token.start, token.end))?.[1]; +} + +const convertDocument = Effect.fnUntraced(function* (text: string) { + const parsed = yield* Effect.try({ + try: () => SmolToml.parse(text), + catch: (error) => + refusal( + "parse_error", + error instanceof Error ? error.message : String(error), + error instanceof SmolToml.TomlError ? error.line : undefined, + ), + }); + const lineOf = (offset: number) => text.slice(0, offset).split("\n").length; + const scan = yield* Effect.try({ + try: () => scanTomlDocument(text), + catch: (error) => + refusal("parse_error", error instanceof Error ? error.message : String(error)), + }); + if ("error" in scan) { + return yield* refusal("parse_error", scan.error, lineOf(scan.offset)); + } + const { tokens, headers } = scan; + let commentCount = 0; + const comment = (raw: string) => { + commentCount++; + return toJsoncComment(raw); + }; + const commentAt = (offset: number) => comment(text.slice(offset).split(/\r?\n|\r/, 1)[0] ?? ""); + + const directiveIndex = leadingSchemaDirectiveIndex(tokens, text); + const directive = + directiveIndex < 0 ? undefined : schemaDirectiveRef(text, tokens[directiveIndex]); + const firstTokenIndex = directiveIndex === 0 ? 1 : 0; + const isComment = (index: number) => + tokens[index]?.kind === "comment" && index !== directiveIndex; + + const root = newTable(); + const rootLead: Array = []; + const rootEnd: Array = []; + const movedComments: Array = []; + const members: Array = []; + const implicitParents = new Map(); + const effective: Array = []; + let scannedComments = directive === undefined ? 0 : -1; + let current = root; + + for (const [index, token] of tokens.entries()) { + const created: Array = []; + if (token.kind === "comment") { + scannedComments++; + } else if (token.kind === "header") { + const line = lineOf(token.start); + let table: TableNode; + if (token.isArrayOfTables) { + const parent = yield* walk(root, token.path.slice(0, -1), line, created); + const name = token.path[token.path.length - 1] ?? ""; + const existing = parent.entries.get(name); + table = newTable(); + if (existing === undefined) { + parent.entries.set(name, { kind: "aot", elements: [table] }); + } else if (existing.kind === "aot") { + existing.elements.push(table); + } else { + return yield* refusal("parse_error", `"${name}" is defined twice`, line); + } + } else { + table = yield* walk(root, token.path, line, created); + } + const implicit = created[0]; + if (implicit !== undefined && implicit !== table) { + implicitParents.set(index, implicit); + } + if (token.commentStart !== undefined) { + scannedComments++; + table.inline = commentAt(token.commentStart); + } + if (token.isArrayOfTables) { + table.at = index; + } + current = table; + members[index] = table; + } else if (token.kind === "kv") { + const line = lineOf(token.start); + const base = token.tableIndex >= 0 ? (headers[token.tableIndex]?.path.length ?? 0) : 0; + const relative = token.path.slice(base); + const parent = yield* walk(current, relative.slice(0, -1), line, created); + const name = relative[relative.length - 1] ?? ""; + if (parent.entries.has(name)) { + return yield* refusal("parse_error", `"${name}" is defined twice`, line); + } + if (created[0] !== undefined) { + implicitParents.set(index, created[0]); + } + const valueText = text.slice(token.valueStart, token.valueEnd); + const value = yield* Effect.try({ + try: () => SmolToml.parse(`v = ${valueText}`)["v"], + catch: (error) => + refusal("parse_error", error instanceof Error ? error.message : String(error), line), + }); + const unsupported = unsupportedReason(value); + if (unsupported !== undefined) { + return yield* refusal("unsupported_value", `${token.path.join(".")}: ${unsupported}`, line); + } + const leaf: LeafNode = { + kind: "leaf", + value, + spread: valueText.includes("\n"), + lead: [], + hoisted: [], + trail: [], + blankBefore: false, + at: index, + }; + scannedComments += token.valueComments.length; + if (token.commentStart !== undefined) { + scannedComments++; + leaf.inline = commentAt(token.commentStart); + } + const scalarCount = + leaf.spread && Array.isArray(value) && value.every(isScalar) ? value.length : 0; + const layout = + scalarCount > 0 ? scanScalarArrayLayout(text, token.valueStart, token.valueEnd) : null; + if (layout !== null && layout.items.length === scalarCount) { + leaf.array = arrayDecor(layout, text, comment); + } else { + for (const span of token.valueComments) { + const raw = text.slice(span.start, span.end).trim(); + leaf.hoisted.push(comment(raw)); + movedComments.push({ line: lineOf(span.start), text: raw, anchor: token.path }); + } + } + parent.entries.set(name, leaf); + members[index] = leaf; + } + for (const table of created) { + table.at = index; + } + effective[index] = current; + } + + const groupEnd = (start: number) => { + let end = start; + while (isComment(end)) { + end++; + } + return end; + }; + const groupLines = (start: number, end: number) => + tokens.slice(start, end).map((entry) => text.slice(entry.start, entry.end)); + const reachesExample = (from: number): boolean => { + let at = from; + while (tokens[at]?.kind === "blank") { + at++; + } + if (!isComment(at)) { + return false; + } + const end = groupEnd(at); + return holdsExample(groupLines(at, end)) || reachesExample(end); + }; + + let open: OpenBlock | undefined; + let openEnd = -1; + let deferred: { readonly start: number; readonly lines: Array } | undefined; + tokens.forEach((token, index) => { + if (!isComment(index)) { + return; + } + if (isComment(index - 1)) { + return; + } + const end = groupEnd(index); + const ownLines = groupLines(index, end); + const start = deferred?.start ?? index; + const previous = start > firstTokenIndex ? tokens[start - 1] : undefined; + const blankBefore = previous === undefined || previous.kind === "blank"; + const next = tokens[end]; + // Detached prose followed by a commented example travels with that example. + if ( + blankBefore && + next?.kind === "blank" && + !holdsExample(ownLines) && + (open !== undefined || tokens.slice(0, index).some(isMember)) && + reachesExample(end) + ) { + deferred = { start, lines: [...(deferred?.lines ?? []), ...ownLines] }; + return; + } + const rawLines = [...(deferred?.lines ?? []), ...ownLines]; + deferred = undefined; + const leadTarget = isMember(next) ? (implicitParents.get(end) ?? members[end]) : undefined; + const continues = + open !== undefined && tokens.slice(openEnd, start).every((entry) => entry.kind === "blank") + ? open + : undefined; + const translated = translateGroup(root, effective[index - 1] ?? root, rawLines, start, { + blankBefore, + leadsNextMember: leadTarget !== undefined, + continues, + }); + open = translated.open; + openEnd = end; + const { carried, tail } = translated; + commentCount += carried + tail.length; + if (tail.length === 0) { + return; + } + const keysPlaced = carried > 0; + if (leadTarget?.kind === "table" && next?.kind === "header" && leadTarget.at < end) { + leadTarget.placed.push({ + at: index, + source: tail.map((text) => ({ kind: "prose", text })), + blankBefore, + }); + return; + } + if (leadTarget !== undefined) { + if (leadTarget.lead.length === 0) { + leadTarget.blankBefore = blankBefore && !keysPlaced; + } + leadTarget.lead.push(...tail); + return; + } + const owner = isMember(previous) ? members[index - 1] : undefined; + if (owner !== undefined) { + (owner.kind === "table" ? owner.inner : owner.trail).push(...tail); + return; + } + const nextMemberIndex = tokens.findIndex((entry, at) => at >= end && isMember(entry)); + const nextMember = implicitParents.get(nextMemberIndex) ?? members[nextMemberIndex]; + const hasMemberBefore = tokens.slice(0, index).some(isMember); + if (!hasMemberBefore) { + rootLead.push(...tail, ...(next === undefined ? [] : [""])); + } else if (nextMember !== undefined) { + if (nextMember.lead.length === 0) { + nextMember.blankBefore = true; + } + nextMember.lead.push(...tail, ""); + } else { + rootEnd.push("", ...tail); + } + }); + + if (commentCount !== scannedComments) { + return yield* refusal( + "verification_mismatch", + `converted document carries ${commentCount} of ${scannedComments} comments`, + ); + } + + members.forEach((member, index) => { + if (member === undefined) { + return; + } + if (member.lead.length === 0) { + member.blankBefore = index > firstTokenIndex && tokens[index - 1]?.kind === "blank"; + } + const implicit = implicitParents.get(index); + if (implicit !== undefined && implicit.lead.length === 0) { + implicit.blankBefore = member.blankBefore; + } + }); + + const keyed = root.entries.get("$schema"); + let schemaRef: string; + let schemaSource: "directive" | "key" | "default"; + if (keyed !== undefined) { + if (keyed.kind !== "leaf" || typeof keyed.value !== "string") { + return yield* refusal("unsupported_value", "`$schema` must be a string"); + } + if (directive !== undefined && directive !== keyed.value) { + return yield* refusal( + "unsupported_value", + `the schema is declared twice, as \`#:schema ${directive}\` and as \`$schema = "${keyed.value}"\`; keep one and rerun`, + ); + } + schemaRef = keyed.value; + schemaSource = "key"; + root.entries.delete("$schema"); + root.entries = new Map([["$schema", keyed], ...root.entries]); + } else { + schemaRef = directive ?? CLI_CONFIG_SCHEMA_URL; + schemaSource = directive === undefined ? "default" : "directive"; + const entry: LeafNode = { + kind: "leaf", + value: schemaRef, + spread: false, + lead: [], + hoisted: [], + trail: [], + blankBefore: false, + at: -1, + }; + root.entries = new Map([["$schema", entry], ...root.entries]); + } + + const newline = scan.newline; + const rendered = [ + ...rootLead, + "{", + ...renderTableBody(root, INDENT), + ...indented(INDENT, rootEnd), + "}", + ].join(newline); + const output = `${rendered}${newline}`; + + const actual = yield* Effect.try({ + try: () => parseJsonc(output), + catch: (error) => + refusal( + "verification_mismatch", + `converted document does not parse: ${error instanceof Error ? error.message : String(error)}`, + ), + }); + if (!deepEqualValue(actual, { $schema: schemaRef, ...parsed })) { + return yield* refusal( + "verification_mismatch", + "converted document does not match the original values", + ); + } + + return { text: output, schemaRef, schemaSource, commentCount, movedComments }; +}); + +/** Converts a `config.toml` document to `config.jsonc` text with comments carried over; verified by re-parse. */ +export const convertCliConfigTomlToJsonc = ( + source: string, +): Effect.Effect => + convertDocument(source.startsWith("") ? source.slice(1) : source); diff --git a/packages/config/src/config-convert.unit.test.ts b/packages/config/src/config-convert.unit.test.ts new file mode 100644 index 0000000000..d1ff7bdd43 --- /dev/null +++ b/packages/config/src/config-convert.unit.test.ts @@ -0,0 +1,963 @@ +import { describe, expect, test } from "vitest"; +import { BunServices } from "@effect/platform-bun"; +import { Effect, FileSystem, Path } from "effect"; +import * as SmolToml from "smol-toml"; +import { + CliConfigConvertError, + convertCliConfigTomlToJsonc, + type MovedTomlComment, +} from "./config-convert.ts"; +import { loadCliConfig, parseCliConfigDocumentFile } from "./io.ts"; +import { parseJsonc } from "./jsonc.ts"; +import { CLI_CONFIG_SCHEMA_URL } from "./schema-metadata.ts"; + +function converted(source: string) { + return Effect.runSync(convertCliConfigTomlToJsonc(source)); +} + +function refusal(source: string): CliConfigConvertError { + return Effect.runSync(Effect.flip(convertCliConfigTomlToJsonc(source))); +} + +function uncommented(text: string): unknown { + return parseJsonc(text.replace(/^(\s*)\/\/ (?=\s*["{}[\]])/gm, "$1")); +} + +function body(source: string): string { + const { text } = converted(source); + return text.split("\n").slice(2, -2).join("\n").replace(/^\n+/, ""); +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function leaves(value: unknown, path: ReadonlyArray = []): Map { + if (!isRecord(value) || Object.keys(value).length === 0) { + return new Map([[path.join("."), JSON.stringify(value)]]); + } + return new Map( + Object.entries(value).flatMap(([key, child]) => [...leaves(child, [...path, key])]), + ); +} + +function changed(after: Map, before: Map) { + return new Map([...after].filter(([path, value]) => before.get(path) !== value)); +} + +const EXAMPLE_LINE = /^# (\[\[?[^\]]+\]\]?|[\w."'-]+ = .+)$/; + +function commentedMembers(lines: ReadonlyArray): Array { + const members: Array = []; + for (let start = 0; start < lines.length; start++) { + const match = /^(\s*)\/\/ "[^"]+": (.*)$/.exec(lines[start] ?? ""); + if (match === null) { + continue; + } + let end = start; + if (/[{[],?$/.test(match[2] ?? "") && !/[}\]],?$/.test(match[2] ?? "")) { + const close = new RegExp(`^${match[1]}// [}\\]],?$`); + while (end < lines.length && !close.test(lines[end] ?? "")) { + end++; + } + if (end === lines.length) { + throw new Error(`No closing delimiter for the commented member on line ${start + 1}`); + } + } + members.push([start, end]); + start = end; + } + return members; +} + +function expectExamplesUncommentAtTomlPaths(source: string) { + const lines = converted(source).text.split("\n"); + const active = leaves(parseJsonc(lines.join("\n"))); + const withExamples = source + .split("\n") + .map((line) => (EXAMPLE_LINE.test(line) ? line.slice(2) : line)) + .join("\n"); + const expected = changed(leaves(SmolToml.parse(withExamples)), leaves(SmolToml.parse(source))); + const members = commentedMembers(lines); + const seen = new Map(); + for (const [start, end] of members) { + const document = lines + .map((line, index) => + index >= start && index <= end ? line.replace(/^(\s*)\/\/ ?/, "$1") : line, + ) + .join("\n"); + const gained = changed(leaves(parseJsonc(document)), active); + expect(gained.size).toBeGreaterThan(0); + for (const [path, value] of gained) { + seen.set(path, value); + } + } + expect(members.length).toBeGreaterThan(0); + expect(seen).toEqual(expected); +} + +function expectEachCommentOnce(source: string, text: string) { + const emitted = text.split("\n").map((line) => line.trim().replace(/^(\/\/\s*)+/, "")); + const prose = source + .split("\n") + .filter((line) => line.startsWith("# ") && !EXAMPLE_LINE.test(line)) + .map((line) => line.slice(2).trimEnd()); + for (const comment of new Set(prose)) { + expect( + emitted.filter((line) => line === comment), + comment, + ).toHaveLength(prose.filter((line) => line === comment).length); + } +} + +describe("convertCliConfigTomlToJsonc: schema", () => { + test("promotes the #:schema directive to $schema without repeating it as a comment", () => { + const outcome = converted('#:schema https://example.com/s.json\nproject_id = "demo"\n'); + expect(outcome.schemaRef).toBe("https://example.com/s.json"); + expect(outcome.schemaSource).toBe("directive"); + expect(outcome.commentCount).toBe(0); + expect(outcome.text).toBe( + '{\n "$schema": "https://example.com/s.json",\n "project_id": "demo"\n}\n', + ); + }); + + test("falls back to the current schema URL without a directive", () => { + const outcome = converted('project_id = "demo"\n'); + expect(outcome.schemaRef).toBe(CLI_CONFIG_SCHEMA_URL); + expect(outcome.schemaSource).toBe("default"); + }); + + test("refuses a #:schema directive and a different $schema key", () => { + const error = refusal( + '#:schema https://example.com/a.json\nproject_id = "demo"\n"$schema" = "https://example.com/b.json"\n', + ); + expect(error.reason).toBe("unsupported_value"); + expect(error.detail).toContain("#:schema https://example.com/a.json"); + }); + + test("keeps a $schema key that repeats the directive, without repeating the directive", () => { + const outcome = converted( + '#:schema https://example.com/a.json\nproject_id = "demo"\n"$schema" = "https://example.com/a.json"\n', + ); + expect(outcome.schemaSource).toBe("key"); + expect(outcome.text).toBe( + '{\n "$schema": "https://example.com/a.json",\n "project_id": "demo"\n}\n', + ); + }); + + test("reads a #:schema directive below leading comments, as the loader does", () => { + const outcome = converted( + '# Project settings.\n\n #:schema https://example.com/s.json\n# More notes.\nproject_id = "demo"\n', + ); + expect(outcome.schemaRef).toBe("https://example.com/s.json"); + expect(outcome.schemaSource).toBe("directive"); + expect(outcome.text).not.toContain("#:schema"); + expect(outcome.text).not.toContain("//:schema"); + expect(outcome.text).toContain("// Project settings."); + expect(outcome.text).toContain("// More notes."); + }); + + test("reads a #:schema directive that has trailing whitespace", () => { + const outcome = converted('#:schema https://example.com/s.json \nproject_id = "demo"\n'); + expect(outcome.schemaRef).toBe("https://example.com/s.json"); + expect(outcome.schemaSource).toBe("directive"); + expect(outcome.commentCount).toBe(0); + }); + + test("ignores a #:schema line that is not the first line", () => { + const outcome = converted('project_id = "demo"\n#:schema https://example.com/a.json\n'); + expect(outcome.schemaSource).toBe("default"); + expect(outcome.text).toContain("//:schema https://example.com/a.json"); + }); +}); + +describe("convertCliConfigTomlToJsonc: values", () => { + test("keeps env() references byte-identical", () => { + expect(body('[auth.external.github]\nsecret = "env(GITHUB_SECRET)"\n')).toBe( + [ + ' "auth": {', + ' "external": {', + ' "github": {', + ' "secret": "env(GITHUB_SECRET)"', + " }", + " }", + " }", + ].join("\n"), + ); + }); + + test("keeps a comment starting with a quoted string with invalid escapes as prose", () => { + const source = '# "C:\\Users\\me" holds it\n# ["\\xZZ"]\n# "\\uZZZZ" = 1\na = 1\n'; + const { text } = converted(source); + expect(text).toContain('// "C:\\Users\\me" holds it'); + expect(text).toContain('// ["\\xZZ"]'); + expect(parseJsonc(text)).toEqual({ $schema: CLI_CONFIG_SCHEMA_URL, a: 1 }); + }); + + test("decodes hexadecimal and escape-character escapes in quoted keys", () => { + const { text } = converted('[functions."\\x61"]\nk = 1\n"\\e" = 2\n'); + expect(parseJsonc(text)).toEqual({ + $schema: CLI_CONFIG_SCHEMA_URL, + functions: { a: { k: 1, "\u001b": 2 } }, + }); + }); + + test("expands dotted keys, implicit parents, and parents declared after their children", () => { + const source = '[a.b]\nx = 1\n[c]\ny = true\n[a]\nz.w = "s"\n'; + expect(JSON.parse(converted(source).text)).toEqual({ + $schema: CLI_CONFIG_SCHEMA_URL, + a: { b: { x: 1 }, z: { w: "s" } }, + c: { y: true }, + }); + expect(body(source).indexOf('"a"')).toBeLessThan(body(source).indexOf('"c"')); + }); + + test("renders inline tables expanded and empty containers compactly", () => { + expect(body("t = { a = 1, b = [] }\ne = {}\n")).toBe( + [' "t": {', ' "a": 1,', ' "b": []', " },", ' "e": {}'].join("\n"), + ); + }); + + test("keeps a one-line array on one line and spreads a multi-line array", () => { + expect(body('a = ["x", "y"]\nb = [\n "x",\n "y",\n]\n')).toBe( + [' "a": ["x", "y"],', ' "b": [', ' "x",', ' "y"', " ]"].join("\n"), + ); + }); + + test("renders array-of-tables elements as objects with their own comments", () => { + const source = + '[[experimental.inspect.rules]]\n# first\nname = "a"\n\n# second element\n[[experimental.inspect.rules]]\nname = "b" # why b\n'; + expect(body(source)).toBe( + [ + ' "experimental": {', + ' "inspect": {', + ' "rules": [', + " {", + " // first", + ' "name": "a"', + " },", + "", + " // second element", + " {", + ' "name": "b" // why b', + " }", + " ]", + " }", + " }", + ].join("\n"), + ); + }); + + test("writes CRLF output for a CRLF source", () => { + const { text } = converted('# c\r\nproject_id = "demo"\r\n'); + expect(text).toBe( + `{\r\n "$schema": "${CLI_CONFIG_SCHEMA_URL}",\r\n\r\n // c\r\n "project_id": "demo"\r\n}\r\n`, + ); + }); + + test("strips a leading byte order mark", () => { + expect(converted('#:schema https://example.com/s.json\nproject_id = "d"\n').schemaRef).toBe( + "https://example.com/s.json", + ); + }); +}); + +describe("convertCliConfigTomlToJsonc: comments", () => { + test("a group directly above a key or header leads it", () => { + expect(body('# about id\nproject_id = "demo"\n# about api\n[api]\nport = 1\n')).toBe( + [ + " // about id", + ' "project_id": "demo",', + " // about api", + ' "api": {', + ' "port": 1', + " }", + ].join("\n"), + ); + }); + + test("same-line comments follow the comma on keys and sit after the brace on headers", () => { + expect(body('[api] # the api\nport = 1 # the port\nschemas = ["a"] # many\n')).toBe( + [ + ' "api": { // the api', + ' "port": 1, // the port', + ' "schemas": ["a"] // many', + " }", + ].join("\n"), + ); + }); + + test("a group below a key stays with it, before the next child table", () => { + expect(body("[api]\nport = 1\n# about tls\n\n[api.tls]\nenabled = false\n")).toBe( + [ + ' "api": {', + ' "port": 1,', + " // about tls", + "", + ' "tls": {', + ' "enabled": false', + " }", + " }", + ].join("\n"), + ); + }); + + test("a detached group leads the next member and keeps its blank lines", () => { + expect(body("a = 1\n\n# about b\n\nb = 2\n")).toBe( + [' "a": 1,', "", " // about b", "", ' "b": 2'].join("\n"), + ); + }); + + test("a table with only commented keys keeps them inside its braces", () => { + expect(body('[db.vault]\n# secret = "env(X)"\n\n[db.pooler]\nenabled = true\n')).toBe( + [ + ' "db": {', + ' "vault": {', + ' // "secret": "env(X)",', + " },", + "", + ' "pooler": {', + ' "enabled": true', + " }", + " }", + ].join("\n"), + ); + }); + + test("a detached top-of-file group sits above the opening brace", () => { + const { text } = converted('# file header\n\nproject_id = "demo"\n'); + expect(text.startsWith("// file header\n\n{\n")).toBe(true); + }); + + test("a detached end-of-file group closes the root object", () => { + const { text } = converted("a = 1\n\n# the end\n"); + expect(text).toBe(`{\n "$schema": "${CLI_CONFIG_SCHEMA_URL}",\n "a": 1\n\n // the end\n}\n`); + }); + + test("keeps the text after the hash verbatim and trims trailing whitespace", () => { + expect(body("#tight\n# wide \na = 1\n")).toBe( + [" //tight", " // wide", ' "a": 1'].join("\n"), + ); + }); + + test("keeps comments inside a multi-line scalar array next to their elements", () => { + const source = + 'x = 1\n[api]\nschemas = [\n # about a\n "a", # keep a\n "b",\n # after b\n]\n'; + const outcome = converted(source); + expect(body(source)).toContain( + [ + ' "schemas": [', + " // about a", + ' "a", // keep a', + ' "b"', + " // after b", + " ]", + ].join("\n"), + ); + expect(outcome.commentCount).toBe(3); + expect(outcome.movedComments).toEqual([]); + }); + + test("keeps a comment after the opening bracket as the first element's lead", () => { + expect(body("a = [ # note\n 1,\n 2,\n]\n")).toBe( + [' "a": [', " // note", " 1,", " 2", " ]"].join("\n"), + ); + }); + + test("hoists comments inside nested arrays above their key and reports them", () => { + const source = "x = 1\n[api]\nm = [\n [1, 2], # keep\n [3],\n]\n"; + const outcome = converted(source); + expect(body(source)).toContain([" // keep", ' "m": ['].join("\n")); + expect(outcome.commentCount).toBe(1); + expect(outcome.movedComments).toEqual([ + { line: 4, text: "# keep", anchor: ["api", "m"] }, + ] satisfies ReadonlyArray); + }); + + test("hoists comments inside an inline table, including ones that hold a brace", () => { + const source = "a = { b = [\n 1, # why }\n] }\n"; + const outcome = converted(source); + expect(body(source)).toBe([" // why }", ' "a": {', ' "b": [1]', " }"].join("\n")); + expect(outcome.movedComments).toEqual([ + { line: 2, text: "# why }", anchor: ["a"] }, + ] satisfies ReadonlyArray); + }); + + test("keeps comments of a multi-line inline table", () => { + const outcome = converted("t = {\n a = 1, # c\n b = 2,\n}\n"); + expect(outcome.text).toContain("// c"); + expect(outcome.movedComments).toEqual([ + { line: 2, text: "# c", anchor: ["t"] }, + ] satisfies ReadonlyArray); + }); + + test("a comment above a table declared after its subtables stays before that header's keys", () => { + const source = "[auth.email]\nx = 1\n\n# about auth\n[auth]\ny = 2\n"; + const outcome = converted(source); + expect(body(source)).toBe( + [ + ' "auth": {', + ' "email": {', + ' "x": 1', + " },", + "", + " // about auth", + ' "y": 2', + " }", + ].join("\n"), + ); + expect(outcome.movedComments).toEqual([]); + }); + + test("keeps the blank line before an implicit parent table", () => { + expect(body('a = 1\n\n[remotes.staging]\nproject_id = "x"\n')).toBe( + [ + ' "a": 1,', + "", + ' "remotes": {', + ' "staging": {', + ' "project_id": "x"', + " }", + " }", + ].join("\n"), + ); + }); +}); + +describe("convertCliConfigTomlToJsonc: commented-out examples", () => { + test("a commented key becomes a commented member in place and ends the last real member with a comma", () => { + const source = "[api]\n# Port to use.\n# port = 1\nenabled = true\n# max_rows = 5\n"; + const outcome = converted(source); + expect(body(source)).toBe( + [ + ' "api": {', + " // Port to use.", + ' // "port": 1,', + ' "enabled": true,', + ' // "max_rows": 5,', + " }", + ].join("\n"), + ); + expectEachCommentOnce(source, outcome.text); + expect(uncommented(outcome.text)).toEqual({ + $schema: CLI_CONFIG_SCHEMA_URL, + api: { port: 1, enabled: true, max_rows: 5 }, + }); + }); + + test("a dotted commented key joins the existing table on its path", () => { + const source = + "[auth]\nhook.send_sms.enabled = true\n# hook.custom_access_token.enabled = true\n"; + const { text } = converted(source); + const uncommented = text.replace('// "custom_access_token"', '"custom_access_token"'); + expect(parseJsonc(uncommented)).toMatchObject({ + auth: { hook: { send_sms: { enabled: true }, custom_access_token: { enabled: true } } }, + }); + expectExamplesUncommentAtTomlPaths(source); + }); + + test("a dotted commented key under a table declared by header joins it", () => { + const source = + "[auth]\nenabled = true\n# Use a custom hook.\n# hook.b.enabled = true\n\n[auth.hook.a]\nenabled = true\n"; + const { text } = converted(source); + expect(text).toContain( + [" // Use a custom hook.", ' // "b": { "enabled": true },'].join("\n"), + ); + expectExamplesUncommentAtTomlPaths(source); + expectEachCommentOnce(source, text); + }); + + test("commented dotted keys sharing a parent become one commented object", () => { + const source = + '[auth]\nenabled = true\n# [auth.hook]\n# send_sms.enabled = true\n# send_sms.uri = "pg-functions://x"\n'; + const { text } = converted(source); + expect(text.match(/"send_sms"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { hook: { send_sms: { enabled: true, uri: "pg-functions://x" } } }, + }); + expectEachCommentOnce(source, text); + }); + + test("dotted keys under a commented header of an existing table join its existing subtables", () => { + const sources = [ + "# [auth]\n# hook.custom_access_token.enabled = false\n[auth.hook.send_sms]\nenabled = true\n", + "# [auth]\n# enabled = true\n\n# hook.custom_access_token.enabled = false\n[auth.hook.send_sms]\nenabled = true\n", + ]; + for (const source of sources) { + const { text } = converted(source); + expect(text.match(/"hook"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { hook: { custom_access_token: { enabled: false }, send_sms: { enabled: true } } }, + }); + expectExamplesUncommentAtTomlPaths(source); + expectEachCommentOnce(source, text); + } + }); + + test("prose above a commented header of an existing table stays above its resolved keys", () => { + const source = + "[auth.hook.send_sms]\nenabled = true\n\n# Only enable this in development.\n# [auth]\n# hook.custom_access_token.enabled = true\n"; + const lines = converted(source).text.split("\n"); + const prose = lines.findIndex((line) => line.includes("// Only enable this in development.")); + expect(lines[prose + 1]?.trim()).toBe('// "custom_access_token": { "enabled": true },'); + expect(uncommented(lines.join("\n"))).toMatchObject({ + auth: { hook: { custom_access_token: { enabled: true }, send_sms: { enabled: true } } }, + }); + expectEachCommentOnce(source, lines.join("\n")); + }); + + test("commented dotted keys in an active table share one commented object", () => { + const source = '[auth]\nenabled = true\n# hook.a.enabled = true\n# hook.a.uri = "x"\n'; + const { text } = converted(source); + expect(text.match(/"hook"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { enabled: true, hook: { a: { enabled: true, uri: "x" } } }, + }); + }); + + test("prose above a grouped commented dotted key stays directly above that key", () => { + const sources = [ + '[auth]\nenabled = true\n# hook.a.enabled = true\n# URI to invoke\n# hook.a.uri = "x"\n', + '[auth]\n# hook.a.enabled = true\nenabled = true\n# URI to invoke\n# hook.a.uri = "x"\n', + ]; + for (const source of sources) { + const lines = converted(source).text.split("\n"); + const prose = lines.findIndex((line) => line.includes("// URI to invoke")); + expect(lines[prose + 1]).toMatch(/^\s*\/\/\s+"uri": "x"/); + expectEachCommentOnce(source, converted(source).text); + } + }); + + test("commented dotted keys separated by blank lines share one commented object", () => { + const source = '[auth]\nenabled = true\n# hook.a.enabled = true\n\n# hook.a.uri = "x"\n'; + const { text } = converted(source); + expect(text.match(/"hook"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { enabled: true, hook: { a: { enabled: true, uri: "x" } } }, + }); + expectEachCommentOnce(source, text); + }); + + test("a prose paragraph between parts of a commented table keeps the table open", () => { + const sources = [ + '[api]\nport = 1\n\n# [api.tls]\n# enabled = true\n\n# Paths below are relative.\n\n# cert = "c"\n', + '[api]\nport = 1\n\n# [storage.s3]\n# enabled = true\n\n# Credentials:\n\n# key = "k"\n\n[db]\nx = 1\n', + ]; + const expected = [ + { api: { port: 1, tls: { enabled: true, cert: "c" } } }, + { api: { port: 1 }, storage: { s3: { enabled: true, key: "k" } }, db: { x: 1 } }, + ]; + for (const [index, source] of sources.entries()) { + const { text } = converted(source); + expect(uncommented(text)).toStrictEqual({ + $schema: CLI_CONFIG_SCHEMA_URL, + ...expected[index], + }); + expectEachCommentOnce(source, text); + } + }); + + test("a detached prose paragraph stays above the commented example that follows it", () => { + const sources = [ + '[auth]\nenabled = true\n\n# Uncomment to customise SMTP:\n\n# [auth.smtp]\n# host = "x"\n\n[db]\nport = 1\n', + '[auth]\nenabled = true\n\n# Uncomment to set the URL:\n\n# site_url = "x"\n', + ]; + for (const source of sources) { + const lines = converted(source).text.split("\n"); + const prose = lines.findIndex((line) => line.includes("// Uncomment to")); + expect(lines[prose + 1]).toMatch(/^\s+\/\/ "(smtp|site_url)"/); + expect(lines.slice(prose).findIndex((line) => line.startsWith(" }"))).toBeGreaterThan(1); + expectEachCommentOnce(source, converted(source).text); + } + }); + + test("a detached prose paragraph before an active table still leads that table", () => { + const source = + "[api]\nport = 1\n\n# [api.tls]\n# enabled = true\n\n# Database settings.\n\n[db]\nx = 1\n"; + const lines = converted(source).text.split("\n"); + const prose = lines.findIndex((line) => line.includes("// Database settings.")); + expect(lines.slice(prose + 1).find((line) => line.trim() !== "")).toMatch(/^\s+"db": \{/); + }); + + test("commented dotted keys separated by an active key share one commented object", () => { + const source = '[auth]\n# hook.a.enabled = true\nenabled = true\n# hook.a.uri = "x"\n'; + const { text } = converted(source); + expect(text.match(/"hook"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { enabled: true, hook: { a: { enabled: true, uri: "x" } } }, + }); + }); + + test("a commented dotted key joins a commented table example on the same path", () => { + const before = + '[auth]\nenabled = true\n# hook.a.uri = "x"\n\n# [auth.hook.a]\n# enabled = true\n'; + const after = '[auth]\n# [auth.hook.a]\n# enabled = true\nenabled = true\n# hook.a.uri = "x"\n'; + for (const source of [before, after]) { + const { text } = converted(source); + expect(text.match(/"hook"/g)).toHaveLength(1); + expect(uncommented(text)).toMatchObject({ + auth: { enabled: true, hook: { a: { enabled: true, uri: "x" } } }, + }); + expectEachCommentOnce(source, text); + } + }); + + test("a blank line inside a commented table example keeps the later keys in that example", () => { + const source = '[auth]\nenabled = true\n# [auth.hook.a]\n# enabled = true\n\n# uri = "x"\n'; + const { text } = converted(source); + const parsed = uncommented(text); + expect(parsed).toMatchObject({ + auth: { enabled: true, hook: { a: { enabled: true, uri: "x" } } }, + }); + expect(parsed).not.toHaveProperty("auth.uri"); + expectEachCommentOnce(source, text); + }); + + test("a dotted commented key becomes a nested inline object", () => { + const source = "[auth]\nenabled = true\n# hook.send_sms.enabled = true\n"; + expect(body(source)).toContain(' // "hook": { "send_sms": { "enabled": true } },'); + expect(uncommented(converted(source).text)).toMatchObject({ + auth: { hook: { send_sms: { enabled: true } } }, + }); + }); + + test("a commented header whose table exists puts its keys inside that table", () => { + const source = + '[db]\nport = 1\n\n[db.vault]\nenabled = true\n\n[db.pooler]\nport = 2\n\n# [db.vault]\n# secret_key = "env(X)"\n'; + const outcome = converted(source); + expect(body(source)).toContain( + [' "enabled": true,', "", ' // "secret_key": "env(X)",', " },"].join("\n"), + ); + expect(uncommented(outcome.text)).toMatchObject({ + db: { vault: { enabled: true, secret_key: "env(X)" } }, + }); + }); + + test("a commented header under a missing parent lands in the nearest existing ancestor", () => { + const source = + '[auth]\nenabled = true\n\n# [auth.hook.custom_access_token]\n# enabled = true\n# uri = "pg-functions://x"\n\n[auth.sms]\nenabled = false\n'; + const outcome = converted(source); + expect(body(source)).toBe( + [ + ' "auth": {', + ' "enabled": true,', + "", + ' // "hook": {', + ' // "custom_access_token": {', + ' // "enabled": true,', + ' // "uri": "pg-functions://x"', + " // }", + " // },", + "", + ' "sms": {', + ' "enabled": false', + " }", + " }", + ].join("\n"), + ); + expect(uncommented(outcome.text)).toMatchObject({ + auth: { hook: { custom_access_token: { enabled: true, uri: "pg-functions://x" } } }, + }); + }); + + test("a block closed before the end of its ancestor goes to the end of the ancestor", () => { + const source = + "[auth]\nenabled = true\n\n[auth.sms]\nenabled = false\n\n# [auth.captcha]\n# enabled = true\n\n[studio]\nenabled = true\n"; + expect(body(source)).toContain( + [" },", "", ' // "captcha": {', ' // "enabled": true', " // },", " },"].join( + "\n", + ), + ); + }); + + test("blocks under the same missing parent merge into one commented object", () => { + const source = + "[auth]\nenabled = true\n\n# This hook runs first.\n# [auth.hook.before_user_created]\n# enabled = true\n\n# This hook runs second.\n# [auth.hook.custom_access_token]\n# enabled = false\n"; + const outcome = converted(source); + expect(body(source)).toBe( + [ + ' "auth": {', + ' "enabled": true,', + "", + " // This hook runs first.", + ' // "hook": {', + ' // "before_user_created": {', + ' // "enabled": true', + " // },", + " // // This hook runs second.", + ' // "custom_access_token": {', + ' // "enabled": false', + " // }", + " // },", + " }", + ].join("\n"), + ); + expect(uncommented(outcome.text)).toMatchObject({ + auth: { + hook: { before_user_created: { enabled: true }, custom_access_token: { enabled: false } }, + }, + }); + }); + + test("prose directly above a commented header moves with its block", () => { + const source = + '[auth]\nenabled = true\n\n# Configure sessions.\n# [auth.sessions]\n# Force log out.\n# timebox = "24h"\n\n[studio]\nenabled = true\n'; + expect(body(source)).toContain( + [ + " // Configure sessions.", + ' // "sessions": {', + " // // Force log out.", + ' // "timebox": "24h"', + " // },", + ].join("\n"), + ); + expectEachCommentOnce(source, converted(source).text); + }); + + test("a commented header with no keys becomes an empty commented object", () => { + const source = "[storage]\nenabled = true\n# [storage.buckets.my-bucket]\n"; + expect(uncommented(converted(source).text)).toMatchObject({ + storage: { buckets: { "my-bucket": {} } }, + }); + }); + + test("a commented array-of-tables header becomes a commented array", () => { + const source = + '[experimental]\nenabled = true\n# [[experimental.rules]]\n# name = "a"\n# [[experimental.rules]]\n# name = "b"\n'; + expect(body(source)).toContain( + [ + ' // "rules": [', + " // {", + ' // "name": "a"', + " // },", + " // {", + ' // "name": "b"', + " // }", + " // ],", + ].join("\n"), + ); + expect(uncommented(converted(source).text)).toMatchObject({ + experimental: { rules: [{ name: "a" }, { name: "b" }] }, + }); + }); + + test("prose and lines that only look like TOML stay verbatim comments", () => { + const source = [ + "[api]", + "enabled = true", + "# Set port = 1 to change it.", + "# port = ", + "# mode = maybe", + "# list = [1, 2", + "# when = 1979-05-27", + "# [api tls]", + "# size = 1 # note", + "", + ].join("\n"); + const outcome = converted(source); + expect(body(source)).toBe( + [ + ' "api": {', + ' "enabled": true', + " // Set port = 1 to change it.", + " // port =", + " // mode = maybe", + " // list = [1, 2", + " // when = 1979-05-27", + " // [api tls]", + " // size = 1 # note", + " }", + ].join("\n"), + ); + expectEachCommentOnce(source, outcome.text); + }); + + test("a commented header that collides with a real key stays verbatim", () => { + const source = "[api]\nport = 1\n\n# [api.port.extra]\n# a = 1\n\n[studio]\nenabled = true\n"; + expect(converted(source).text).toContain("// [api.port.extra]\n // a = 1"); + }); + + test("a commented key above a nested table header stays in the object it follows", () => { + const source = "[a]\nx = 1\n\n# y = 2\n[a.b.c]\nz = 3\n"; + expect(uncommented(converted(source).text)).toMatchObject({ + a: { x: 1, y: 2, b: { c: { z: 3 } } }, + }); + }); + + test.each([ + ["a sibling header", "[api]\nenabled = true\n# max_rows = 1000\n[db]\nport = 1\n"], + [ + "a later reopening of an outer table", + "[api]\nenabled = true\n[db]\nport = 1\n# max = 1\n[api.tls]\nx = 1\n", + ], + [ + "the next array-of-tables element", + '[[experimental.inspect.rules]]\nname = "a"\n# query = "select 1"\n[[experimental.inspect.rules]]\nname = "b"\n', + ], + [ + "a blank line before a sibling header", + "[api]\nenabled = true\n\n# max_rows = 1000\n\n[db]\nport = 1\n", + ], + ["a dotted key", "[auth]\nhook.x = 1\n# y = 2\n[db]\nport = 1\n"], + ["a key detached at the top of the file", '# Main\n# project_id = "x"\n\n[api]\nport = 1\n'], + ["a file holding only a commented key", "# b = 2\n"], + [ + "prose, a key and a header in one group", + "[api]\nenabled = true\n# max_rows = 1000\n# About db.\n[db]\nport = 1\n", + ], + [ + "a second commented array element with its own prose", + "[a]\nz = 1\n# [[a.rules]]\n# name = 'a'\n# Second.\n# [[a.rules]]\n# name = 'b'\n", + ], + ])("a commented key above %s uncomments at its TOML path", (_name, source) => { + expectExamplesUncommentAtTomlPaths(source); + expectEachCommentOnce(source, converted(source).text); + }); + + test("prose above a second commented array element stays inside the array", () => { + const source = + "[a]\nz = 1\n# [[a.rules]]\n# name = 'a'\n# Second.\n# [[a.rules]]\n# name = 'b'\n"; + expect(body(source)).toContain([" // },", " // // Second.", " // {"].join("\n")); + }); + + test("a commented header naming an existing table without keys stays verbatim", () => { + const source = "[db.vault]\nenabled = true\n\n[api]\nport = 1\n\n# [db.vault]\n"; + const { text } = converted(source); + expect(text).toContain("// [db.vault]"); + expect(parseJsonc(text)).toMatchObject({ db: { vault: { enabled: true } }, api: { port: 1 } }); + }); + + test("a commented table header with prose but no keys stays verbatim", () => { + const source = "[db]\nenabled = true\n\n# [db]\n# Some prose\n\n[api]\nport = 1\n"; + const { text } = converted(source); + expect(text).toContain("// [db]"); + expect(text).toContain("// Some prose"); + expectEachCommentOnce(source, text); + }); + + test("trailing prose after the last commented block stays inside that block", () => { + const source = + "[auth]\nenabled = true\n\n# [auth.hook.a]\n# enabled = true\n# Trailing prose.\n\n[studio]\nx = 1\n"; + expect(body(source)).toContain( + [' // "enabled": true', " // // Trailing prose.", " // }"].join("\n"), + ); + }); + + test("prose directly above the next table after a commented block leads that table", () => { + const source = + "[auth]\nenabled = true\n# [auth.hook.a]\n# enabled = true\n# Studio settings.\n[studio]\nx = 1\n"; + const { text } = converted(source); + expect(text).toContain([" // Studio settings.", ' "studio": {'].join("\n")); + expectEachCommentOnce(source, text); + }); + + test("a verbatim fallback keeps its source order relative to merged blocks", () => { + const source = "[a]\nz = 1\n# [[a.r]]\n# n = 1\n# [a.r]\n# n = 2\n"; + const { text } = converted(source); + expect(text.indexOf('"r": [')).toBeLessThan(text.indexOf("// [a.r]")); + expectEachCommentOnce(source, text); + }); + + test.each([ + [ + "a dotted key with spaced dots", + "[db]\nport = 1\n# e.g. port = 5432\n", + "// e.g. port = 5432", + ], + ["a bracketed word", "[db]\nport = 1\n# [Deprecated]\n# [note]\n", "// [Deprecated]"], + ])("prose that looks like TOML stays a comment: %s", (_name, source, line) => { + const { text } = converted(source); + expect(text).toContain(line); + expect(parseJsonc(text)).toEqual({ $schema: CLI_CONFIG_SCHEMA_URL, db: { port: 1 } }); + expect(commentedMembers(text.split("\n"))).toEqual([]); + }); +}); + +describe("convertCliConfigTomlToJsonc: refusals", () => { + test("refuses TOML dates with the line and how to fix them", () => { + const error = refusal("a = 1\nwhen = 1979-05-27\n"); + expect(error).toBeInstanceOf(CliConfigConvertError); + expect(error).toMatchObject({ reason: "unsupported_value", sourceLine: 2 }); + expect(error.detail).toContain("Quote the value as a string, then rerun"); + }); + + test("refuses non-finite floats", () => { + expect(refusal("a = inf\n").reason).toBe("unsupported_value"); + expect(refusal("a = nan\n").reason).toBe("unsupported_value"); + }); + + test("refuses malformed TOML with the line", () => { + expect(refusal("a = 1\nb = \n")).toMatchObject({ reason: "parse_error", sourceLine: 2 }); + }); + + test("leaves the source line undefined when the refusal has none", () => { + expect(refusal('"$schema" = 1\n').sourceLine).toBeUndefined(); + }); +}); + +const RICH_TOML = `#:schema ${CLI_CONFIG_SCHEMA_URL} + +# project +project_id = "demo" + +[api] +port = 54321 # api port +schemas = [ + "public", # exposed + "graphql_public", +] + +[auth.external.github] +enabled = true +client_id = "env(GITHUB_ID)" +secret = "env(GITHUB_SECRET)" + +[functions.hello] +verify_jwt = false +entrypoint = "./functions/hello/index.ts" + +[[experimental.inspect.rules]] +name = "a" +query = "select 1" + +[[experimental.inspect.rules]] +name = "b" + +[remotes.staging] +project_id = "abcdefghijklmnopqrst" + +[remotes.staging.api] +port = 1 +`; + +describe("convertCliConfigTomlToJsonc: loader round trip", () => { + test("a converted project loads to the same config and raw document", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const env = "GITHUB_ID=id\nGITHUB_SECRET=shh\n"; + const makeProject = Effect.fnUntraced(function* (file: string, content: string) { + const root = yield* fs.makeTempDirectoryScoped({ prefix: "supabase-convert-" }); + yield* fs.makeDirectory(path.join(root, "supabase"), { recursive: true }); + yield* fs.writeFileString(path.join(root, "supabase", file), content); + yield* fs.writeFileString(path.join(root, ".env"), env); + return root; + }); + + const tomlRoot = yield* makeProject("config.toml", RICH_TOML); + const jsoncRoot = yield* makeProject("config.jsonc", converted(RICH_TOML).text); + + const fromToml = yield* loadCliConfig(tomlRoot, { search: false }); + const fromJsonc = yield* loadCliConfig(jsoncRoot, { search: false }); + const rawToml = yield* parseCliConfigDocumentFile(tomlRoot, { search: false }); + const rawJsonc = yield* parseCliConfigDocumentFile(jsoncRoot, { search: false }); + + expect(fromJsonc?.format).toBe("json"); + expect(fromJsonc?.config).toEqual(fromToml?.config); + expect(fromJsonc?.config.remotes["staging"]?.project_id).toBe("abcdefghijklmnopqrst"); + expect(fromJsonc?.config.functions["hello"]?.verify_jwt).toBe(false); + expect(fromJsonc?.config.experimental["inspect"]?.rules).toHaveLength(2); + const { $schema: _schema, ...jsoncDocument } = Object(rawJsonc?.rawDocument); + expect(jsoncDocument).toEqual(rawToml?.rawDocument); + }).pipe(Effect.scoped, Effect.provide(BunServices.layer), Effect.runPromise)); +}); diff --git a/packages/config/src/config-edit.ts b/packages/config/src/config-edit.ts index 66a3e1da7c..f6df6e45be 100644 --- a/packages/config/src/config-edit.ts +++ b/packages/config/src/config-edit.ts @@ -8,6 +8,14 @@ import { import * as SmolToml from "smol-toml"; import type { ConfigFormat } from "./config-format.ts"; import { parseJsonc } from "./jsonc.ts"; +import { + scanTomlDocument, + skipInlineWhitespace, + type TomlHeaderToken, + type TomlKeyToken, + type TomlScanResult, + type TomlToken, +} from "./toml-scan.ts"; /** * Format-preserving surgical editor for `supabase/config.{toml,json,jsonc}`. Pure and synchronous: @@ -76,7 +84,7 @@ function isRemotesLabelRoot(path: ReadonlyArray): boolean { // package's wider env-resolution graph. const ENV_CAPTURE_REGEX = /^env\((.*)\)$/; -function isPlainRecord(value: unknown): value is Readonly> { +export function isPlainRecord(value: unknown): value is Readonly> { return ( typeof value === "object" && value !== null && @@ -149,7 +157,7 @@ function isEnvReferenceValue(value: unknown): boolean { * round-trip-faithful `toISOString()`, since two distinct instances of "the same" TOML * date/time are never `===`). Used both for mandatory re-parse verification and for * detecting a no-op edit. */ -function deepEqualValue(a: unknown, b: unknown): boolean { +export function deepEqualValue(a: unknown, b: unknown): boolean { if (a === b) { return true; } @@ -306,450 +314,6 @@ function renderLeafValue(value: ConfigEditLeafValue): string { return isLeafArrayValue(value) ? `[${value.map(renderScalar).join(", ")}]` : renderScalar(value); } -// Character-level TOML scanner. Produces top-level tokens in document order: blank lines, -// comments, table headers, and key-value lines (multi-line arrays/strings scanned as single -// opaque spans). Never throws — an unrecognized construct yields an `{ error }` result instead. - -interface TomlHeaderToken { - readonly kind: "header"; - readonly start: number; - readonly end: number; - readonly path: ReadonlyArray; - readonly isArrayOfTables: boolean; -} - -interface TomlKeyToken { - readonly kind: "kv"; - readonly start: number; - readonly end: number; - /** Fully qualified: the enclosing table's path plus this key's own (possibly dotted) segments. */ - readonly path: ReadonlyArray; - readonly tableIndex: number; - readonly valueStart: number; - readonly valueEnd: number; - /** True when this key's OWN value is an inline table (`{ ... }`) — see `findInlineTableOnPath`. */ - readonly insideInlineTable: boolean; -} - -interface TomlBlankToken { - readonly kind: "blank"; - readonly start: number; - readonly end: number; -} - -interface TomlCommentToken { - readonly kind: "comment"; - readonly start: number; - readonly end: number; -} - -type TomlToken = TomlHeaderToken | TomlKeyToken | TomlBlankToken | TomlCommentToken; - -interface TomlScanResult { - readonly source: string; - readonly tokens: ReadonlyArray; - readonly headers: ReadonlyArray; - readonly newline: "\n" | "\r\n"; - readonly endsWithNewline: boolean; -} - -interface TomlScanError { - readonly error: string; -} - -function charAt(source: string, pos: number): string { - const ch = source[pos]; - return ch ?? ""; -} - -function skipInlineWhitespace(source: string, pos: number): number { - let cursor = pos; - while (cursor < source.length && (source[cursor] === " " || source[cursor] === "\t")) { - cursor++; - } - return cursor; -} - -function skipToEndOfLine(source: string, pos: number): number { - let cursor = pos; - while (cursor < source.length && source[cursor] !== "\n" && source[cursor] !== "\r") { - cursor++; - } - return cursor; -} - -function advancePastNewline(source: string, pos: number): number { - if (source[pos] === "\r" && source[pos + 1] === "\n") { - return pos + 2; - } - if (source[pos] === "\n" || source[pos] === "\r") { - return pos + 1; - } - return pos; -} - -function scanBasicString(source: string, pos: number): number | null { - let cursor = pos; - while (cursor < source.length) { - const ch = source[cursor]; - if (ch === "\\") { - cursor += 2; - continue; - } - if (ch === '"') { - return cursor + 1; - } - if (ch === "\n" || ch === "\r") { - return null; - } - cursor++; - } - return null; -} - -function scanLiteralString(source: string, pos: number): number | null { - let cursor = pos; - while (cursor < source.length) { - const ch = source[cursor]; - if (ch === "'") { - return cursor + 1; - } - if (ch === "\n" || ch === "\r") { - return null; - } - cursor++; - } - return null; -} - -function scanMultilineBasicString(source: string, pos: number): number | null { - let cursor = pos; - while (cursor < source.length) { - const ch = source[cursor]; - if (ch === "\\") { - cursor += 2; - continue; - } - if (ch === '"' && source.startsWith('"""', cursor)) { - cursor += 3; - let extra = 0; - while (extra < 2 && source[cursor] === '"') { - cursor++; - extra++; - } - return cursor; - } - cursor++; - } - return null; -} - -function scanMultilineLiteralString(source: string, pos: number): number | null { - let cursor = pos; - while (cursor < source.length) { - if (source[cursor] === "'" && source.startsWith("'''", cursor)) { - cursor += 3; - let extra = 0; - while (extra < 2 && source[cursor] === "'") { - cursor++; - extra++; - } - return cursor; - } - cursor++; - } - return null; -} - -function scanBareValue(source: string, pos: number): number { - let cursor = pos; - while (cursor < source.length) { - const ch = source[cursor]; - if (ch === "#" || ch === "\n" || ch === "\r") { - break; - } - cursor++; - } - // Trailing inline whitespace before a `#` comment (or EOL) belongs to the comment/line-ending, - // not the value: without this, replacing a value would fold that space into the replaced span - // and eat it. - while (cursor > pos && (source[cursor - 1] === " " || source[cursor - 1] === "\t")) { - cursor--; - } - return cursor; -} - -/** Scans a bracketed value (array or inline table), tracking nested strings/brackets so an - * unrelated `]`/`}`/`#` inside a string never terminates the scan early. `openChar`/`closeChar` - * select array (`[`/`]`) or inline-table (`{`/`}`) matching; comments (`#...`) are only - * meaningful — and skippable — inside an array, never an inline table. */ -function scanBracketedValue( - source: string, - pos: number, - openChar: string, - closeChar: string, - allowComments: boolean, -): number | null { - let cursor = pos; - let depth = 1; - while (cursor < source.length) { - const ch = source[cursor]; - if (ch === '"') { - const next = source.startsWith('"""', cursor) - ? scanMultilineBasicString(source, cursor + 3) - : scanBasicString(source, cursor + 1); - if (next === null) { - return null; - } - cursor = next; - continue; - } - if (ch === "'") { - const next = source.startsWith("'''", cursor) - ? scanMultilineLiteralString(source, cursor + 3) - : scanLiteralString(source, cursor + 1); - if (next === null) { - return null; - } - cursor = next; - continue; - } - if (allowComments && ch === "#") { - cursor = advancePastNewline(source, skipToEndOfLine(source, cursor)); - continue; - } - if (ch === openChar) { - depth++; - cursor++; - continue; - } - if (ch === closeChar) { - depth--; - cursor++; - if (depth === 0) { - return cursor; - } - continue; - } - cursor++; - } - return null; -} - -function scanValue(source: string, start: number): number | null { - const ch = charAt(source, start); - if (ch === '"') { - return source.startsWith('"""', start) - ? scanMultilineBasicString(source, start + 3) - : scanBasicString(source, start + 1); - } - if (ch === "'") { - return source.startsWith("'''", start) - ? scanMultilineLiteralString(source, start + 3) - : scanLiteralString(source, start + 1); - } - if (ch === "[") { - return scanBracketedValue(source, start + 1, "[", "]", true); - } - if (ch === "{") { - return scanBracketedValue(source, start + 1, "{", "}", false); - } - if (ch === "") { - return null; - } - return scanBareValue(source, start); -} - -const BARE_KEY_CHAR = /^[A-Za-z0-9_-]$/; - -function unescapeBasicString(raw: string): string { - let result = ""; - for (let i = 0; i < raw.length; i++) { - const ch = raw[i]; - if (ch !== "\\") { - result += ch ?? ""; - continue; - } - const next = raw[i + 1]; - if (next === "\\" || next === '"') { - result += next; - i++; - } else if (next === "b") { - result += "\b"; - i++; - } else if (next === "f") { - result += "\f"; - i++; - } else if (next === "n") { - result += "\n"; - i++; - } else if (next === "r") { - result += "\r"; - i++; - } else if (next === "t") { - result += "\t"; - i++; - } else if (next === "u") { - result += String.fromCodePoint(Number.parseInt(raw.slice(i + 2, i + 6), 16)); - i += 5; - } else if (next === "U") { - result += String.fromCodePoint(Number.parseInt(raw.slice(i + 2, i + 10), 16)); - i += 9; - } else { - result += next ?? ""; - i++; - } - } - return result; -} - -interface DottedKeyScan { - readonly segments: ReadonlyArray; - readonly end: number; -} - -/** Parses one or more dot-separated key segments (bare, basic-quoted, or literal-quoted), - * used for both table headers (`[a."b.c"]`) and key-value lines (`a."b.c" = 1`). Stops as soon - * as no further `.`-continuation is found; the caller checks for the expected terminator - * (`]` or `=`) itself. */ -function scanDottedKeyPath(source: string, pos: number): DottedKeyScan | null { - const segments: Array = []; - let cursor = pos; - for (;;) { - cursor = skipInlineWhitespace(source, cursor); - const ch = charAt(source, cursor); - if (ch === '"') { - const strEnd = scanBasicString(source, cursor + 1); - if (strEnd === null) { - return null; - } - segments.push(unescapeBasicString(source.slice(cursor + 1, strEnd - 1))); - cursor = strEnd; - } else if (ch === "'") { - const strEnd = scanLiteralString(source, cursor + 1); - if (strEnd === null) { - return null; - } - segments.push(source.slice(cursor + 1, strEnd - 1)); - cursor = strEnd; - } else if (BARE_KEY_CHAR.test(ch)) { - let bareEnd = cursor; - while (BARE_KEY_CHAR.test(charAt(source, bareEnd))) { - bareEnd++; - } - segments.push(source.slice(cursor, bareEnd)); - cursor = bareEnd; - } else { - return null; - } - const afterSegment = skipInlineWhitespace(source, cursor); - if (charAt(source, afterSegment) === ".") { - cursor = afterSegment + 1; - continue; - } - cursor = afterSegment; - break; - } - return { segments, end: cursor }; -} - -function scanTomlDocument(source: string): TomlScanResult | TomlScanError { - const tokens: Array = []; - const headers: Array = []; - const length = source.length; - let pos = 0; - let currentTableIndex = -1; - let currentTablePath: ReadonlyArray = []; - - while (pos < length) { - const lineStart = pos; - const firstNonWhitespace = skipInlineWhitespace(source, pos); - const ch = charAt(source, firstNonWhitespace); - - if (ch === "" || ch === "\n" || ch === "\r") { - const end = advancePastNewline(source, firstNonWhitespace); - tokens.push({ kind: "blank", start: lineStart, end }); - pos = end === firstNonWhitespace ? length : end; - continue; - } - - if (ch === "#") { - const end = advancePastNewline(source, skipToEndOfLine(source, firstNonWhitespace)); - tokens.push({ kind: "comment", start: lineStart, end }); - pos = end; - continue; - } - - if (ch === "[") { - const isArrayOfTables = charAt(source, firstNonWhitespace + 1) === "["; - const keyStart = firstNonWhitespace + (isArrayOfTables ? 2 : 1); - const parsedPath = scanDottedKeyPath(source, keyStart); - if (parsedPath === null || parsedPath.segments.length === 0) { - return { error: `malformed table header at offset ${lineStart}` }; - } - let closeCursor = parsedPath.end; - if (charAt(source, closeCursor) !== "]") { - return { error: `malformed table header at offset ${lineStart}` }; - } - closeCursor += 1; - if (isArrayOfTables) { - if (charAt(source, closeCursor) !== "]") { - return { error: `malformed array-of-tables header at offset ${lineStart}` }; - } - closeCursor += 1; - } - const end = advancePastNewline(source, skipToEndOfLine(source, closeCursor)); - const headerToken: TomlHeaderToken = { - kind: "header", - start: lineStart, - end, - path: parsedPath.segments, - isArrayOfTables, - }; - headers.push(headerToken); - tokens.push(headerToken); - currentTableIndex = headers.length - 1; - currentTablePath = parsedPath.segments; - pos = end; - continue; - } - - const parsedKey = scanDottedKeyPath(source, firstNonWhitespace); - if (parsedKey === null || parsedKey.segments.length === 0) { - return { error: `malformed key-value line at offset ${lineStart}` }; - } - const afterKey = skipInlineWhitespace(source, parsedKey.end); - if (charAt(source, afterKey) !== "=") { - return { error: `malformed key-value line at offset ${lineStart}` }; - } - const valueStart = skipInlineWhitespace(source, afterKey + 1); - const valueEndRaw = scanValue(source, valueStart); - if (valueEndRaw === null) { - return { error: `unterminated value at offset ${valueStart}` }; - } - const end = advancePastNewline(source, skipToEndOfLine(source, valueEndRaw)); - const fullPath = [...currentTablePath, ...parsedKey.segments]; - const rawValueText = source.slice(valueStart, valueEndRaw); - tokens.push({ - kind: "kv", - start: lineStart, - end, - path: fullPath, - tableIndex: currentTableIndex, - valueStart, - valueEnd: valueEndRaw, - insideInlineTable: rawValueText.startsWith("{"), - }); - pos = end; - } - - const newline = source.includes("\r\n") ? "\r\n" : "\n"; - // A mixed-EOL file may be detected as CRLF overall (because some earlier line uses it) while - // its final line ends in a bare `\n`; checking for `"\n"` alone (rather than the detected - // flavor) covers both terminators, since a `"\r\n"`-ending string always also ends in `"\n"`. - return { source, tokens, headers, newline, endsWithNewline: source.endsWith("\n") }; -} - interface Splice { readonly start: number; readonly end: number; @@ -1081,7 +645,7 @@ function planTomlSplices(scan: TomlScanResult, leaves: ReadonlyArray): function applyTomlEdits(source: string, edits: ReadonlyArray): ConfigEditOutcome { const scan = scanTomlDocument(source); if ("error" in scan) { - return refused("parse_error", [], scan.error); + return refused("parse_error", [], `${scan.error} at offset ${scan.offset}`); } const duplicate = findDuplicateTableHeader(scan.headers); diff --git a/packages/config/src/entrypoint-purity.unit.test.ts b/packages/config/src/entrypoint-purity.unit.test.ts index 1130df97b1..20cbbfafa0 100644 --- a/packages/config/src/entrypoint-purity.unit.test.ts +++ b/packages/config/src/entrypoint-purity.unit.test.ts @@ -519,6 +519,7 @@ describe("src/internal.ts export surface", () => { expect(Object.keys(internalEntrypoint).sort()).toMatchInlineSnapshot(` [ "AUTH_HOOK_NAMES", + "CliConfigConvertError", "CliConfigWriteError", "DEFAULT_MIGRATION_CHECK_SEVERITY", "ENV_CAPTURE_REGEX", @@ -527,6 +528,8 @@ describe("src/internal.ts export surface", () => { "PROVIDER_SIGNUP_ALIASES", "applyConfigEdits", "cliConfigFormatForPath", + "convertCliConfigTomlToJsonc", + "createCliConfigDocumentText", "decodeCliConfigDocumentForValidationEffect", "decodeMergedCliConfig", "dualScopeProjectConfigPaths", @@ -544,6 +547,7 @@ describe("src/internal.ts export surface", () => { "resolveCliConfigSubtree", "resolveCliConfigValue", "unmappedSecretApiPaths", + "updateJsonDocument", "withoutSafeIntegerBounds", "writeCliConfigDocumentText", ] diff --git a/packages/config/src/errors.ts b/packages/config/src/errors.ts index 1c02cbbe9f..d59c297e27 100644 --- a/packages/config/src/errors.ts +++ b/packages/config/src/errors.ts @@ -35,6 +35,12 @@ export class CliConfigRemovedKeyError extends Data.TaggedError("CliConfigRemoved ...this.removedKeys.map(({ key, replacement }) => ` ${key}: use ${replacement} instead.`), ].join("\n"); } + + /** The edit that clears this error, for commands that print a remediation next to the message. */ + get suggestion(): string { + const file = this.path.split(/[\\/]/).slice(-2).join("/"); + return `Update ${file}, then rerun the command.`; + } } /** Both `config.json` and `config.jsonc` exist in one project; `paths` lists every conflicting file. */ diff --git a/packages/config/src/internal.ts b/packages/config/src/internal.ts index 73485b0f49..9262254961 100644 --- a/packages/config/src/internal.ts +++ b/packages/config/src/internal.ts @@ -23,7 +23,13 @@ export { type ConfigEditRefusal, type ConfigEditRefusalReason, type ConfigEditValue, + updateJsonDocument, } from "./config-edit.ts"; +export { + CliConfigConvertError, + convertCliConfigTomlToJsonc, + type MovedTomlComment, +} from "./config-convert.ts"; export { projectConfigApiBlockKeys } from "./project-config/api-attributes.ts"; export { dualScopeProjectConfigPaths } from "./project-config/project-config.ts"; export { AUTH_HOOK_NAMES, unmappedSecretApiPaths } from "./project-config/registry-auth.ts"; @@ -43,6 +49,7 @@ export { type ParseMergeCliConfigOptions, remoteNameForProjectRef, remoteProjectIdEntries, + createCliConfigDocumentText, writeCliConfigDocumentText, decodeCliConfigDocumentForValidationEffect, type DecodeCliConfigDocumentForValidationEffectOptions, diff --git a/packages/config/src/io.stages.unit.test.ts b/packages/config/src/io.stages.unit.test.ts index 1cc0d90c4a..c1e214cf93 100644 --- a/packages/config/src/io.stages.unit.test.ts +++ b/packages/config/src/io.stages.unit.test.ts @@ -172,7 +172,7 @@ enabled = true expect(failure).toMatchObject({ _tag: "CliConfigRemovedKeyError", removedKeys: [ - { key: "[remotes.staging.inbucket]", replacement: "[remotes.staging.local_smtp]" }, + { key: "remotes.staging.inbucket", replacement: "remotes.staging.local_smtp" }, ], }); }), diff --git a/packages/config/src/io.ts b/packages/config/src/io.ts index 59e263b4f4..30d17fca89 100644 --- a/packages/config/src/io.ts +++ b/packages/config/src/io.ts @@ -1,5 +1,6 @@ import { randomBytes } from "node:crypto"; import { Clock, Effect, FileSystem, Option, Path, Predicate, Redacted } from "effect"; +import type { PlatformError } from "effect/PlatformError"; import * as SmolToml from "smol-toml"; import { CliConfigSchema, type CliConfig } from "./base.ts"; import { @@ -935,6 +936,57 @@ export const saveCliConfig = Effect.fn("CliConfig.save")(function* (options: Sav } satisfies LoadedCliConfig; }); +const succeedUnlessExists = (error: PlatformError) => + Predicate.isTagged(error.reason, "AlreadyExists") ? Effect.succeed(false) : Effect.fail(error); + +/** Publishes a new file with exactly `mode`, never replacing an existing one: `false` means the + * target already existed and was left untouched. Where hard links are unsupported, it falls back + * to an exclusive create, which readers can observe mid-write. */ +export const createCliConfigDocumentText = Effect.fn("CliConfig.createDocument")(function* ( + filePath: string, + content: string, + mode: number, +) { + const fs = yield* FileSystem.FileSystem; + const now = yield* Clock.currentTimeMillis; + const tmpPath = `${filePath}.tmp.${now}.${randomBytes(3).toString("hex")}`; + + const createExclusive = Effect.scoped( + Effect.gen(function* () { + const file = yield* fs.open(filePath, { flag: "wx", mode }); + yield* Effect.gen(function* () { + yield* fs.chmod(filePath, mode); + yield* file.writeAll(new TextEncoder().encode(content)); + }).pipe(Effect.onError(() => fs.remove(filePath).pipe(Effect.ignore))); + return true; + }), + ).pipe(Effect.catchTag("PlatformError", succeedUnlessExists)); + + const created = yield* Effect.gen(function* () { + yield* fs.writeFileString(tmpPath, content, { mode }); + yield* fs.chmod(tmpPath, mode); + return yield* fs.link(tmpPath, filePath).pipe( + Effect.as(true), + Effect.catchTag("PlatformError", (error) => + Predicate.isTagged(error.reason, "AlreadyExists") ? Effect.succeed(false) : createExclusive, + ), + ); + }).pipe( + Effect.ensuring(fs.remove(tmpPath).pipe(Effect.ignore)), + Effect.catchTag("PlatformError", (cause) => + Effect.fail( + new CliConfigWriteError({ + path: filePath, + cause, + message: `Failed to write ${filePath}: ${cause.message}`, + }), + ), + ), + ); + yield* Effect.annotateCurrentSpan("config.created", created); + return created; +}); + /** Atomically replaces text while applying the target mode at creation to protect sensitive files. */ export const writeCliConfigDocumentText = Effect.fn("CliConfig.writeDocument")(function* ( filePath: string, diff --git a/packages/config/src/io.unit.test.ts b/packages/config/src/io.unit.test.ts index 4730ae0608..a5d09d5f2e 100644 --- a/packages/config/src/io.unit.test.ts +++ b/packages/config/src/io.unit.test.ts @@ -36,6 +36,7 @@ import { remoteNameForProjectRef, remoteProjectIdEntries, saveCliConfig, + createCliConfigDocumentText, writeCliConfigDocumentText, } from "./io.ts"; import { loadCliConfig as loadCliConfigFromNode } from "./node.ts"; @@ -285,6 +286,15 @@ describe("config io", () => { expect(() => decodeCliConfig({ api: { max_rows: NaN } })).toThrow("Expected a finite number"); }); + test("decodes an optional api.db_pool of one or more whole connections", () => { + expect(decodeCliConfig({}).api.db_pool).toBeUndefined(); + expect(decodeCliConfig({ api: { db_pool: 1 } }).api.db_pool).toBe(1); + expect(() => decodeCliConfig({ api: { db_pool: 0 } })).toThrow("one or more connections"); + expect(() => decodeCliConfig({ api: { db_pool: 1.5 } })).toThrow( + "a whole number of connections", + ); + }); + test("only validates the highest-priority enabled sms provider during decode", () => { // Providers are validated in a fixed priority order (twilio, twilio_verify, messagebird, // textlocal, vonage); only the first enabled one is checked, so a complete, higher-priority @@ -1213,6 +1223,24 @@ major_version = 16 }), )); + test("saving TOML keeps a #:schema directive that has trailing whitespace", () => + runConfigEffect( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { join } = yield* Path.Path; + const cwd = yield* makeTempProject(); + const tomlPath = yield* configTomlPath(cwd); + const directive = "#:schema https://example.com/config.schema.json"; + yield* fs.makeDirectory(join(cwd, "supabase"), { recursive: true }); + yield* fs.writeFileString(tomlPath, `${directive} \nproject_id = "old_ref"\n`); + + yield* saveCliConfig({ cwd, config: sampleConfig }); + + const written = yield* fs.readFileString(tomlPath); + expect(written.split("\n")[0]?.trimEnd()).toBe(directive); + }), + )); + test("preserves the discovered project format when saving from a nested cwd", () => runConfigEffect( Effect.gen(function* () { @@ -2574,14 +2602,14 @@ project_id = "stagingrefaaaaaaaaaa" { name: "[inbucket] whatever its contents", toml: "[inbucket]\nenabled = false\n", - key: "[inbucket]", - replacement: "[local_smtp]", + key: "inbucket", + replacement: "local_smtp", }, { name: "[remotes.*.inbucket]", toml: `${stagingRemote}\n[remotes.staging.inbucket]\nport = 33333\n`, - key: "[remotes.staging.inbucket]", - replacement: "[remotes.staging.local_smtp]", + key: "remotes.staging.inbucket", + replacement: "remotes.staging.local_smtp", }, { name: "a non-empty experimental.orioledb_version", @@ -2604,20 +2632,20 @@ project_id = "stagingrefaaaaaaaaaa" { name: "an enabled [auth.external.slack]", toml: "[auth.external.slack]\nenabled = true\n", - key: "[auth.external.slack]", - replacement: "[auth.external.slack_oidc]", + key: "auth.external.slack", + replacement: "auth.external.slack_oidc", }, { name: "a disabled [auth.external.linkedin]", toml: "[auth.external.linkedin]\nenabled = false\n", - key: "[auth.external.linkedin]", - replacement: "[auth.external.linkedin_oidc]", + key: "auth.external.linkedin", + replacement: "auth.external.linkedin_oidc", }, { name: "a remote's [auth.external.linkedin]", toml: `${stagingRemote}\n[remotes.staging.auth.external.linkedin]\nenabled = true\n`, - key: "[remotes.staging.auth.external.linkedin]", - replacement: "[remotes.staging.auth.external.linkedin_oidc]", + key: "remotes.staging.auth.external.linkedin", + replacement: "remotes.staging.auth.external.linkedin_oidc", }, ])("rejects $name", ({ toml, key, replacement }) => runConfigEffect( @@ -2637,8 +2665,11 @@ project_id = "stagingrefaaaaaaaaaa" ); expect(error.message).toBe( - "[inbucket] in supabase/config.toml is no longer supported. Use [local_smtp] instead.", + "inbucket in supabase/config.toml is no longer supported. Use local_smtp instead.", ); + expect(error).toMatchObject({ + suggestion: "Update supabase/config.toml, then rerun the command.", + }); }), )); @@ -2669,13 +2700,16 @@ enabled = false expect(error.message).toBe( [ "supabase/config.toml uses config keys that are no longer supported:", - " [inbucket]: use [local_smtp] instead.", + " inbucket: use local_smtp instead.", " experimental.orioledb_version: use db.orioledb_version instead.", - " [auth.external.slack]: use [auth.external.slack_oidc] instead.", - " [remotes.staging.inbucket]: use [remotes.staging.local_smtp] instead.", - " [remotes.staging.auth.external.linkedin]: use [remotes.staging.auth.external.linkedin_oidc] instead.", + " auth.external.slack: use auth.external.slack_oidc instead.", + " remotes.staging.inbucket: use remotes.staging.local_smtp instead.", + " remotes.staging.auth.external.linkedin: use remotes.staging.auth.external.linkedin_oidc instead.", ].join("\n"), ); + expect(error).toMatchObject({ + suggestion: "Update supabase/config.toml, then rerun the command.", + }); }), )); @@ -3126,6 +3160,91 @@ describe("remoteNameForProjectRef / remoteProjectIdEntries", () => { }); }); +describe("createCliConfigDocumentText", () => { + function targetIn() { + return Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { join } = yield* Path.Path; + const dir = join(yield* makeTempProject(), "supabase"); + yield* fs.makeDirectory(dir, { recursive: true }); + return { dir, filePath: join(dir, "config.jsonc") }; + }); + } + + test("creates the file with the requested mode and no temp file left behind", () => + runConfigEffect( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { dir, filePath } = yield* targetIn(); + + const created = yield* createCliConfigDocumentText(filePath, "{}\n", 0o600); + + expect(created).toBe(true); + expect(yield* fs.readFileString(filePath)).toBe("{}\n"); + expect((yield* fs.stat(filePath)).mode & 0o777).toBe(0o600); + expect(yield* fs.readDirectory(dir)).toEqual(["config.jsonc"]); + }), + )); + + test("applies the requested mode exactly, whatever the umask", () => + runConfigEffect( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { filePath } = yield* targetIn(); + + yield* createCliConfigDocumentText(filePath, "{}\n", 0o666); + + expect((yield* fs.stat(filePath)).mode & 0o777).toBe(0o666); + }), + )); + + test("creates the file exclusively when the filesystem has no hard links", () => + runConfigEffect( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { dir, filePath } = yield* targetIn(); + const noLinks: FileSystem.FileSystem = { + ...fs, + link: (from) => + Effect.fail( + PlatformError.systemError({ + _tag: "Unknown", + module: "FileSystem", + method: "link", + pathOrDescriptor: from, + description: "operation not supported", + }), + ), + }; + const create = (content: string) => + createCliConfigDocumentText(filePath, content, 0o600).pipe( + Effect.provideService(FileSystem.FileSystem, noLinks), + ); + + expect(yield* create("{}\n")).toBe(true); + expect(yield* create('{ "second": true }\n')).toBe(false); + expect(yield* fs.readFileString(filePath)).toBe("{}\n"); + expect((yield* fs.stat(filePath)).mode & 0o777).toBe(0o600); + expect(yield* fs.readDirectory(dir)).toEqual(["config.jsonc"]); + }), + )); + + test("returns false and leaves an existing file untouched", () => + runConfigEffect( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { dir, filePath } = yield* targetIn(); + yield* fs.writeFileString(filePath, '{ "kept": true }\n'); + + const created = yield* createCliConfigDocumentText(filePath, "{}\n", 0o600); + + expect(created).toBe(false); + expect(yield* fs.readFileString(filePath)).toBe('{ "kept": true }\n'); + expect(yield* fs.readDirectory(dir)).toEqual(["config.jsonc"]); + }), + )); +}); + describe("writeCliConfigDocumentText", () => { function tempFileTargets() { return Effect.gen(function* () { @@ -3287,7 +3406,7 @@ describe("decodeCliConfigDocumentForValidationEffect", () => { expect(error).toMatchObject({ _tag: "CliConfigRemovedKeyError", removedKeys: [ - { key: "[inbucket]", replacement: "[local_smtp]" }, + { key: "inbucket", replacement: "local_smtp" }, { key: "remotes.staging.experimental.orioledb_version", replacement: "remotes.staging.db.orioledb_version", diff --git a/packages/config/src/project-config/registry.ts b/packages/config/src/project-config/registry.ts index 1c0a3aa3b2..5214855841 100644 --- a/packages/config/src/project-config/registry.ts +++ b/packages/config/src/project-config/registry.ts @@ -107,8 +107,8 @@ const apiSectionRows: ReadonlyArray = [ }, normalizeDocument: normalizeDocumentMaxRows, }, - // Unmapped (no config counterpart): api.db_pool, api.db_pool_acquisition_timeout, - // api.db_pool_max_lifetime, api.db_pool_max_idletime. + /* Unmapped: api.db_pool (`[api] db_pool` sizes only the local PostgREST pool), and the other + api.db_pool_* settings, which have no config counterpart. */ ]; /** Settings fields whose remote value is a signed int, clamped to uint. */ diff --git a/packages/config/src/removed-config-keys.ts b/packages/config/src/removed-config-keys.ts index 65fa008e79..004f2968ba 100644 --- a/packages/config/src/removed-config-keys.ts +++ b/packages/config/src/removed-config-keys.ts @@ -18,7 +18,7 @@ function scanScope( let stripped = scope; if (Object.hasOwn(scope, "inbucket")) { - removedKeys.push({ key: `[${prefix}inbucket]`, replacement: `[${prefix}local_smtp]` }); + removedKeys.push({ key: `${prefix}inbucket`, replacement: `${prefix}local_smtp` }); } const experimental = scope["experimental"]; @@ -41,8 +41,8 @@ function scanScope( for (const provider of REMOVED_EXTERNAL_PROVIDERS) { if (Object.hasOwn(external, provider)) { removedKeys.push({ - key: `[${prefix}auth.external.${provider}]`, - replacement: `[${prefix}auth.external.${provider}_oidc]`, + key: `${prefix}auth.external.${provider}`, + replacement: `${prefix}auth.external.${provider}_oidc`, }); } } diff --git a/packages/config/src/toml-scan.ts b/packages/config/src/toml-scan.ts new file mode 100644 index 0000000000..da66e2ed02 --- /dev/null +++ b/packages/config/src/toml-scan.ts @@ -0,0 +1,541 @@ +// Character-level TOML scanner. Produces top-level tokens in document order: blank lines, +// comments, table headers, and key-value lines (multi-line arrays/strings scanned as single +// opaque spans). Never throws — an unrecognized construct yields an `{ error }` result instead. + +export interface TomlHeaderToken { + readonly kind: "header"; + readonly start: number; + readonly end: number; + readonly path: ReadonlyArray; + readonly isArrayOfTables: boolean; + /** Offset of a same-line `#` after the closing bracket. */ + readonly commentStart?: number; +} + +interface TomlSpan { + readonly start: number; + readonly end: number; +} + +export interface TomlKeyToken { + readonly kind: "kv"; + readonly start: number; + readonly end: number; + /** Fully qualified: the enclosing table's path plus this key's own (possibly dotted) segments. */ + readonly path: ReadonlyArray; + readonly tableIndex: number; + readonly valueStart: number; + readonly valueEnd: number; + /** True when this key's OWN value is an inline table (`{ ... }`) — see `findInlineTableOnPath`. */ + readonly insideInlineTable: boolean; + /** Offset of a same-line `#` after the value. */ + readonly commentStart?: number; + /** Comments inside a multi-line array or inline-table value. */ + readonly valueComments: ReadonlyArray; +} + +interface TomlBlankToken { + readonly kind: "blank"; + readonly start: number; + readonly end: number; +} + +interface TomlCommentToken { + readonly kind: "comment"; + readonly start: number; + readonly end: number; +} + +export type TomlToken = TomlHeaderToken | TomlKeyToken | TomlBlankToken | TomlCommentToken; + +export interface TomlScanResult { + readonly source: string; + readonly tokens: ReadonlyArray; + readonly headers: ReadonlyArray; + readonly newline: "\n" | "\r\n"; + readonly endsWithNewline: boolean; +} + +export interface TomlScanError { + readonly error: string; + readonly offset: number; +} + +function charAt(source: string, pos: number): string { + const ch = source[pos]; + return ch ?? ""; +} + +export function skipInlineWhitespace(source: string, pos: number): number { + let cursor = pos; + while (cursor < source.length && (source[cursor] === " " || source[cursor] === "\t")) { + cursor++; + } + return cursor; +} + +function skipToEndOfLine(source: string, pos: number): number { + let cursor = pos; + while (cursor < source.length && source[cursor] !== "\n" && source[cursor] !== "\r") { + cursor++; + } + return cursor; +} + +function advancePastNewline(source: string, pos: number): number { + if (source[pos] === "\r" && source[pos + 1] === "\n") { + return pos + 2; + } + if (source[pos] === "\n" || source[pos] === "\r") { + return pos + 1; + } + return pos; +} + +function scanBasicString(source: string, pos: number): number | null { + let cursor = pos; + while (cursor < source.length) { + const ch = source[cursor]; + if (ch === "\\") { + cursor += 2; + continue; + } + if (ch === '"') { + return cursor + 1; + } + if (ch === "\n" || ch === "\r") { + return null; + } + cursor++; + } + return null; +} + +function scanLiteralString(source: string, pos: number): number | null { + let cursor = pos; + while (cursor < source.length) { + const ch = source[cursor]; + if (ch === "'") { + return cursor + 1; + } + if (ch === "\n" || ch === "\r") { + return null; + } + cursor++; + } + return null; +} + +function scanMultilineBasicString(source: string, pos: number): number | null { + let cursor = pos; + while (cursor < source.length) { + const ch = source[cursor]; + if (ch === "\\") { + cursor += 2; + continue; + } + if (ch === '"' && source.startsWith('"""', cursor)) { + cursor += 3; + let extra = 0; + while (extra < 2 && source[cursor] === '"') { + cursor++; + extra++; + } + return cursor; + } + cursor++; + } + return null; +} + +function scanMultilineLiteralString(source: string, pos: number): number | null { + let cursor = pos; + while (cursor < source.length) { + if (source[cursor] === "'" && source.startsWith("'''", cursor)) { + cursor += 3; + let extra = 0; + while (extra < 2 && source[cursor] === "'") { + cursor++; + extra++; + } + return cursor; + } + cursor++; + } + return null; +} + +function scanBareValue(source: string, pos: number): number { + let cursor = pos; + while (cursor < source.length) { + const ch = source[cursor]; + if (ch === "#" || ch === "\n" || ch === "\r") { + break; + } + cursor++; + } + // Trailing inline whitespace before a `#` comment (or EOL) belongs to the comment/line-ending, + // not the value: without this, replacing a value would fold that space into the replaced span + // and eat it. + while (cursor > pos && (source[cursor - 1] === " " || source[cursor - 1] === "\t")) { + cursor--; + } + return cursor; +} + +/** Scans a bracketed value (array or inline table), tracking nested strings/brackets so an + * unrelated `]`/`}`/`#` inside a string never terminates the scan early. `openChar`/`closeChar` + * select array (`[`/`]`) or inline-table (`{`/`}`) matching; a `#` outside a string starts a + * comment that is skipped and, when `comments` is given, recorded. */ +function scanBracketedValue( + source: string, + pos: number, + openChar: string, + closeChar: string, + comments?: Array, +): number | null { + let cursor = pos; + let depth = 1; + while (cursor < source.length) { + const ch = source[cursor]; + if (ch === '"') { + const next = source.startsWith('"""', cursor) + ? scanMultilineBasicString(source, cursor + 3) + : scanBasicString(source, cursor + 1); + if (next === null) { + return null; + } + cursor = next; + continue; + } + if (ch === "'") { + const next = source.startsWith("'''", cursor) + ? scanMultilineLiteralString(source, cursor + 3) + : scanLiteralString(source, cursor + 1); + if (next === null) { + return null; + } + cursor = next; + continue; + } + if (ch === "#") { + const commentEnd = skipToEndOfLine(source, cursor); + comments?.push({ start: cursor, end: commentEnd }); + cursor = advancePastNewline(source, commentEnd); + continue; + } + if (ch === openChar) { + depth++; + cursor++; + continue; + } + if (ch === closeChar) { + depth--; + cursor++; + if (depth === 0) { + return cursor; + } + continue; + } + cursor++; + } + return null; +} + +function scanValue(source: string, start: number, comments?: Array): number | null { + const ch = charAt(source, start); + if (ch === '"') { + return source.startsWith('"""', start) + ? scanMultilineBasicString(source, start + 3) + : scanBasicString(source, start + 1); + } + if (ch === "'") { + return source.startsWith("'''", start) + ? scanMultilineLiteralString(source, start + 3) + : scanLiteralString(source, start + 1); + } + if (ch === "[") { + return scanBracketedValue(source, start + 1, "[", "]", comments); + } + if (ch === "{") { + return scanBracketedValue(source, start + 1, "{", "}", comments); + } + if (ch === "") { + return null; + } + return scanBareValue(source, start); +} + +const BARE_KEY_CHAR = /^[A-Za-z0-9_-]$/; + +function hexCodePoint(raw: string, start: number, length: number): string | null { + const hex = raw.slice(start, start + length); + const value = Number.parseInt(hex, 16); + return new RegExp(`^[0-9A-Fa-f]{${length}}$`).test(hex) && + value <= 0x10ffff && + (value < 0xd800 || value > 0xdfff) + ? String.fromCodePoint(value) + : null; +} + +/** Decodes a basic-string key segment, or returns null when an escape is invalid TOML. */ +function unescapeBasicString(raw: string): string | null { + let result = ""; + for (let i = 0; i < raw.length; i++) { + const ch = raw[i]; + if (ch !== "\\") { + result += ch ?? ""; + continue; + } + const next = raw[i + 1]; + if (next === "\\" || next === '"') { + result += next; + i++; + } else if (next === "b") { + result += "\b"; + i++; + } else if (next === "f") { + result += "\f"; + i++; + } else if (next === "n") { + result += "\n"; + i++; + } else if (next === "r") { + result += "\r"; + i++; + } else if (next === "t") { + result += "\t"; + i++; + } else if (next === "e") { + result += "\u001b"; + i++; + } else if (next === "x" || next === "u" || next === "U") { + const length = next === "x" ? 2 : next === "u" ? 4 : 8; + const decoded = hexCodePoint(raw, i + 2, length); + if (decoded === null) { + return null; + } + result += decoded; + i += length + 1; + } else { + return null; + } + } + return result; +} + +interface DottedKeyScan { + readonly segments: ReadonlyArray; + readonly end: number; +} + +/** Parses one or more dot-separated key segments (bare, basic-quoted, or literal-quoted), + * used for both table headers (`[a."b.c"]`) and key-value lines (`a."b.c" = 1`). Stops as soon + * as no further `.`-continuation is found; the caller checks for the expected terminator + * (`]` or `=`) itself. */ +function scanDottedKeyPath(source: string, pos: number): DottedKeyScan | null { + const segments: Array = []; + let cursor = pos; + for (;;) { + cursor = skipInlineWhitespace(source, cursor); + const ch = charAt(source, cursor); + if (ch === '"') { + const strEnd = scanBasicString(source, cursor + 1); + if (strEnd === null) { + return null; + } + const segment = unescapeBasicString(source.slice(cursor + 1, strEnd - 1)); + if (segment === null) { + return null; + } + segments.push(segment); + cursor = strEnd; + } else if (ch === "'") { + const strEnd = scanLiteralString(source, cursor + 1); + if (strEnd === null) { + return null; + } + segments.push(source.slice(cursor + 1, strEnd - 1)); + cursor = strEnd; + } else if (BARE_KEY_CHAR.test(ch)) { + let bareEnd = cursor; + while (BARE_KEY_CHAR.test(charAt(source, bareEnd))) { + bareEnd++; + } + segments.push(source.slice(cursor, bareEnd)); + cursor = bareEnd; + } else { + return null; + } + const afterSegment = skipInlineWhitespace(source, cursor); + if (charAt(source, afterSegment) === ".") { + cursor = afterSegment + 1; + continue; + } + cursor = afterSegment; + break; + } + return { segments, end: cursor }; +} + +export function scanTomlDocument(source: string): TomlScanResult | TomlScanError { + const tokens: Array = []; + const headers: Array = []; + const length = source.length; + let pos = 0; + let currentTableIndex = -1; + let currentTablePath: ReadonlyArray = []; + + while (pos < length) { + const lineStart = pos; + const firstNonWhitespace = skipInlineWhitespace(source, pos); + const ch = charAt(source, firstNonWhitespace); + + if (ch === "" || ch === "\n" || ch === "\r") { + const end = advancePastNewline(source, firstNonWhitespace); + tokens.push({ kind: "blank", start: lineStart, end }); + pos = end === firstNonWhitespace ? length : end; + continue; + } + + if (ch === "#") { + const end = advancePastNewline(source, skipToEndOfLine(source, firstNonWhitespace)); + tokens.push({ kind: "comment", start: lineStart, end }); + pos = end; + continue; + } + + if (ch === "[") { + const isArrayOfTables = charAt(source, firstNonWhitespace + 1) === "["; + const keyStart = firstNonWhitespace + (isArrayOfTables ? 2 : 1); + const parsedPath = scanDottedKeyPath(source, keyStart); + if (parsedPath === null || parsedPath.segments.length === 0) { + return { error: "malformed table header", offset: lineStart }; + } + let closeCursor = parsedPath.end; + if (charAt(source, closeCursor) !== "]") { + return { error: "malformed table header", offset: lineStart }; + } + closeCursor += 1; + if (isArrayOfTables) { + if (charAt(source, closeCursor) !== "]") { + return { error: "malformed array-of-tables header", offset: lineStart }; + } + closeCursor += 1; + } + const afterHeader = skipInlineWhitespace(source, closeCursor); + const headerComment = charAt(source, afterHeader) === "#" ? afterHeader : undefined; + const end = advancePastNewline(source, skipToEndOfLine(source, closeCursor)); + const headerToken: TomlHeaderToken = { + kind: "header", + start: lineStart, + end, + path: parsedPath.segments, + isArrayOfTables, + ...(headerComment === undefined ? {} : { commentStart: headerComment }), + }; + headers.push(headerToken); + tokens.push(headerToken); + currentTableIndex = headers.length - 1; + currentTablePath = parsedPath.segments; + pos = end; + continue; + } + + const parsedKey = scanDottedKeyPath(source, firstNonWhitespace); + if (parsedKey === null || parsedKey.segments.length === 0) { + return { error: "malformed key-value line", offset: lineStart }; + } + const afterKey = skipInlineWhitespace(source, parsedKey.end); + if (charAt(source, afterKey) !== "=") { + return { error: "malformed key-value line", offset: lineStart }; + } + const valueStart = skipInlineWhitespace(source, afterKey + 1); + const valueComments: Array = []; + const valueEndRaw = scanValue(source, valueStart, valueComments); + if (valueEndRaw === null) { + return { error: "unterminated value", offset: valueStart }; + } + const afterValue = skipInlineWhitespace(source, valueEndRaw); + const valueComment = charAt(source, afterValue) === "#" ? afterValue : undefined; + const end = advancePastNewline(source, skipToEndOfLine(source, valueEndRaw)); + const fullPath = [...currentTablePath, ...parsedKey.segments]; + const rawValueText = source.slice(valueStart, valueEndRaw); + tokens.push({ + kind: "kv", + start: lineStart, + end, + path: fullPath, + tableIndex: currentTableIndex, + valueStart, + valueEnd: valueEndRaw, + insideInlineTable: rawValueText.startsWith("{"), + valueComments, + ...(valueComment === undefined ? {} : { commentStart: valueComment }), + }); + pos = end; + } + + const newline = source.includes("\r\n") ? "\r\n" : "\n"; + // A mixed-EOL file may be detected as CRLF overall (because some earlier line uses it) while + // its final line ends in a bare `\n`; checking for `"\n"` alone (rather than the detected + // flavor) covers both terminators, since a `"\r\n"`-ending string always also ends in `"\n"`. + return { source, tokens, headers, newline, endsWithNewline: source.endsWith("\n") }; +} + +export interface TomlArrayLayout { + readonly items: ReadonlyArray<{ + readonly leading: ReadonlyArray; + readonly trailing?: TomlSpan; + }>; + readonly tail: ReadonlyArray; +} + +/** Maps the comments of a scalar-only array to its elements: a comment on its own line leads the + * next element, one sharing a line with an element trails it, and any after the last element form the tail. */ +export function scanScalarArrayLayout( + source: string, + valueStart: number, + valueEnd: number, +): TomlArrayLayout | null { + const items: Array<{ leading: Array; trailing?: TomlSpan }> = []; + let pending: Array = []; + let sameLine = false; + let cursor = valueStart + 1; + const close = valueEnd - 1; + while (cursor < close) { + const ch = charAt(source, cursor); + if (ch === "\n" || ch === "\r") { + sameLine = false; + cursor++; + } else if (ch === " " || ch === "\t" || ch === ",") { + cursor++; + } else if (ch === "#") { + const end = skipToEndOfLine(source, cursor); + const last = items[items.length - 1]; + if (sameLine && last !== undefined) { + last.trailing = { start: cursor, end }; + } else { + pending.push({ start: cursor, end }); + } + cursor = end; + } else { + let end: number | null = cursor; + if (ch === '"' || ch === "'") { + end = scanValue(source, cursor); + } else { + while (end < close && !/[,#\s\]]/.test(charAt(source, end))) { + end++; + } + } + if (end === null) { + return null; + } + items.push({ leading: pending }); + pending = []; + sameLine = true; + cursor = end; + } + } + return { items, tail: pending }; +} diff --git a/packages/stack/ARCHITECTURE.md b/packages/stack/ARCHITECTURE.md index 84c9f08841..4054a81523 100644 --- a/packages/stack/ARCHITECTURE.md +++ b/packages/stack/ARCHITECTURE.md @@ -312,7 +312,7 @@ Validate composition references, input/output types and cycles when registering Composition start first assigns or reuses and binds every configured public listener of its selected members, including lazy members, and registers their routes. One worker per member then waits for its prerequisites' outcomes: a lazy member is armed (also after a prerequisite failed), and an eager member is started and awaited for readiness, or reported as blocked when a prerequisite failed. Prerequisites outside the configured members run as eager standalone instances. It does not select unrelated standalone instances. Successful start returns member observations with their public endpoints; credentials reads render usable connection strings from these assignments without starting lazy backends. A failed launch or readiness check makes the operation return an error with per-instance outcomes; a running but unhealthy instance remains running, and completed steps are not rolled back. -After binding the shared API listener, default composition setup uses the endpoint renderer to populate ordinary configuration values: Studio receives `apiUrl` and `publicApiUrl`, Auth receives `externalApiUrl`, plus `templateBaseUrl` beside a generated `templateToken` when it has templates, and Functions receives `apiUrl`. When the database has a configured SQL endpoint, Functions also receives its rendered `databaseUrl`; this saved value is refreshed when callers recompose the composition, and does not create a database readiness dependency for Function execution. These values are saved in each instance's configuration; individual starts and normal host reopening consume that configuration. This is concrete default setup code, not declarative input wiring or a public listener-binding API. The endpoint renderer owns the host/runtime reachability rules; custom configurations supply plain URLs through the same inputs. URL values do not imply graph edges. +After binding the shared API listener, default composition setup uses the endpoint renderer to populate ordinary configuration values: Studio receives `apiUrl` and `publicApiUrl`, Auth receives `externalApiUrl`, plus `templateBaseUrl` beside a generated `templateToken` when it has templates, and Functions receives `apiUrl`. When the database has a configured SQL endpoint, Functions also receives its rendered `functionsDatabaseUrl` (the `postgres` role) as `databaseUrl`; this saved value is refreshed when callers recompose the composition, and does not create a database readiness dependency for Function execution. These values are saved in each instance's configuration; individual starts and normal host reopening consume that configuration. This is concrete default setup code, not declarative input wiring or a public listener-binding API. The endpoint renderer owns the host/runtime reachability rules; custom configurations supply plain URLs through the same inputs. URL values do not imply graph edges. Composition restart is two passes: stop the selected instances in reverse dependency order, then perform composition start. If the stop pass fails, report partial results without beginning the start pass. Cancelling composition withdraws its waits; admitted executions continue in the owner scope, and launched instances remain until an explicit stop or owner close. Explicit empty selection is a no-op; there is no generic rollback engine. @@ -606,6 +606,15 @@ The shared allocator manages physical public listeners. A service definition dec A shared listener is a networking resource, not a capability or service group. Composition maps each route to an individual instance ID. Traffic is attributed to the matched route's instance for wake and idle decisions; there is no aggregate service lifecycle. A file route, like Auth's `/email`, is answered by the owner process with no wake or activity; it reads its file on every request, only while the path resolves inside its root, through a no-follow handle that must still name the resolved file. +With API TLS the shared listener keeps its bind and port and reads each connection's first byte: + +- A TLS ClientHello is served HTTPS for every peer, and plain HTTP only from loopback (`127.0.0.0/8` or `::1`): processes on this host, any user's, and containers on runtimes that forward their traffic from loopback. Every other peer is closed before any HTTP byte. +- A stack start that saves a different pair while the listener is open reopens it on its port (an unchanged pair keeps it), and when the new listener can't bind the previous TLS is saved again before any shared bind can open the listener, it opens again with that TLS, and the start fails (if that bind fails too, or the previous TLS can't be saved, the next start or shared bind opens it with its routes and the saved TLS). +- Each connection gets the plain listener's clocks: no request headers within 12 s (a TLS handshake included), no complete request within 300 s of its headers (upgrades have none), or 75 s idle after a response closes it; unlike that listener, a connection that read bytes since its last request gets 12 s more once, so a request that started before idle ran out can finish. +- Plain requests must name a stack host alias, `localhost` or an IP literal with the API port in `Host` (the port is optional on port 80), else 421, upgrades included. File routes answer only plain HTTP. `X-Forwarded-Proto` follows each connection. +- Host addresses of the shared endpoint carry `scheme: "https"`; runtime addresses stay plain. +- While the listener serves TLS on an engine, every stack start or restart, and every instance start or restart while the database runs, ends with the database container sending one plain `GET /__api_tls_check`; the listener answers with the body the owner armed (this stack's id and a fresh nonce). Any other outcome, including a plain connection closed without a reply on runtimes that don't forward containers from loopback, stops the stack and fails the operation. Compose, starts and restarts hold the owner's lifecycle permit with their checks; the check admits nothing. + | Address | Purpose | Lifetime | | ------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | Public | Stable endpoint exposed through a dedicated listener or shared route | Assignment survives stop/start until its owner is destroyed or explicitly reconfigured | diff --git a/packages/stack/README.md b/packages/stack/README.md index 076b6b8bcc..40e9a6339e 100644 --- a/packages/stack/README.md +++ b/packages/stack/README.md @@ -171,11 +171,11 @@ const services = await stack.composition.supabase([ await stack.composition.start(); ``` -The factory accepts one instance of each selected recipe, binds its configured public endpoints, and wires managed inputs such as REST's database URL. When the database SQL endpoint is configured, Functions receives the saved database URL as an ordinary input too; recompose the composition after rotating database credentials to refresh that value. This binding does not make Functions wait for database readiness. Database is eager; Studio is lazy with a 5-minute idle timeout; other public services, Functions included, are lazy with a 60-second idle timeout. Services without public endpoints are eager. Pass `{ eager: true }` to start every member eagerly. A managed URL binding requires its producer's endpoint to be configured. The factory also supplies ordinary host/runtime API URLs to Auth, Studio, and Functions without adding dependencies from those URLs. It rejects an already configured composition. +The factory accepts one instance of each selected recipe, binds its configured public endpoints, and wires managed inputs such as REST's database URL. When the database SQL endpoint is configured, Functions receives the database's `postgres`-role URL as an ordinary input too; recompose the composition after rotating database credentials to refresh that value. This binding does not make Functions wait for database readiness. Database is eager; Studio is lazy with a 5-minute idle timeout; other public services, Functions included, are lazy with a 60-second idle timeout. Services without public endpoints are eager. Pass `{ eager: true }` to start every member eagerly. A managed URL binding requires its producer's endpoint to be configured. The factory also supplies ordinary host/runtime API URLs to Auth, Studio, and Functions without adding dependencies from those URLs. It rejects an already configured composition. Inputs that the composition binds or the owner fills from the stack credentials, such as REST's `databaseUrl` or a JWT secret, are optional in creation configuration. Starting or restarting an instance without a required input that was neither bound nor provided fails before any lifecycle change with a `ServiceError` whose `operation` is `"input"` and whose message names the input; a running instance keeps running. -To recompose a stopped stack, pass the IDs to keep in `reuseIds`. `composition.plan(services)` compares requested creations with every saved instance of the same kinds without contacting the owner or changing state. Each entry reports its instance `id`, `service`, whether it is a composition `member`, and a `change`: `unchanged`, `changed` with the differing config `paths`, or `incompatible` with the `paths` of an endpoint or PostgreSQL release-line change that the saved instance cannot adopt. Inputs that the composition or the stack credentials supply are ignored, an automatic API port is compared as the shared fixed port the composition would assign; a pin change on any other service is a `changed` configuration. Recomposing with `reuseIds` replaces a `changed` instance's configuration while keeping its identity, data, and ports. Add `retainMembers: true` to rebind only the requested services, which must not expose an API endpoint, and leave the other saved members and their dependencies in place. The database accepts a changed pin on initialized data only as a new slim-services revision of the build that created it. Auth, Storage, Realtime, Analytics and the pooler refuse a pin whose upstream version is older than the newest one that already migrated the database, which the database instance records in `schema-writers.json`; the error names the stack to destroy. Other services accept any pin change. +To recompose a stopped stack, pass the IDs to keep in `reuseIds`. `composition.plan(services)` compares requested creations with every saved instance of the same kinds without contacting the owner or changing state. Each entry reports its instance `id`, `service`, whether it is a composition `member`, and a `change`: `unchanged`, `changed` with the differing config `paths`, or `incompatible` with the `paths` of an endpoint or PostgreSQL release-line change that the saved instance cannot adopt. Inputs that the composition or the stack credentials supply are ignored, an automatic API port is compared as the shared fixed port the composition would assign; a pin change on any other service is a `changed` configuration. Recomposing with `reuseIds` replaces a `changed` instance's configuration while keeping its identity, data, and ports. Add `retainMembers: true` to rebind only the requested services, which must not expose an API endpoint, and leave the other saved members and their dependencies in place. Pass `apiTls: { cert, key }`, a PEM pair whose certificate covers `127.0.0.1`, to save it with the stack and serve the shared API port over HTTPS, with plain HTTP only from loopback; starts that serve it fail on engines whose containers don't reach this host from loopback; a composition without it and without `retainMembers` clears the saved pair, and while a pair is served the shared API endpoint's host addresses carry `scheme: "https"`. The database accepts a changed pin on initialized data only as a new slim-services revision of the build that created it. Auth, Storage, Realtime, Analytics and the pooler refuse a pin whose upstream version is older than the newest one that already migrated the database, which the database instance records in `schema-writers.json`; the error names the stack to destroy. Other services accept any pin change. The whole-stack E2E suite covers the default lazy lifecycle and reopen, all-eager startup, idle and wake, and parallel stack isolation for native, Docker, and Podman runtimes, split into a `lifecycle` and an `idle-parallel` file per runtime. The Podman files need `SUPABASE_STACK_TEST_ENGINE=podman`; CI runs them, and the container integration suite, on the Linux runner image's rootless Podman. macOS `podman machine` is not covered by CI. Run one runtime with a filter such as `pnpm --filter @supabase/stack test:e2e:run src/whole-stack.native` (matches both native files) or target one file, for example `src/whole-stack.docker.idle-parallel.e2e.test.ts`. diff --git a/packages/stack/src/Artifacts.ts b/packages/stack/src/Artifacts.ts index a0034c74d1..2a7d0f9356 100644 --- a/packages/stack/src/Artifacts.ts +++ b/packages/stack/src/Artifacts.ts @@ -127,23 +127,23 @@ const definitions: Readonly> = { database: definition( "postgres", { - upstreamVersion: "17.11.0.018", + upstreamVersion: "17.11.0.019", revision: 0, image: - "ghcr.io/supabase/cli/postgres:17.11.0.018-r0@sha256:4f5cf9d03718b200df8c8e4735081eaa55a74d11dca848f5c8283203921e5751", - upstreamImage: "supabase/postgres:17.11.0.018", + "ghcr.io/supabase/cli/postgres:17.11.0.019-r0@sha256:b154311f02fee93dc5c9b248483b2c4d34b5d53d9cb7bb69e1af34cb650556de", + upstreamImage: "supabase/postgres:17.11.0.019", natives: { "darwin-arm64": { - archive: "5033846ff2dc56a992e9bf929d62d132bd2819656e040d4a359632121a9722e7", - manifest: "9e6d77b467111e6b6dd822ebf5b100214ca5837b563556e97227b93332ae87ce", + archive: "a2627baa652b2aa0dbaef75ff958b470007b032a11e388bd6fe97c3a28f4ab4d", + manifest: "bcdc61b185a969fa9c92bf74b30895ef74ee44596ee94e4f4a5e453c0e0f1572", }, "linux-amd64": { - archive: "80c80a56481e65491eaafe1609eedafe0b35ee2ff10773adfb9ab34e5ebfa8c5", - manifest: "56c4b951f5dd16870fca927e221c2c289d23bd42514027594fab13ede672d9b1", + archive: "04b5033d5bea6370732bd909387a180ec9b9ed263f59f34c82a5cd06dd131585", + manifest: "4009a9870eaf36c04d9bd90391e4efdeafddea919f64b9596429de99f56b09de", }, "linux-arm64": { - archive: "e066fcea166bf302ba24779d32ff22150905860fe7fb067c415cff7efe7e5f3e", - manifest: "42883bbb35d4f165706eabc4bf66002636eb500ea1ff55915c539e970f768339", + archive: "821bc779666c569dab9d95b93175d359e4945978487e7e5d1401e02fd02f3a2e", + manifest: "bb831068bb6874a9c8b0ddae5c3d6623cdcf8dca58aed67c7dd46712e5baf4aa", }, }, }, @@ -157,24 +157,24 @@ const definitions: Readonly> = { "bin/psql", ], { - "15.19.0.018": { - upstreamVersion: "15.19.0.018", + "15.19.0.019": { + upstreamVersion: "15.19.0.019", revision: 0, image: - "ghcr.io/supabase/cli/postgres:15.19.0.018-r0@sha256:b0b4057a43543546d54d74434b562721af4bf9a7802b53a00158dcec7059bb4b", - upstreamImage: "supabase/postgres:15.19.0.018", + "ghcr.io/supabase/cli/postgres:15.19.0.019-r0@sha256:92bbdc7be216bd75cc5b9a26701353a95f0204b622f4a8b9f91f48099cc9f733", + upstreamImage: "supabase/postgres:15.19.0.019", natives: { "darwin-arm64": { - archive: "682bd39c23b0ef677e652f641f74862aa61b9a5472f51e29f5163b09876f6da4", - manifest: "27ad0dffd559ed1dc5e84ed368890dc1089d135d34a5591ce7b7640f5cf76aa6", + archive: "351d35b7f7181a461235fbf7915481b4b4e57c5a223b72492d916746b3c11027", + manifest: "abb7e97783612366a36a37bb0cc72b9c34d61825ab3f690fb78fcb1da2ca6cb4", }, "linux-amd64": { - archive: "3191c152650e7284d4168e71ab91f45e31fb690153c58d8f2a425e03ea86b4e1", - manifest: "0301008324b5df8c885066105dd59f4faf41974be54bec7a285b7d6dcc71a535", + archive: "0615748e875cf54c7ebb33c9a235b891b22c2da34aaef99c7a0aea809159f0fc", + manifest: "abafbed356fa0417993a935ffb443759805679dda76707d712227471221a35d1", }, "linux-arm64": { - archive: "21f3d647d844e19aa656802438992597f177d1b60545662e7244d6eb0be01248", - manifest: "04baea44897bd198c161460e0ae46bd304a349b0d8baf8885e158ec49aee8448", + archive: "c70947e46e8dd28e32e5ad2d22e12af60aa4bfb6f1fa656db37db512915f4206", + manifest: "627910697b183143810399511aa22522c329aaf5179135b3b0470e5a7614c1d2", }, }, }, @@ -409,6 +409,27 @@ const definitions: Readonly> = { }, }, }, + "17.11.0.019-orioledb": { + upstreamVersion: "17.11.0.019-orioledb", + revision: 0, + image: + "ghcr.io/supabase/cli/postgres:17.11.0.019-orioledb-r0@sha256:5911e8f3d001153046fd0177ebeabcf9772b1a4d5478f8bfd9bc6e1a4bd64b62", + upstreamImage: "supabase/postgres:17.11.0.019-orioledb", + natives: { + "darwin-arm64": { + archive: "0e9635a6a41fede0f55cb938064d97321f0be722a910ee3637b9e55d4cb97515", + manifest: "5bf57accc77cb26f64994b528cc35abb2e641f48e55508c0d7db6e7abeebb5d7", + }, + "linux-amd64": { + archive: "11d04a2e30b660eadda15215be05647551ab93830fc40f03b897b8e12561d0ca", + manifest: "726235ccb391875b784f6848a3867da3a4aceb242e463449012942c4ffcfe550", + }, + "linux-arm64": { + archive: "507164e13269da078fa51cac6050780989a5db11f4ffd0bc2e901f59cc2ab2fb", + manifest: "f37fa08776d655e21fc783db8f90c46ce5ff99a896d49cf3c9df6acacc7eae2c", + }, + }, + }, }, ), rest: definition( @@ -464,23 +485,23 @@ const definitions: Readonly> = { realtime: definition( "realtime", { - upstreamVersion: "v2.154.0", + upstreamVersion: "v2.160.0", revision: 0, image: - "ghcr.io/supabase/cli/realtime:v2.154.0-r0@sha256:e6b4e8032dcb0a83f355a860b061aa9b3a189f23d4e62ac9ae1f8cd5494ac54d", - upstreamImage: "supabase/realtime:v2.154.0", + "ghcr.io/supabase/cli/realtime:v2.160.0-r0@sha256:80714d498a63ea98030b67cf09a15b8971dcb56b511bd8b81fc850af3ac8ba7d", + upstreamImage: "supabase/realtime:v2.160.0", natives: { "darwin-arm64": { - archive: "15b041e0b8ade0d7cc7b195024930cf83d820f0a2118f18ffd3a9f6870eee143", - manifest: "761582da816b0c4f4fa4f77affcf194c3aff80d108d5be7783a06f8c0b26935d", + archive: "e8ab5081ca17f55e54474c2907a54c9a33b1454299e3a09b7383b24276465510", + manifest: "358edb201274c68d7f3346f44a0fca9cd68aa1efc1e8797e1561797ff5f5243e", }, "linux-amd64": { - archive: "c70aed4bee8f0f2b4feea163b4ad410cfe029de957524b4122ec7d22077e8721", - manifest: "a22e690d7004d44d72860c097b5e863202946dd2f48148c2e635c8125a7d9b75", + archive: "f4c76db95039c263939fe26df4640f210b19088cb8ff540a3aef3124b5c366c5", + manifest: "8c05e10ea4abe0dfd59bc3c8f13913b4b59001fa1ef24b02f398438c55ad6f98", }, "linux-arm64": { - archive: "1c3d9f67fc8229d5fe8cf98f42f2a6038d31063bb68815ac16a1d46defb186fa", - manifest: "81b9b25e10f26e15b3c3da51f9660848e47e6735205285fc2c8f7b68df7a0145", + archive: "3a0ae9ecf06958bf6bfa6c7ae9d34a691479b3d435813b85aac1b9991bf3c4cb", + manifest: "06d7a2c527f13298473cb0d3992b67ef2b0c2fe5df0aeac318d2283146f90d8f", }, }, }, @@ -490,23 +511,23 @@ const definitions: Readonly> = { storage: definition( "storage", { - upstreamVersion: "v1.90.1", + upstreamVersion: "v1.94.2", revision: 0, image: - "ghcr.io/supabase/cli/storage:v1.90.1-r0@sha256:21cffda72ebee5b43ee08f4f3add0f2b884cf751edca82759d7f81f69dffd9aa", - upstreamImage: "supabase/storage-api:v1.90.1", + "ghcr.io/supabase/cli/storage:v1.94.2-r0@sha256:98be14f7c9a1827b2b951a3005c37642a7d5139818e9df3e7bebc932578594dc", + upstreamImage: "supabase/storage-api:v1.94.2", natives: { "darwin-arm64": { - archive: "f9954fb4cea6bbb93dec7f5dd6064ae8acfeb5642a0eb5f64d0cf40866cff7f2", - manifest: "7c9ca7e1f6114d164215073ea70c89ace3f0e638c5a08644adecc10ff80560bc", + archive: "b2e004473f1af6b3cf23ecd31b9af262bab32a5a18c4959d1e5014dd1661f5b0", + manifest: "b09bdd2e731029c78ce591cba81f3c5e25d09a915e22ec493dff9c98c3062050", }, "linux-amd64": { - archive: "ea1d86e68d1c71a6f715b21093577ea40e51f8547b0ddac20077c3dc31adf56e", - manifest: "79f017444d2754525c1ac9b31c4705119007696841926616672a9792f5274490", + archive: "cb1b506282118b12ef1ae6ed450037408db9fb8f99dc89f9062b43ac7c2ddb0e", + manifest: "054bd98e6f08a64fdb85b555ef786f3ffe6f32d61757c6ef480ca3f3bf0395b2", }, "linux-arm64": { - archive: "c9376533b4e1c35e636011c0ffe222852c51b76aa61842037f9019fd6f91d291", - manifest: "ad1f68a3bf9004d1fd87fe383864d0bb52ad018a7f60e4953efff54f626b1096", + archive: "dceb698ef576ca4d0e1f5eda2d6a784851265a8c745c3879d3c8b245ca3b0790", + manifest: "b6f64cd3062a2d516c4f0edbe24788a6aa5d2c23fa7e66222474aca36bdb7ac2", }, }, }, diff --git a/packages/stack/src/HttpProxy.integration.test.ts b/packages/stack/src/HttpProxy.integration.test.ts index 69f2cb30d0..e9d87c54e5 100644 --- a/packages/stack/src/HttpProxy.integration.test.ts +++ b/packages/stack/src/HttpProxy.integration.test.ts @@ -1,14 +1,18 @@ import { NodeHttpClient, NodeServices } from "@effect/platform-node"; import { expect, it } from "@effect/vitest"; -import { Data, Deferred, Effect, Fiber, Layer, Queue } from "effect"; +import { Data, Deferred, Effect, Fiber, FileSystem, Layer, Path, Queue, Ref } from "effect"; +import { TestClock } from "effect/testing"; import { HttpClient, HttpClientRequest } from "effect/http"; import { createServer, type Server, type ServerResponse } from "node:http"; // oxlint-disable-line effecttsgo/node-builtin-import -- raw server fixture. import { createServer as createTcpServer, Socket, type Server as NetServer } from "node:net"; // oxlint-disable-line effecttsgo/node-builtin-import -- raw disconnect fixture. +import { generateKeyPairSync, randomUUID } from "node:crypto"; +import { connect as tlsConnect } from "node:tls"; // oxlint-disable-next-line effecttsgo/node-builtin-import -- raw WebSocket upgrade fixture. import { WebSocket, WebSocketServer } from "ws"; import { captureLogs } from "../tests/logs.ts"; import { ProxyError } from "./Proxy.ts"; -import { makeHttpProxy, type HttpAccess, type HttpRoute } from "./HttpProxy.ts"; +import { API_TLS_CHECK_PATH, makeHttpProxy, type HttpAccess, type HttpRoute } from "./HttpProxy.ts"; +import { externalAddress, onCi, runCommand } from "../tests/api-tls.ts"; import { sharedRoutes } from "./host/Endpoints.ts"; const listen = (server: Server | NetServer, options?: { readonly beforeClose?: () => void }) => @@ -2067,3 +2071,708 @@ it.live("records and releases a request whose client resets after the full body }), ).pipe(Effect.provide(NodeServices.layer)), ); + +const testPair = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const certs = path.join(import.meta.dirname, "..", "tests", "certs"); + return { + cert: yield* fs.readFileString(path.join(certs, "trusted.crt")), + key: yield* fs.readFileString(path.join(certs, "localhost.key")), + }; +}); + +/* Writes `head` over plain TCP or TLS to the proxy at `host` and answers with every byte it sent + back. */ +const exchange = (port: number, head: string, ca?: string, host = "127.0.0.1") => + Effect.callback((resume) => { + let text = ""; + const socket = + ca === undefined + ? new Socket().connect(port, host, () => socket.write(head)) + : tlsConnect({ host, port, ca, servername: "localhost" }, () => socket.write(head)); + socket.on("data", (chunk: Buffer) => { + text += chunk.toString("latin1"); + }); + socket.once("close", () => resume(Effect.succeed(text))); + socket.once("error", () => resume(Effect.succeed(text))); + return Effect.sync(() => socket.destroy()); + }); + +it.live("serves TLS to every peer and plain HTTP on the same port only from loopback", () => + Effect.scoped( + Effect.gen(function* () { + const { cert, key } = yield* testPair; + const lan = yield* externalAddress; + const backend = yield* listen( + createServer((incoming, outgoing) => + outgoing.end( + `proto=${headerOf(incoming.headers["x-forwarded-proto"])} port=${headerOf(incoming.headers["x-forwarded-port"])}`, + ), + ), + ); + const proxy = yield* makeHttpProxy({ host: "0.0.0.0", port: 0, tls: { cert, key } }); + yield* proxy.setRoutes([ + { id: "api", prefix: "/api", gateway: true, target: Effect.succeed(backend) }, + { + id: "file", + prefix: "/email", + file: () => Effect.succeed(new TextEncoder().encode("file marker")), + }, + ]); + const at = (host: string, target = "/x", ...lines: Array) => + [`GET ${target} HTTP/1.1`, `Host: ${host}`, ...lines, "Connection: close", "", ""].join( + "\r\n", + ); + const local = `127.0.0.1:${proxy.port}`; + + expect(yield* exchange(proxy.port, at(local), cert)).toMatch(/^HTTP\/1\.1 404 /u); + expect(yield* exchange(proxy.port, at(local, "/api"), cert)).toMatch( + new RegExp(`proto=https port=${proxy.port}$`, "u"), + ); + expect(yield* exchange(proxy.port, at("evil.example", "/api"), cert)).toMatch( + new RegExp(`proto=https port=${proxy.port}$`, "u"), + ); + expect(yield* exchange(proxy.port, at(local, "/api"))).toMatch( + new RegExp(`proto=http port=${proxy.port}$`, "u"), + ); + /* A peer on this host's LAN address gets no plain byte, but TLS from the same address. */ + expect(yield* exchange(proxy.port, at(local, "/api"), undefined, lan)).toBe(""); + expect(yield* exchange(proxy.port, at(local, "/api"), cert, lan)).toMatch( + new RegExp(`proto=https port=${proxy.port}$`, "u"), + ); + /* `pg_net` SQL may name the bridge gateway or this host by IP. */ + expect(yield* exchange(proxy.port, at(`172.17.0.1:${proxy.port}`, "/api"))).toMatch( + new RegExp(`proto=http port=${proxy.port}$`, "u"), + ); + const browser = ["Origin: http://evil.example", "Sec-Fetch-Site: cross-site"]; + expect(yield* exchange(proxy.port, at(local, "/api", ...browser))).toMatch( + new RegExp(`proto=http port=${proxy.port}$`, "u"), + ); + expect(yield* exchange(proxy.port, at(local, "/email/invite"))).toContain("file marker"); + const overTls = yield* exchange(proxy.port, at(local, "/email/invite"), cert); + expect(overTls).toMatch(/^HTTP\/1\.1 404 /u); + expect(overTls).not.toContain("file marker"); + for (const head of [ + at(`evil.example:${proxy.port}`, "/api"), + at("127.0.0.1", "/api"), + at(`localhost:${proxy.port + 1}`, "/api"), + at(`evil.example:${proxy.port}`, "/api", "Upgrade: websocket", "Connection: Upgrade"), + ]) + expect(yield* exchange(proxy.port, head), head).toMatch(/^HTTP\/1\.1 421 /u); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +class RoutedPeerError extends Data.TaggedError("RoutedPeerError")<{ readonly message: string }> {} + +/* docker0's IPv4, when sudo works without a password, curl is installed and docker0 holds a /16 + or wider IPv4 network to carve a /24 from. */ +const routedPrerequisites = Effect.gen(function* () { + const sudo = yield* runCommand("sudo", ["-n", "true"]); + const curl = yield* runCommand("curl", ["--version"]); + const address = yield* runCommand("ip", ["-4", "-o", "addr", "show", "docker0"]); + const [, gateway, prefix] = /\binet (\d+\.\d+\.\d+\.\d+)\/(\d+)/u.exec(address.stdout) ?? []; + if (sudo.code !== 0 || curl.code !== 0 || gateway === undefined || Number(prefix) > 16) + return undefined; + return gateway; +}).pipe(Effect.orElseSucceed(() => undefined)); + +const routedGateway = + process.platform === "linux" + ? await Effect.runPromise(routedPrerequisites.pipe(Effect.provide(NodeServices.layer))) + : undefined; +const ci = Effect.runSync(onCi); + +/* A network namespace whose veth peer holds `..5/24` inside docker0's network, `` taken + from its id, routed to this host by a narrower /24 on `..1`. Its exact netns and links + are removed when the scope closes, and the close fails when any is left. `exec` runs a command + inside it as root. */ +const routedNamespace = (gateway: string) => + Effect.gen(function* () { + const id = randomUUID().slice(0, 8); + const namespace = `sbt-${id}`; + const hostSide = `sbh${id}`; + const peerSide = `sbp${id}`; + const [first, second] = gateway.split("."); + const subnet = `${first}.${second}.${100 + (Number.parseInt(id.slice(0, 2), 16) % 150)}`; + const inside = ["ip", "netns", "exec", namespace]; + const steps = [ + ["ip", "netns", "add", namespace], + ["ip", "link", "add", hostSide, "type", "veth", "peer", "name", peerSide], + ["ip", "link", "set", peerSide, "netns", namespace], + ["ip", "addr", "add", `${subnet}.1/24`, "dev", hostSide], + ["ip", "link", "set", hostSide, "up"], + [...inside, "ip", "addr", "add", `${subnet}.5/24`, "dev", peerSide], + [...inside, "ip", "link", "set", peerSide, "up"], + [...inside, "ip", "link", "set", "lo", "up"], + [...inside, "ip", "route", "add", "default", "via", `${subnet}.1`], + ]; + yield* Effect.addFinalizer(() => + Effect.gen(function* () { + yield* runCommand("sudo", ["-n", "ip", "netns", "del", namespace]); + yield* runCommand("sudo", ["-n", "ip", "link", "del", hostSide]); + const namespaces = yield* runCommand("ip", ["netns", "list"]); + const link = yield* runCommand("ip", ["link", "show", hostSide]); + if (namespaces.stdout.split("\n").some((line) => line.split(" ")[0] === namespace)) + return yield* Effect.die(`the routed-peer test left netns ${namespace}`); + if (link.code === 0) return yield* Effect.die(`the routed-peer test left link ${hostSide}`); + }).pipe(Effect.orDie), + ); + yield* Effect.forEach(steps, (step) => + runCommand("sudo", ["-n", ...step]).pipe( + Effect.filterOrFail( + ({ code }) => code === 0, + ({ stderr }) => new RoutedPeerError({ message: `${step.join(" ")} failed: ${stderr}` }), + ), + ), + ); + return { + exec: (args: ReadonlyArray) => runCommand("sudo", ["-n", ...inside, ...args]), + }; + }); + +/* A routed peer: an address inside docker0's network that this host reaches through + a narrower route, as a VPN or second bridge would, is not loopback however it is routed. */ +it.live.skipIf(process.platform !== "linux" || (routedGateway === undefined && !ci))( + "gives a routed peer inside the bridge network no plain byte, but TLS", + () => + Effect.scoped( + Effect.gen(function* () { + if (routedGateway === undefined) + return yield* Effect.die( + "the routed-peer test needs `sudo -n`, curl and a /16 or wider docker0 IPv4 on Linux CI", + ); + const proxy = yield* makeHttpProxy({ host: "0.0.0.0", port: 0, tls: yield* testPair }); + const namespace = yield* routedNamespace(routedGateway); + const plain = yield* namespace.exec([ + "bash", + "-c", + `exec 3<>/dev/tcp/${routedGateway}/${proxy.port} && printf 'GET /x HTTP/1.0\\r\\nHost: 127.0.0.1:${proxy.port}\\r\\n\\r\\n' >&3 && { IFS= read -r -d '' -t 5 reply <&3; printf '%s %s' "$?" "$reply"; }`, + ]); + /* Connected and asked, then closed with nothing read. */ + expect(plain.stdout, plain.stderr).toMatch(/^\d+ $/u); + const secure = yield* namespace.exec([ + "curl", + "-sk", + "--max-time", + "10", + "-o", + "/dev/null", + "-w", + "%{http_code}", + `https://${routedGateway}:${proxy.port}/x`, + ]); + expect(secure.stdout, secure.stderr).toBe("404"); + /* The same listener still serves loopback in plain. */ + expect( + yield* exchange(proxy.port, `GET /x HTTP/1.0\r\nHost: 127.0.0.1:${proxy.port}\r\n\r\n`), + ).toMatch(/^HTTP\/1\.1 404 /u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + 30_000, +); + +it.live( + "answers the readiness route in plain with the armed body, and leaves it to routing otherwise", + () => + Effect.scoped( + Effect.gen(function* () { + const { cert, key } = yield* testPair; + let routed = 0; + const backend = yield* listen( + createServer((_incoming, outgoing) => { + routed += 1; + outgoing.end("routed"); + }), + ); + const armed = yield* Ref.make(undefined); + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: { cert, key, check: Ref.get(armed) }, + }); + yield* proxy.setRoutes([ + { id: "api", prefix: "/", gateway: true, target: Effect.succeed(backend) }, + ]); + const local = `127.0.0.1:${proxy.port}`; + const probe = (method = "GET", host = local) => + `${method} ${API_TLS_CHECK_PATH} HTTP/1.1\r\nHost: ${host}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n`; + const routedTo = (reply: string) => + reply.startsWith("HTTP/1.1 200 ") && reply.endsWith("routed"); + + expect(routedTo(yield* exchange(proxy.port, probe()))).toBe(true); + expect(routed).toBe(1); + yield* Ref.set(armed, "supabase-stack s1 n1"); + const reply = yield* exchange(proxy.port, probe()); + const [head = "", body] = reply.split("\r\n\r\n"); + expect(head).toMatch(/^HTTP\/1\.1 200 /u); + const headers = head.toLowerCase().split("\r\n"); + expect(headers).toContain("content-type: text/plain; charset=utf-8"); + expect(headers).toContain("x-content-type-options: nosniff"); + expect(headers).toContain("cache-control: no-store"); + expect(body).toBe("supabase-stack s1 n1"); + expect(routed).toBe(1); + /* Over TLS and for any other method, the path is the gateway's like any other. */ + expect(routedTo(yield* exchange(proxy.port, probe(), cert))).toBe(true); + expect(routedTo(yield* exchange(proxy.port, probe("POST")))).toBe(true); + expect(routed).toBe(3); + expect(yield* exchange(proxy.port, probe("GET", `evil.example:${proxy.port}`))).toMatch( + /^HTTP\/1\.1 421 /u, + ); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +/* A raw connection, over TLS with `ca`, that sends `head`, collecting what comes back until the + proxy closes it. */ +const held = (port: number, head: string | Buffer, ca?: string) => + Effect.acquireRelease( + Effect.sync(() => { + const send = () => { + if (head.length > 0) socket.write(head); + }; + const socket = + ca === undefined + ? new Socket().connect(port, "127.0.0.1", send) + : tlsConnect({ host: "127.0.0.1", port, ca, servername: "localhost" }, send); + const received = { text: "" }; + socket.on("data", (chunk: Buffer) => { + received.text += chunk.toString("latin1"); + }); + socket.on("error", () => socket.destroy()); + return { socket, received }; + }), + ({ socket }) => Effect.sync(() => socket.destroy()), + ); + +const closed = (socket: Socket) => + Effect.callback((resume) => { + if (socket.destroyed) return resume(Effect.void); + const onClose = () => resume(Effect.void); + socket.once("close", onClose); + return Effect.sync(() => socket.off("close", onClose)); + }); + +/* Resolves once `received` holds `count` replies ending in `body`. */ +const replies = ( + connection: Effect.Success>, + body: string, + count: number, +) => + Effect.callback((resume) => { + const check = () => { + if (connection.received.text.split(body).length - 1 >= count) + resume(Effect.succeed(connection.received.text)); + }; + connection.socket.on("data", check); + check(); + return Effect.sync(() => connection.socket.off("data", check)); + }); + +it.live( + "closes a TLS port's silent, stalled and idle connections on the plain listener's clocks", + () => + Effect.scoped( + Effect.gen(function* () { + const pair = yield* testPair; + const deadlines = { headers: 2_000, request: 60_000, idle: 150 }; + const admitted = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: { ...pair, deadlines }, + }); + const idle = yield* held( + admitted.port, + `GET /x HTTP/1.1\r\nHost: 127.0.0.1:${admitted.port}\r\n\r\n`, + ); + const stalled = yield* Effect.all([ + held(admitted.port, ""), + held(admitted.port, "G"), + held(admitted.port, `GET /x HTTP/1.1\r\nHost: 127.0.0.1:${admitted.port}\r\n`), + held(admitted.port, Buffer.from([0x16])), + ]); + yield* Effect.forEach([...stalled, idle], ({ socket }) => closed(socket), { + concurrency: "unbounded", + }); + for (const { received } of stalled) expect(received.text).toBe(""); + expect(idle.received.text).toMatch(/^HTTP\/1\.1 404 /u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + 10_000, +); + +it.effect( + "keeps a TLS port's slow, keep-alive and WebSocket connections past the header deadline", + () => + Effect.scoped( + Effect.gen(function* () { + const pair = yield* testPair; + const slow = yield* Deferred.make(); + const backend = createServer((incoming, outgoing) => + incoming.url === "/api/slow" + ? Deferred.doneUnsafe(slow, Effect.succeed(outgoing)) + : outgoing.end("pong"), + ); + const sockets = new WebSocketServer({ server: backend }); + sockets.on("connection", (socket) => + socket.on("message", (message) => socket.send(message)), + ); + const backendAddress = yield* listen(backend, { + beforeClose: () => { + for (const client of sockets.clients) client.terminate(); + }, + }); + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: { ...pair, deadlines: { headers: 1_000, request: 1_000, idle: 60_000 } }, + }); + yield* proxy.setRoutes([ + { id: "api", prefix: "/api", gateway: true, target: Effect.succeed(backendAddress) }, + ]); + const request = (target: string) => + `GET ${target} HTTP/1.1\r\nHost: 127.0.0.1:${proxy.port}\r\n\r\n`; + const kept = yield* held(proxy.port, request("/api/x")); + yield* replies(kept, "pong", 1); + const waiting = yield* held(proxy.port, request("/api/slow")); + const response = yield* Deferred.await(slow); + const client = yield* Effect.acquireRelease( + Effect.callback((resume) => { + const socket = new WebSocket(`ws://127.0.0.1:${proxy.port}/api/ws`); + socket.once("open", () => resume(Effect.succeed(socket))); + socket.once("error", (cause) => + resume(Effect.fail(new HttpProxyTestError({ message: cause.message, cause }))), + ); + }), + (socket) => Effect.sync(() => socket.terminate()), + ); + /* Each connection is past its headers, so running out their clocks must close none. */ + yield* TestClock.adjust(1_000); + response.end("late"); + expect(yield* replies(waiting, "late", 1)).toMatch(/^HTTP\/1\.1 200 /u); + kept.socket.write(request("/api/x")); + expect(yield* replies(kept, "pong", 2)).toMatch(/^HTTP\/1\.1 200 /u); + const echoed = yield* Effect.callback((resume) => { + client.once("message", (message) => + resume(Effect.succeed(Buffer.isBuffer(message) ? message.toString() : "")), + ); + client.send("still open"); + }); + expect(echoed).toBe("still open"); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +/* A keep-alive connection on a TLS port at the plain listener's clocks whose first request, + `POST /api/hold`, the backend answers only once its body ends; `woken` gates each route target. */ +const keepAlive = ( + mode: "plain" | "tls", + head: (host: string) => string, + woken: Effect.Effect = Effect.void, +) => + Effect.gen(function* () { + const pair = yield* testPair; + const holding = yield* Deferred.make(); + const backend = yield* listen( + createServer((incoming, outgoing) => { + if (incoming.url !== "/api/hold") return outgoing.end("pong"); + Deferred.doneUnsafe(holding, Effect.void); + incoming.resume(); + incoming.once("end", () => outgoing.end("held")); + }), + ); + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: { ...pair, deadlines: { headers: 12_000, request: 300_000, idle: 75_000 } }, + }); + yield* proxy.setRoutes([ + { id: "api", prefix: "/api", gateway: true, target: woken.pipe(Effect.as(backend)) }, + ]); + const host = `Host: 127.0.0.1:${proxy.port}\r\n`; + const connection = yield* held(proxy.port, head(host), mode === "tls" ? pair.cert : undefined); + return { connection, holding, host }; + }); + +/* Its first body byte, which reaches the backend only after the proxy's request, then the rest + and the next request's start in one write, which the proxy has read once the held response + arrives on the same connection. */ +const straddling = (mode: "plain" | "tls") => + Effect.gen(function* () { + const { connection, holding, host } = yield* keepAlive( + mode, + (host) => `POST /api/hold HTTP/1.1\r\n${host}Content-Length: 4\r\n\r\nb`, + ); + yield* Deferred.await(holding); + connection.socket.write("odyGET /api/x HTTP/1.1\r\n"); + yield* replies(connection, "held", 1); + return { connection, rest: `${host}\r\n` }; + }); + +/* The connection's next reply, or `closed` when the proxy closes it first. */ +const nextReply = (connection: Effect.Success>, body: string, count = 1) => + Effect.raceFirst( + replies(connection, body, count), + closed(connection.socket).pipe(Effect.as("closed")), + ); + +for (const mode of ["plain", "tls"] as const) { + it.effect(`lets a ${mode} request that started before idle ran out finish its headers`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection, rest } = yield* straddling(mode); + yield* TestClock.adjust(75_000); + yield* TestClock.adjust(11_999); + connection.socket.write(rest); + expect(yield* nextReply(connection, "pong")).toMatch(/HTTP\/1\.1 200 [^]*pong$/u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect( + `closes a ${mode} request that started before idle ran out at its header deadline`, + () => + Effect.scoped( + Effect.gen(function* () { + const { connection } = yield* straddling(mode); + yield* TestClock.adjust(75_000); + yield* TestClock.adjust(12_000); + yield* closed(connection.socket); + expect(connection.received.text).not.toContain("pong"); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`closes an idle ${mode} connection at idle`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection } = yield* keepAlive( + mode, + (host) => `GET /api/x HTTP/1.1\r\n${host}\r\n`, + ); + yield* replies(connection, "pong", 1); + yield* TestClock.adjust(75_000); + yield* closed(connection.socket); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`lets a ${mode} request body arrive until its request deadline`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection, holding } = yield* keepAlive( + mode, + (host) => `POST /api/hold HTTP/1.1\r\n${host}Content-Length: 4\r\n\r\nb`, + ); + yield* Deferred.await(holding); + yield* TestClock.adjust(299_999); + connection.socket.write("ody"); + expect(yield* nextReply(connection, "held")).toMatch(/HTTP\/1\.1 200 [^]*held$/u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`closes a ${mode} request whose body stalls at its request deadline`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection, holding } = yield* keepAlive( + mode, + (host) => `POST /api/hold HTTP/1.1\r\n${host}Content-Length: 4\r\n\r\nb`, + ); + yield* Deferred.await(holding); + yield* TestClock.adjust(300_000); + yield* closed(connection.socket); + expect(connection.received.text).not.toContain("held"); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`keeps a bodyless ${mode} request waiting on its route past the request deadline`, () => + Effect.scoped( + Effect.gen(function* () { + const asked = yield* Deferred.make(); + const wake = yield* Deferred.make(); + const { connection } = yield* keepAlive( + mode, + (host) => `GET /api/x HTTP/1.1\r\n${host}\r\n`, + Deferred.succeed(asked, undefined).pipe(Effect.andThen(Deferred.await(wake))), + ); + yield* Deferred.await(asked); + yield* TestClock.adjust(300_000); + yield* Deferred.succeed(wake, undefined); + expect(yield* nextReply(connection, "pong")).toMatch(/HTTP\/1\.1 200 [^]*pong$/u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect( + `keeps a ${mode} request whose body arrived waiting on its route past the request deadline`, + () => + Effect.scoped( + Effect.gen(function* () { + const asked = yield* Deferred.make(); + const wake = yield* Deferred.make(); + const { connection } = yield* keepAlive( + mode, + (host) => `POST /api/hold HTTP/1.1\r\n${host}Content-Length: 4\r\n\r\nbody`, + Deferred.succeed(asked, undefined).pipe(Effect.andThen(Deferred.await(wake))), + ); + yield* Deferred.await(asked); + yield* TestClock.adjust(300_000); + yield* Deferred.succeed(wake, undefined); + expect(yield* nextReply(connection, "held")).toMatch(/HTTP\/1\.1 200 [^]*held$/u); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`closes a ${mode} pipelined request whose body stalls at its request deadline`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection, holding } = yield* keepAlive( + mode, + (host) => + `GET /api/x HTTP/1.1\r\n${host}\r\nPOST /api/hold HTTP/1.1\r\n${host}Content-Length: 4\r\n\r\nb`, + ); + yield* replies(connection, "pong", 1); + yield* Deferred.await(holding); + yield* TestClock.adjust(300_000); + yield* closed(connection.socket); + expect(connection.received.text).not.toContain("held"); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.effect(`keeps a ${mode} pipelined partial request open for idle`, () => + Effect.scoped( + Effect.gen(function* () { + const { connection, host } = yield* keepAlive( + mode, + (host) => `GET /api/x HTTP/1.1\r\n${host}\r\nGET /api/x HTTP/1.1\r\n`, + ); + yield* replies(connection, "pong", 1); + yield* TestClock.adjust(74_999); + connection.socket.write(`${host}\r\n`); + expect(yield* nextReply(connection, "pong", 2)).toMatch( + /pong[^]*HTTP\/1\.1 200 [^]*pong$/u, + ); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); +} + +it.live( + "fails to listen when the certificate and key are not a pair, or it has no IP SAN for 127.0.0.1", + () => + Effect.scoped( + Effect.gen(function* () { + const pair = yield* testPair; + const other = generateKeyPairSync("ec", { namedCurve: "prime256v1" }).privateKey; + for (const tls of [ + { cert: pair.cert, key: other.export({ type: "pkcs8", format: "pem" }).toString() }, + { cert: pair.cert, key: "not a pem" }, + { cert: "not a pem", key: pair.key }, + { cert: "", key: "" }, + ]) { + const error = yield* Effect.flip(makeHttpProxy({ host: "127.0.0.1", port: 0, tls })); + expect(error.message).toMatch(/^api\.tls: invalid certificate or key: /u); + } + /* A matching pair whose certificate names 127.0.0.1 only by CN, beside DNS:localhost. */ + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const dnsOnly = yield* fs.readFileString( + path.join(import.meta.dirname, "..", "tests", "certs", "dns-only.crt"), + ); + const uncovered = yield* Effect.flip( + makeHttpProxy({ host: "127.0.0.1", port: 0, tls: { cert: dnsOnly, key: pair.key } }), + ); + expect(uncovered.message).toBe( + "api.tls: invalid certificate or key: the certificate has no IP subject alternative name for 127.0.0.1 (for example `mkcert localhost 127.0.0.1`)", + ); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "records a plain request or upgrade refused for its Host like any other, its token redacted", + () => + Effect.scoped( + Effect.gen(function* () { + const accesses = yield* Queue.unbounded(); + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + onAccess: (access) => Queue.offer(accesses, access), + tls: yield* testPair, + }); + const head = `GET /email/invite?token=secret HTTP/1.1\r\nHost: evil.example:${proxy.port}\r\nConnection: close\r\n\r\n`; + expect(yield* exchange(proxy.port, head)).toMatch(/^HTTP\/1\.1 421 /u); + const access = yield* Queue.take(accesses); + expect(access).toMatchObject({ status: 421, target: "/email/invite?token=redacted" }); + const upgrade = [ + `GET /socket?token=secret HTTP/1.1`, + `Host: evil.example:${proxy.port}`, + "Connection: Upgrade", + "Upgrade: websocket", + "Sec-WebSocket-Version: 13", + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==", + "", + "", + ].join("\r\n"); + expect(yield* exchange(proxy.port, upgrade)).toMatch(/^HTTP\/1\.1 421 /u); + expect(yield* Queue.take(accesses)).toMatchObject({ + status: 421, + target: "/socket?token=redacted", + }); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "closes a plain upgrade refused for its Host even when the client keeps its side open", + () => + Effect.scoped( + Effect.gen(function* () { + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: yield* testPair, + }); + const upgrade = [ + "GET /socket HTTP/1.1", + `Host: evil.example:${proxy.port}`, + "Connection: Upgrade", + "Upgrade: websocket", + "Sec-WebSocket-Version: 13", + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==", + "", + "", + ].join("\r\n"); + const socket = yield* Effect.acquireRelease( + Effect.sync(() => { + const client = new Socket({ allowHalfOpen: true }); + client.on("error", () => client.destroy()); + return client.connect(proxy.port, "127.0.0.1", () => client.write(upgrade)); + }), + (client) => Effect.sync(() => client.destroy()), + ); + const reply = yield* Effect.callback((resume) => { + let text = ""; + const onData = (chunk: Buffer) => { + text += chunk.toString("latin1"); + }; + const onEnd = () => resume(Effect.succeed(text)); + socket.on("data", onData); + socket.once("end", onEnd); + return Effect.sync(() => { + socket.off("data", onData); + socket.off("end", onEnd); + }); + }); + expect(reply).toMatch(/^HTTP\/1\.1 421 /u); + /* Bytes after the reply reach a closed connection, which resets it. */ + socket.write("still here"); + yield* closed(socket).pipe(Effect.timeout("10 seconds")); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); diff --git a/packages/stack/src/HttpProxy.ts b/packages/stack/src/HttpProxy.ts index 9cae624588..d75049ec5d 100644 --- a/packages/stack/src/HttpProxy.ts +++ b/packages/stack/src/HttpProxy.ts @@ -9,7 +9,9 @@ import { type IncomingMessage, type ServerResponse, } from "node:http"; // oxlint-disable-line effecttsgo/node-builtin-import -- raw HTTP upgrade sockets preserve handshake bytes. -import { Socket } from "node:net"; +import { X509Certificate, createPrivateKey } from "node:crypto"; +import { createServer as createNetServer, Socket } from "node:net"; +import { createSecureContext, type SecureContext, TLSSocket } from "node:tls"; import type { Duplex } from "node:stream"; class HttpProxyError extends Data.TaggedError("HttpProxyError")<{ @@ -171,7 +173,7 @@ const upstreamHeadersFor = (request: IncomingMessage, route: HttpRoute) => { route.upstreamPrefix === undefined || route.prefix === "/" ? undefined : (route.forwardedPrefix ?? `${route.prefix}/`); - result["x-forwarded-proto"] = "http"; + result["x-forwarded-proto"] = encrypted(request) ? "https" : "http"; if (host === undefined) delete result["x-forwarded-host"]; else result["x-forwarded-host"] = host; if (port === undefined) delete result["x-forwarded-port"]; @@ -688,10 +690,231 @@ const upgrade = Effect.fn("HttpProxy.upgrade")( ), ); +/* The connection's own proto, so a TLS port also forwards http for its plain requests. */ +const encrypted = (request: IncomingMessage) => request.socket instanceof TLSSocket; + +/** Container-facing names plain requests on a TLS port may carry, each with the API port. */ +const RUNTIME_HOSTS = [ + "host.supabase.internal", + "host.docker.internal", + "host.containers.internal", + "localhost", +]; + +/* An IP literal needs no DNS, so it can't be rebound; `pg_net` may call the bridge gateway. */ +const IP_LITERAL = /^(?:(?:\d{1,3}\.){3}\d{1,3}|\[[\da-f:.]+\])$/u; + +/** + * Whether a plain request's `Host` names a stack host alias, `localhost` or an IP literal with the + * API port, so a rebound DNS name never reaches the API in plain; on port 80 the port may be left out. + */ +export const plainHostAllowed = (host: string | undefined, port: number): boolean => { + const value = host?.toLowerCase() ?? ""; + const suffix = `:${port}`; + const name = value.endsWith(suffix) ? value.slice(0, -suffix.length) : port === 80 ? value : ""; + return RUNTIME_HOSTS.includes(name) || IP_LITERAL.test(name); +}; + +/** The readiness route a TLS port answers in plain while `HttpProxyTls.check` holds a reply. */ +export const API_TLS_CHECK_PATH = "/__api_tls_check"; + +/** + * Serves a TLS ClientHello with this PEM pair on the API port; any other first byte is plain HTTP + * from loopback, and every other connection closes before any HTTP byte. + */ +export interface HttpProxyTls { + readonly cert: string; + readonly key: string; + /** The body `GET API_TLS_CHECK_PATH` answers in plain with 200; undefined routes it normally. */ + readonly check?: Effect.Effect; + /** The plain listener's clocks unless a test shortens them. */ + readonly deadlines?: HttpDeadlines; +} + +interface HttpDeadlines { + /** From accept until a request's headers, a TLS handshake included. */ + readonly headers: number; + /** From a request's headers until its body has arrived; upgrades have none. */ + readonly request: number; + /** + * From a response until the connection's next request; when it runs out, a connection that read + * bytes since its last request gets `headers` once more, so a request started before it can finish. + */ + readonly idle: number; +} + +/* Advertising 5 s lets clients close idle sockets first; holding them 75 s, like Kong, keeps a + client that stalls past its own timer from reusing a closed one. */ +const KEEP_ALIVE_TIMEOUT_BUFFER = 70_000; + +/** + * The plain listener's clocks: 12 s for headers, 300 s for a request's body, then 75 s idle + * with no grace; `sniffing` adds a one-time 12 s grace for a request started before idle ran out. + */ +const PLAIN_LISTENER_DEADLINES: HttpDeadlines = { + headers: 12_000, + request: 300_000, + idle: 5_000 + KEEP_ALIVE_TIMEOUT_BUFFER, +}; + +const invalidApiTls = (cause: unknown) => + new PortError({ + key: "http", + message: `api.tls: invalid certificate or key: ${cause instanceof Error ? cause.message : String(cause)}`, + cause, + }); + +/* Fails on a certificate and key that are not a matching PEM pair, or whose certificate does not + cover the advertised `https://127.0.0.1`; an empty pair still makes a secure context, so the + pair is parsed and matched as well. */ +export const apiTlsContext = (tls: { readonly cert: string; readonly key: string }) => + Effect.try({ + try: () => { + const cert = new X509Certificate(tls.cert); + return { + context: createSecureContext({ cert: tls.cert, key: tls.key }), + matches: cert.checkPrivateKey(createPrivateKey(tls.key)), + covers: cert.checkIP("127.0.0.1") !== undefined, + }; + }, + catch: invalidApiTls, + }).pipe( + Effect.filterOrFail( + ({ matches }) => matches, + () => invalidApiTls("the certificate does not match the key"), + ), + Effect.filterOrFail( + ({ covers }) => covers, + () => + invalidApiTls( + "the certificate has no IP subject alternative name for 127.0.0.1 (for example `mkcert localhost 127.0.0.1`)", + ), + ), + Effect.map(({ context }) => context), + ); + +const unmapped = (address: string | undefined) => + address?.startsWith("::ffff:") === true ? address.slice(7) : (address ?? ""); + +/** Whether a socket's remote address is loopback, the only peer plain HTTP is served to under TLS. */ +export const loopbackPeer = (address: string | undefined) => { + const peer = unmapped(address); + return peer === "::1" || /^127\.\d+\.\d+\.\d+$/u.test(peer); +}; + +/* Hands each connection to `server` by its first byte, as `HttpProxyTls` describes; a rejected + peer is destroyed before `server` sees any of its bytes. */ +const sniffing = ( + tls: HttpProxyTls, + secureContext: SecureContext, + server: ReturnType, + sockets: Set, + runDeadline: (deadline: Effect.Effect) => Fiber.Fiber, +) => { + const deadlines = tls.deadlines ?? PLAIN_LISTENER_DEADLINES; + /* Handed-off sockets lose the HTTP server's own clocks, so each accepted one carries a timer + that waits for its next request and destroys the connection when it runs out. */ + interface Deadline { + readonly socket: Socket; + timer: Fiber.Fiber | undefined; + inFlight: number; + /** The raw socket's `bytesRead` at the latest request. */ + readAtRequest: number; + } + const pending = new WeakMap(); + const disarm = (deadline: Deadline) => { + deadline.timer?.interruptUnsafe(); + deadline.timer = undefined; + }; + const arm = (deadline: Deadline, ms: number) => { + disarm(deadline); + deadline.timer = runDeadline( + Effect.sleep(ms).pipe(Effect.andThen(Effect.sync(() => deadline.socket.destroy()))), + ); + }; + /* Never later than `idle + headers`: the grace is decided once, when idle runs out. */ + const armIdle = (deadline: Deadline) => { + disarm(deadline); + deadline.timer = runDeadline( + Effect.sleep(deadlines.idle).pipe( + Effect.andThen( + Effect.suspend(() => + deadline.socket.bytesRead > deadline.readAtRequest + ? Effect.sleep(deadlines.headers) + : Effect.void, + ), + ), + Effect.andThen(Effect.sync(() => deadline.socket.destroy())), + ), + ); + }; + const handOff = (deadline: Deadline, socket: Socket) => { + pending.set(socket, deadline); + server.emit("connection", socket); + }; + server.on("request", (request, response) => { + const deadline = pending.get(request.socket); + if (deadline === undefined) return; + deadline.inFlight += 1; + deadline.readAtRequest = deadline.socket.bytesRead; + disarm(deadline); + response.once("close", () => { + deadline.inFlight -= 1; + if (deadline.inFlight === 0 && !deadline.socket.destroyed) armIdle(deadline); + }); + /* A body that has not arrived by then closes the connection, as on the plain listener. */ + deadline.timer = runDeadline( + Effect.sleep(deadlines.request).pipe( + Effect.andThen( + Effect.sync(() => { + if (!request.complete) deadline.socket.destroy(); + }), + ), + ), + ); + }); + server.on("upgrade", (request) => { + const deadline = pending.get(request.socket); + if (deadline !== undefined) disarm(deadline); + pending.delete(request.socket); + }); + /* Reads `size` bytes without consuming them, or `undefined` when the peer ends first. */ + const peek = (socket: Socket, size: number, next: (bytes: Buffer | undefined) => void) => { + const bytes: Buffer | null = socket.read(size); + if (bytes !== null) { + socket.unshift(bytes); + next(bytes); + } else if (socket.readableEnded || socket.destroyed) next(undefined); + else socket.once("readable", () => peek(socket, size, next)); + }; + return createNetServer({ pauseOnConnect: true }, (socket) => { + const deadline: Deadline = { socket, timer: undefined, inFlight: 0, readAtRequest: 0 }; + arm(deadline, deadlines.headers); + sockets.add(socket); + socket.once("close", () => { + disarm(deadline); + sockets.delete(socket); + }); + socket.on("error", () => socket.destroy()); + const plain = loopbackPeer(socket.remoteAddress); + peek(socket, 1, (first) => { + if (first === undefined) return socket.destroy(); + if (first[0] === 0x16) { + const secure = new TLSSocket(socket, { isServer: true, secureContext }); + secure.on("error", () => secure.destroy()); + return handOff(deadline, secure); + } + if (plain) return handOff(deadline, socket); + socket.destroy(); + }); + }); +}; + export const makeHttpProxy = (options: { readonly host: string; readonly port: number; readonly onAccess?: HttpAccessSink | undefined; + readonly tls?: HttpProxyTls | undefined; }): Effect.Effect => Effect.gen(function* () { const routes = yield* Ref.make>([]); @@ -705,9 +928,13 @@ export const makeHttpProxy = (options: { const runRequest = yield* FiberSet.makeRuntime(); const sockets = new Set(); const onAccess = options.onAccess; - /* Advertising 5 s lets clients close idle sockets first; holding them 75 s, like Kong, keeps - a client that stalls past its own timer from reusing a closed one. */ - const server = createServer({ keepAliveTimeoutBuffer: 70_000 }, (request, response) => { + const tls = options.tls; + /* A plain request on the TLS port whose `Host` is no stack alias or loopback is 421. */ + const misdirected = (request: IncomingMessage) => + tls !== undefined && + !encrypted(request) && + !plainHostAllowed(headerValue(request.headers.host), request.socket.localPort ?? 0); + const handler = (request: IncomingMessage, response: ServerResponse) => { runRequest( Effect.gen(function* () { const sent: Sent = { bytes: 0, clientLeft: false }; @@ -726,11 +953,32 @@ export const makeHttpProxy = (options: { // The access record waits outside this scope, so it never holds the target's activity. yield* Effect.scoped( Effect.gen(function* () { + if (misdirected(request)) { + response.setHeader("content-type", "text/plain; charset=utf-8"); + respond(response, sent, 421, "Misdirected Request"); + return; + } + const check = + tls?.check === undefined || + encrypted(request) || + request.method !== "GET" || + request.url !== API_TLS_CHECK_PATH + ? undefined + : yield* tls.check; + if (check !== undefined) { + response.setHeader("content-type", "text/plain; charset=utf-8"); + response.setHeader("x-content-type-options", "nosniff"); + response.setHeader("cache-control", "no-store"); + respond(response, sent, 200, check); + return; + } const route = yield* Ref.get(routes).pipe( Effect.map((current) => routeFor(request.url ?? "/", current)), ); + /* Under TLS, Auth templates stay off the encrypted path, which the LAN reaches. */ if (route !== undefined && "file" in route) { - yield* serveFile(request, response, sent, route); + if (encrypted(request)) respond(response, sent, 404, "Not Found"); + else yield* serveFile(request, response, sent, route); return; } if (request.method === "OPTIONS" && route?.upstreamCors !== true) { @@ -773,7 +1021,8 @@ export const makeHttpProxy = (options: { ); }), ); - }); + }; + const server = createServer({ keepAliveTimeoutBuffer: KEEP_ALIVE_TIMEOUT_BUFFER }, handler); server.on("connection", (socket) => { sockets.add(socket); socket.once("close", () => { @@ -803,8 +1052,16 @@ export const makeHttpProxy = (options: { const route = yield* Ref.get(routes).pipe( Effect.map((current) => routeFor(request.url ?? "/", current)), ); - const outcome = - route === undefined || "file" in route + const outcome = misdirected(request) + ? yield* Effect.sync(() => { + /* The upgrade took the socket off its deadlines, so it closes once the reply is out. */ + socket.end( + "HTTP/1.1 421 Misdirected Request\r\nconnection: close\r\ncontent-length: 0\r\n\r\n", + () => socket.destroy(), + ); + return 421; + }) + : route === undefined || "file" in route ? yield* Effect.sync(() => { socket.destroy(); return 404; @@ -828,22 +1085,32 @@ export const makeHttpProxy = (options: { }), ); }); + const listener = + tls === undefined + ? server + : sniffing( + tls, + yield* apiTlsContext(tls), + server, + sockets, + yield* FiberSet.makeRuntime(), + ); yield* Effect.acquireRelease( Effect.callback((resume) => { const onError = (cause: Error) => resume(Effect.fail(new PortError({ key: "http", message: cause.message, cause }))); - server.once("error", onError); - server.listen(options.port, options.host, () => resume(Effect.void)); - return Effect.sync(() => server.off("error", onError)); + listener.once("error", onError); + listener.listen(options.port, options.host, () => resume(Effect.void)); + return Effect.sync(() => listener.off("error", onError)); }), () => Effect.callback((resume) => { - server.close(() => resume(Effect.void)); + listener.close(() => resume(Effect.void)); for (const socket of sockets) socket.destroy(); return Effect.sync(() => server.closeAllConnections?.()); }), ); - const address = server.address(); + const address = listener.address(); if (address === null || typeof address === "string") return yield* new PortError({ key: "http", message: "HTTP listener has no address" }); return { diff --git a/packages/stack/src/HttpProxy.unit.test.ts b/packages/stack/src/HttpProxy.unit.test.ts new file mode 100644 index 0000000000..03c52312fa --- /dev/null +++ b/packages/stack/src/HttpProxy.unit.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from "@effect/vitest"; +import { loopbackPeer, plainHostAllowed } from "./HttpProxy.ts"; + +describe("plain Host allowlist on a TLS API port", () => { + it("admits a stack alias, localhost or an IP literal only with the API port", () => { + for (const host of [ + "host.supabase.internal:54321", + "HOST.DOCKER.INTERNAL:54321", + "host.containers.internal:54321", + "127.0.0.1:54321", + "localhost:54321", + "172.17.0.1:54321", + "192.168.5.4:54321", + "[::1]:54321", + ]) + expect(plainHostAllowed(host, 54321), host).toBe(true); + for (const host of [ + undefined, + "", + "localhost", + "127.0.0.1", + "localhost:80", + "localhost:54322", + "evil.example:54321", + "localhost.evil.example:54321", + "172.17.0.1", + "172.17.0.1.nip.io:54321", + "10.0.0.1:54322", + ]) + expect(plainHostAllowed(host, 54321), String(host)).toBe(false); + }); + + it("accepts an allowed name without a port only on port 80", () => { + expect(plainHostAllowed("host.supabase.internal", 80)).toBe(true); + expect(plainHostAllowed("localhost", 80)).toBe(true); + expect(plainHostAllowed("localhost:80", 80)).toBe(true); + expect(plainHostAllowed("localhost:8080", 80)).toBe(false); + expect(plainHostAllowed("evil.example", 80)).toBe(false); + expect(plainHostAllowed("localhost", 8080)).toBe(false); + }); +}); + +describe("plain peer rule on a TLS API port", () => { + it("admits loopback peers only, IPv4-mapped included", () => { + for (const peer of ["127.0.0.1", "127.9.9.9", "::1", "::ffff:127.0.0.1"]) + expect(loopbackPeer(peer), peer).toBe(true); + for (const peer of [ + "::2", + "", + undefined, + "127x.0.0.1", + "128.0.0.1", + "::ffff:192.168.1.2", + "::7f00:1", + "172.17.42.5", + ]) + expect(loopbackPeer(peer), String(peer)).toBe(false); + }); +}); diff --git a/packages/stack/src/Network.integration.test.ts b/packages/stack/src/Network.integration.test.ts index b6dc5c35ba..27bbff10e4 100644 --- a/packages/stack/src/Network.integration.test.ts +++ b/packages/stack/src/Network.integration.test.ts @@ -1,13 +1,26 @@ import { NodeHttpClient, NodeServices } from "@effect/platform-node"; import { expect, it } from "@effect/vitest"; -import { Context, Data, Deferred, Effect, Fiber, FileSystem, Hash, Layer, Path, Ref } from "effect"; +import { + Context, + Data, + Deferred, + Effect, + Exit, + Fiber, + FileSystem, + Hash, + Layer, + Option, + Path, + Ref, +} from "effect"; import { randomUUID } from "node:crypto"; -import { networkInterfaces } from "node:os"; import * as Net from "node:net"; // oxlint-disable-line effecttsgo/node-builtin-import -- fixture retains an idle HTTP connection. +import * as Tls from "node:tls"; import { createServer, type RequestListener } from "node:http"; // oxlint-disable-line effecttsgo/node-builtin-import -- real socket fixture. import { HttpBody, HttpClient } from "effect/http"; import { ChildProcess, ChildProcessSpawner } from "effect/process"; -import type { HttpAccess, HttpAccessSink } from "./HttpProxy.ts"; +import { API_TLS_CHECK_PATH, type HttpAccess, type HttpAccessSink } from "./HttpProxy.ts"; import * as Network from "./Network.ts"; import * as PortReservations from "./namespace/PortReservations.ts"; import * as Ports from "./Ports.ts"; @@ -18,6 +31,7 @@ import type { ServiceCreation } from "./services/Catalog.ts"; import * as StackNamespace from "./StackNamespace.ts"; import { selection } from "../tests/pins.ts"; import { captureLogs } from "../tests/logs.ts"; +import { externalAddress } from "../tests/api-tls.ts"; const makeTestState = (root: string) => Layer.build(StackNamespace.layer({ root })).pipe( @@ -769,7 +783,11 @@ const authWith = ( }); /** An Auth shared route over a real project directory holding `invite.html`, beside `outside/`. */ -const emailTemplates = (runtime: Network.NetworkRuntime, onAccess?: HttpAccessSink) => +const emailTemplates = ( + runtime: Network.NetworkRuntime, + onAccess?: HttpAccessSink, + apiTls?: NonNullable, +) => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; @@ -784,39 +802,69 @@ const emailTemplates = (runtime: Network.NetworkRuntime, onAccess?: HttpAccessSi yield* fs.writeFileString(invite, "invite marker"); const stackId = `email-${randomUUID()}`; const state = yield* makeTestState(path.join(base, "state")); - yield* state.save(stack(stackId)); + yield* state.save({ ...stack(stackId), ...(apiTls === undefined ? {} : { apiTls }) }); const backendCalls = { count: 0 }; const target = yield* backendWith((_request, response) => { backendCalls.count += 1; response.end("backend"); }); const creation = yield* Ref.make(authWith(root, [{ id: "invite", path: invite }])); + /* Auth's shared routes on `network`, bound. */ + const serve = (network: Network.Interface) => + Effect.gen(function* () { + const namespace = yield* network.register({ + id: "auth", + endpoints: { + http: { + ...endpoint(target, Effect.succeed(false)), + shared: sharedRoutes( + { service: "auth" }, + "http", + { publishableKey: "", secretKey: "", anonKey: "", serviceRoleKey: "" }, + () => Effect.succeed(target), + emailTemplateFile(Ref.get(creation)), + ), + }, + }, + }); + const [binding] = yield* namespace.bind; + if (binding === undefined) return yield* new FixtureError({ message: "no binding" }); + yield* Effect.addFinalizer(() => network.releaseStack.pipe(Effect.ignore)); + return { namespace, port: binding.port }; + }); const network = yield* makeTestNetwork({ stackId, runtime, state, onAccess }); - const namespace = yield* network.register({ - id: "auth", - endpoints: { - http: { - ...endpoint(target, Effect.succeed(false)), - shared: sharedRoutes( - { service: "auth" }, - "http", - { publishableKey: "", secretKey: "", anonKey: "", serviceRoleKey: "" }, - () => Effect.succeed(target), - emailTemplateFile(Ref.get(creation)), - ), - }, - }, - }); - const [binding] = yield* namespace.bind; - if (binding === undefined) return yield* new FixtureError({ message: "no binding" }); - yield* Effect.addFinalizer(() => network.releaseStack.pipe(Effect.ignore)); - return { root, outside, invite, creation, backendCalls, port: binding.port }; + const { namespace, port } = yield* serve(network); + return { + root, + outside, + invite, + creation, + backendCalls, + port, + namespace, + network, + state, + stackId, + }; }); -/** Sends bytes as written, so a client never normalizes the path, and answers with the raw reply. */ -const raw = (port: number, head: string, host = "127.0.0.1", connection = "close") => +/** + * Sends a request head verbatim, Host included, over plain TCP or TLS, and answers the raw reply. + */ +const rawHead = ( + port: number, + lines: ReadonlyArray, + options: { readonly host?: string; readonly ca?: string } = {}, +) => Effect.callback((resume) => { - const socket = Net.connect({ host, port }); + const host = options.host ?? "127.0.0.1"; + const head = `${lines.join("\r\n")}\r\n\r\n`; + const socket = + options.ca === undefined + ? Net.connect({ host, port }, () => socket.write(head)) + : Tls.connect({ host, port, ca: options.ca, servername: "localhost" }, () => + socket.write(head), + ); let received = ""; socket.on("data", (chunk) => { received += chunk.toString(); @@ -825,14 +873,15 @@ const raw = (port: number, head: string, host = "127.0.0.1", connection = "close resume(Effect.fail(new FixtureError({ message: cause.message }))), ); socket.once("close", () => resume(Effect.succeed(received))); - socket.once("connect", () => - socket.write(`${head}\r\nHost: stack\r\nConnection: ${connection}\r\n\r\n`), - ); return Effect.sync(() => { socket.destroy(); }); }); +/** Sends bytes as written, so a client never normalizes the path, and answers with the raw reply. */ +const raw = (port: number, head: string, host = "127.0.0.1", connection = "close") => + rawHead(port, [head, "Host: stack", `Connection: ${connection}`], { host }); + const invite = "/email/invite?token=template-token"; it.live("serves configured templates from the live creation and fresh from disk", () => @@ -1059,16 +1108,6 @@ it.live("sends no CORS header on any template response", () => ).pipe(Effect.provide(NodeServices.layer)), ); -const external = Object.values(networkInterfaces()) - .flat() - .find((entry) => entry?.family === "IPv4" && !entry.internal)?.address; - -/* A LAN test that cannot reach the external interface fails rather than skips. */ -const externalAddress = - external === undefined - ? Effect.die("no external IPv4 address to reach the API from the LAN side") - : Effect.succeed(external); - it.live("keeps a template behind its token on the external address, and off it on native", () => Effect.scoped( Effect.gen(function* () { @@ -1300,3 +1339,514 @@ it.live("warns once about a template that keeps failing, and again after it reco }), ).pipe(Effect.provide(Layer.merge(NodeServices.layer, captureLogs(["Warn"])(warnings)))); }); + +/* A self-signed pair for localhost and 127.0.0.1, standing in for `[api.tls]`'s local one. */ +const localTls = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const certs = path.join(import.meta.dirname, "..", "tests", "certs"); + return { + cert: yield* fs.readFileString(path.join(certs, "trusted.crt")), + key: yield* fs.readFileString(path.join(certs, "localhost.key")), + }; +}); + +for (const runtime of ["docker", "native"] as const) + it.live(`serves the ${runtime} API over TLS and runtimes plain HTTP on the same port`, () => + Effect.scoped( + Effect.gen(function* () { + const tls = yield* localTls; + const { port, namespace } = yield* emailTemplates(runtime, undefined, tls); + const host = yield* namespace.address("http", "host"); + const inside = yield* namespace.address("http", "runtime"); + expect(host).toMatchObject({ host: "127.0.0.1", port, scheme: "https" }); + expect(inside).toMatchObject({ + host: runtime === "native" ? "127.0.0.1" : DOCKER_HOST_ALIAS, + port, + }); + expect(inside.scheme).toBeUndefined(); + + const get = (path: string, ...lines: Array) => [ + `GET ${path} HTTP/1.1`, + ...lines, + "Connection: close", + ]; + const at = `Host: host.supabase.internal:${port}`; + const secure = yield* rawHead(port, get("/auth/v1/health", `Host: localhost:${port}`), { + ca: tls.cert, + }); + expect(secure).toMatch(/^HTTP\/1\.1 200 /u); + expect(secure).toContain("backend"); + expect( + yield* rawHead(port, get(invite, `Host: localhost:${port}`), { ca: tls.cert }), + ).toMatch(/^HTTP\/1\.1 404 /u); + + expect(yield* rawHead(port, get("/auth/v1/health", at))).toMatch(/^HTTP\/1\.1 200 /u); + expect(yield* rawHead(port, get(invite, at))).toContain("invite marker"); + /* A function forwarding a browser's headers to the runtime URL keeps working. */ + expect( + yield* rawHead( + port, + get( + "/auth/v1/health", + at, + "Origin: http://localhost:3000", + "Sec-Fetch-Site: cross-site", + ), + ), + ).toMatch(/^HTTP\/1\.1 200 /u); + for (const head of [`Host: evil.example:${port}`, "Host: 127.0.0.1"]) + expect(yield* rawHead(port, get("/auth/v1/health", head)), head).toMatch( + /^HTTP\/1\.1 421 /u, + ); + /* Plain HTTP is for loopback only, even from this host's own LAN address. */ + const lan = yield* externalAddress; + if (runtime === "docker") { + expect( + yield* rawHead(port, get("/auth/v1/health", at), { host: lan }).pipe( + Effect.orElseSucceed(() => ""), + ), + ).toBe(""); + expect( + yield* rawHead(port, get("/auth/v1/health", `Host: localhost:${port}`), { + host: lan, + ca: tls.cert, + }), + ).toMatch(/^HTTP\/1\.1 200 /u); + } else yield* Effect.flip(rawHead(port, get("/auth/v1/health", at), { host: lan })); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + +it.live("keeps every listener, URL and scheme of the API without TLS", () => + Effect.scoped( + Effect.gen(function* () { + const { port, namespace } = yield* emailTemplates("docker"); + expect(yield* namespace.address("http", "host")).toEqual({ + name: "http", + protocol: "http", + host: "127.0.0.1", + port, + }); + expect( + yield* rawHead(port, [ + "GET /auth/v1/health HTTP/1.1", + "Host: anything", + "Connection: close", + ]), + ).toMatch(/^HTTP\/1\.1 200 /u); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live("advertises the scheme the open API listener serves, not the saved TLS", () => + Effect.scoped( + Effect.gen(function* () { + const tls = yield* localTls; + const { namespace, state, stackId } = yield* emailTemplates("docker", undefined, tls); + expect(yield* namespace.address("http", "host")).toMatchObject({ scheme: "https" }); + yield* state.save(stack(stackId)); + expect(yield* namespace.address("http", "host")).toMatchObject({ scheme: "https" }); + expect((yield* namespace.bindings).find(({ name }) => name === "http")?.scheme).toBe("https"); + yield* namespace.close; + expect((yield* namespace.address("http", "host")).scheme).toBeUndefined(); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live("answers the API's readiness route only while a start check runs", () => + Effect.scoped( + Effect.gen(function* () { + const tls = yield* localTls; + const { port, network } = yield* emailTemplates("docker", undefined, tls); + const probe = rawHead(port, [ + `GET ${API_TLS_CHECK_PATH} HTTP/1.1`, + `Host: ${DOCKER_HOST_ALIAS}:${port}`, + "Connection: close", + ]); + expect(yield* probe).toMatch(/^HTTP\/1\.1 404 /u); + const during = yield* network.checkApi("supabase-stack s1 n1", probe); + expect(during).toMatch(/^HTTP\/1\.1 200 /u); + expect(during.endsWith("\r\n\r\nsupabase-stack s1 n1")).toBe(true); + expect(yield* probe).toMatch(/^HTTP\/1\.1 404 /u); + yield* Effect.flip( + network.checkApi("supabase-stack s1 n2", new FixtureError({ message: "probe failed" })), + ); + expect(yield* probe).toMatch(/^HTTP\/1\.1 404 /u); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "reads the saved TLS before a shared API bind owns any scope, so it stays interruptible", + () => + Effect.scoped( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const base = yield* fs.makeTempDirectoryScoped({ prefix: "network-tls-read-" }); + const state = yield* makeTestState(path.join(base, "state")); + const stackId = `tls-read-${randomUUID()}`; + yield* state.save(stack(stackId)); + const reading = yield* Deferred.make(); + let stalled = false; + const network = yield* makeTestNetwork({ + stackId, + runtime: "docker", + state: { + ...state, + read: (id) => + Effect.suspend(() => + stalled + ? Deferred.succeed(reading, undefined).pipe(Effect.andThen(Effect.never)) + : state.read(id), + ), + }, + }); + yield* Effect.addFinalizer(() => network.releaseStack.pipe(Effect.ignore)); + const target = yield* backendWith((_request, response) => response.end("backend")); + const namespace = yield* network.register({ + id: "rest", + endpoints: { + http: { ...endpoint(target, Effect.succeed(false)), shared: [{ prefix: "/rest/v1" }] }, + }, + }); + stalled = true; + const binding = yield* Effect.forkChild(namespace.bind); + yield* Deferred.await(reading); + yield* Fiber.interrupt(binding); + stalled = false; + expect(yield* namespace.bind).toHaveLength(1); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +/* Listens on every address at `port`, or answers none while a listener there holds it. */ +const listenAll = (port: number) => + Effect.callback>((resume) => { + const server = Net.createServer((socket) => socket.destroy()); + server.once("error", () => resume(Effect.succeedNone)); + server.listen({ host: "0.0.0.0", port }, () => resume(Effect.succeedSome(server))); + return Effect.sync(() => { + server.close(); + }); + }); + +const closeServer = (server: Net.Server) => + Effect.callback((resume) => { + server.close(() => resume(Effect.void)); + return Effect.void; + }); + +/* A shared API listener serving trusted TLS, and from the first state read + that finds its port free, the one a reopen makes once the old listener closed, a test listener + that holds the port for `hold.reads` more reads; the next `hold.failures` reads fail. */ +const tlsReopen = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const base = yield* fs.makeTempDirectoryScoped({ prefix: "network-tls-reopen-" }); + const state = yield* makeTestState(path.join(base, "state")); + const stackId = `tls-reopen-${randomUUID()}`; + const trusted = yield* localTls; + const untrusted = { + ...trusted, + cert: yield* fs.readFileString( + path.join(import.meta.dirname, "..", "tests", "certs", "untrusted.crt"), + ), + }; + const saveTls = (tls: typeof trusted) => state.save({ ...stack(stackId), apiTls: tls }); + yield* saveTls(trusted); + const hold: { port: number; reads: number; failures: number; server: Net.Server | undefined } = { + port: 0, + reads: 0, + failures: 0, + server: undefined, + }; + const free = Effect.suspend(() => { + const server = hold.server; + hold.server = undefined; + return server === undefined ? Effect.void : closeServer(server); + }); + yield* Effect.addFinalizer(() => free); + const network = yield* makeTestNetwork({ + stackId, + runtime: "docker", + state: { + ...state, + read: (id) => + Effect.gen(function* () { + if (hold.failures > 0) { + hold.failures -= 1; + return yield* new StackNamespace.NamespaceError({ + operation: "read", + message: "unreadable state", + }); + } + if (hold.server !== undefined) { + if (hold.reads === 0) yield* free; + else hold.reads -= 1; + } else if (hold.port !== 0) { + hold.server = Option.getOrUndefined(yield* listenAll(hold.port)); + if (hold.server !== undefined) hold.port = 0; + } + return yield* state.read(id); + }), + }, + }); + yield* Effect.addFinalizer(() => network.releaseStack.pipe(Effect.ignore)); + const target = yield* backendWith((_request, response) => response.end("backend")); + const namespace = yield* network.register({ + id: "rest", + endpoints: { + http: { ...endpoint(target, Effect.succeed(false)), shared: [{ prefix: "/rest/v1" }] }, + }, + }); + const [binding] = yield* namespace.bind; + if (binding === undefined) return yield* new FixtureError({ message: "no binding" }); + const { port } = binding; + const served = (ca: string) => + rawHead( + port, + ["GET /rest/v1/health HTTP/1.1", `Host: localhost:${port}`, "Connection: close"], + { ca }, + ).pipe(Effect.orElseSucceed(() => "")); + const savedCert = state.read(stackId).pipe(Effect.map((saved) => saved?.apiTls?.cert)); + expect(yield* served(trusted.cert)).toContain("backend"); + return { + state, + stackId, + trusted, + untrusted, + saveTls, + hold, + free, + network, + namespace, + port, + served, + savedCert, + }; +}); + +/* A kept-alive TLS request loop on the API port trusting `ca`: `ask` answers the next reply, or + "closed" once the proxy closed the connection. */ +const keptAlive = (port: number, ca: string) => + Effect.acquireRelease( + Effect.callback((resume) => { + const socket = Tls.connect({ host: "127.0.0.1", port, ca, servername: "localhost" }, () => + resume(Effect.succeed(socket)), + ); + socket.once("error", (cause) => + resume(Effect.fail(new FixtureError({ message: cause.message }))), + ); + return Effect.sync(() => socket.destroy()); + }), + (socket) => Effect.sync(() => socket.destroy()), + ).pipe( + Effect.map((socket) => { + socket.on("error", () => socket.destroy()); + const closed = Effect.callback((resume) => { + if (socket.destroyed) return resume(Effect.succeed("closed")); + const onClose = () => resume(Effect.succeed("closed")); + socket.once("close", onClose); + return Effect.sync(() => socket.off("close", onClose)); + }); + const reply = Effect.callback((resume) => { + let text = ""; + const onData = (chunk: Buffer) => { + text += chunk.toString(); + if (text.includes("backend")) resume(Effect.succeed(text)); + }; + socket.on("data", onData); + socket.write(`GET /rest/v1/health HTTP/1.1\r\nHost: localhost:${port}\r\n\r\n`); + return Effect.sync(() => socket.off("data", onData)); + }); + return { ask: Effect.raceFirst(reply, closed), closed }; + }), + ); + +it.live( + "keeps the API listener and its connections when the same pair is saved again, and rebinds for a new one", + () => + Effect.scoped( + Effect.gen(function* () { + const { trusted, untrusted, saveTls, network, port, served } = yield* tlsReopen; + const connection = yield* keptAlive(port, trusted.cert); + expect(yield* connection.ask).toContain("backend"); + /* A recompose of the stopped stack saves its unchanged pair again. */ + yield* saveTls(trusted); + yield* network.reopenApi(Effect.void); + expect(yield* connection.ask).toContain("backend"); + expect(yield* network.apiTlsPort).toBe(port); + yield* saveTls(untrusted); + yield* network.reopenApi(Effect.void); + expect(yield* connection.closed).toBe("closed"); + expect(yield* served(untrusted.cert)).toContain("backend"); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "keeps serving the API with its TLS when a reopen can't listen, and opens it again once the port frees", + () => + Effect.scoped( + Effect.gen(function* () { + const { trusted, untrusted, saveTls, hold, free, network, namespace, port, served } = + yield* tlsReopen; + const savedAgain = saveTls(untrusted); + + /* The replacement can't listen, so the TLS it served is saved and opens again. */ + yield* saveTls(untrusted); + hold.port = port; + yield* Effect.flip(network.reopenApi(saveTls(trusted))); + expect(hold.server).toBeUndefined(); + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* served(trusted.cert)).toContain("backend"); + expect(yield* served(untrusted.cert)).toBe(""); + + yield* saveTls(untrusted); + yield* network.reopenApi(Effect.void); + expect(yield* served(untrusted.cert)).toContain("backend"); + expect(yield* served(trusted.cert)).toBe(""); + + /* Neither can listen: the next shared bind, then the next reopen, opens it again with the + TLS saved again. */ + for (const reopen of [namespace.bind, network.reopenApi(Effect.void)]) { + yield* saveTls(trusted); + hold.port = port; + hold.reads = Number.POSITIVE_INFINITY; + yield* Effect.flip(network.reopenApi(savedAgain)); + expect(yield* network.apiTlsPort).toBeUndefined(); + yield* free; + yield* reopen; + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* served(untrusted.cert)).toContain("backend"); + } + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "never opens the API in plain from a TLS removal that couldn't listen, for a shared bind right after it", + () => + Effect.scoped( + Effect.gen(function* () { + const { + state, + stackId, + trusted, + saveTls, + hold, + free, + network, + namespace, + port, + served, + savedCert, + } = yield* tlsReopen; + yield* state.save(stack(stackId)); + hold.port = port; + hold.reads = Number.POSITIVE_INFINITY; + yield* Effect.flip(network.reopenApi(saveTls(trusted))); + expect(yield* network.apiTlsPort).toBeUndefined(); + + /* The bind waits on the network until the TLS it served is saved again. */ + yield* free; + yield* namespace.bind; + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* savedCert).toBe(trusted.cert); + expect(yield* served(trusted.cert)).toContain("backend"); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "keeps the API closed while the TLS it served can't be saved again, then opens it with the saved TLS", + () => + Effect.scoped( + Effect.gen(function* () { + const { trusted, untrusted, saveTls, hold, network, namespace, port, served, savedCert } = + yield* tlsReopen; + yield* saveTls(untrusted); + hold.port = port; + const error = yield* Effect.flip( + network.reopenApi(Effect.fail(new FixtureError({ message: "read-only state" }))), + ); + expect(error).toBeInstanceOf(FixtureError); + expect(yield* network.apiTlsPort).toBeUndefined(); + expect(yield* savedCert).toBe(untrusted.cert); + + yield* namespace.bind; + expect(hold.server).toBeUndefined(); + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* served(untrusted.cert)).toContain("backend"); + expect(yield* served(trusted.cert)).toBe(""); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "closes the API when the saved TLS can't be read nor the TLS it served saved again, then opens it with the saved TLS", + () => + Effect.scoped( + Effect.gen(function* () { + const { trusted, untrusted, saveTls, hold, network, namespace, port, served, savedCert } = + yield* tlsReopen; + yield* saveTls(untrusted); + hold.failures = 1; + const error = yield* Effect.flip( + network.reopenApi(Effect.fail(new FixtureError({ message: "read-only state" }))), + ); + expect(error).toBeInstanceOf(FixtureError); + expect(yield* network.apiTlsPort).toBeUndefined(); + expect(yield* served(trusted.cert)).not.toContain("backend"); + + yield* namespace.bind; + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* savedCert).toBe(untrusted.cert); + expect(yield* served(untrusted.cert)).toContain("backend"); + expect(yield* served(trusted.cert)).toBe(""); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); + +it.live( + "closes the API when a reopen is interrupted while the TLS it served can't be saved again, then opens it with the saved TLS", + () => + Effect.scoped( + Effect.gen(function* () { + const { trusted, untrusted, saveTls, hold, network, namespace, port, served, savedCert } = + yield* tlsReopen; + yield* saveTls(untrusted); + hold.failures = 1; + const restoring = yield* Deferred.make(); + const release = yield* Deferred.make(); + const reopen = yield* Effect.forkChild( + network.reopenApi( + Effect.uninterruptible( + Deferred.succeed(restoring, undefined).pipe( + Effect.andThen(Deferred.await(release)), + Effect.andThen(Effect.fail(new FixtureError({ message: "read-only state" }))), + ), + ), + ), + ); + yield* Deferred.await(restoring); + /* The interrupt lands while the restore is in flight, then the restore fails. */ + const interrupting = yield* Effect.forkChild(Fiber.interrupt(reopen), { + startImmediately: true, + }); + yield* Deferred.succeed(release, undefined); + yield* Fiber.join(interrupting); + expect(Exit.hasInterrupts(yield* Fiber.await(reopen))).toBe(true); + expect(yield* network.apiTlsPort).toBeUndefined(); + expect(yield* served(trusted.cert)).not.toContain("backend"); + + yield* namespace.bind; + expect(yield* network.apiTlsPort).toBe(port); + expect(yield* savedCert).toBe(untrusted.cert); + expect(yield* served(untrusted.cert)).toContain("backend"); + expect(yield* served(trusted.cert)).toBe(""); + }), + ).pipe(Effect.provide(NodeServices.layer)), +); diff --git a/packages/stack/src/Network.ts b/packages/stack/src/Network.ts index fb88bac53a..105bde8c52 100644 --- a/packages/stack/src/Network.ts +++ b/packages/stack/src/Network.ts @@ -9,6 +9,7 @@ import { type HttpAccessSink, type HttpFileRoute, type HttpProxy, + type HttpProxyTls, type HttpRoute, } from "./HttpProxy.ts"; @@ -55,6 +56,8 @@ interface NetworkBinding { readonly protocol: "tcp" | "http"; readonly host: string; readonly port: number; + /** Set on the shared API endpoint's host address while it serves HTTPS. */ + readonly scheme?: "https"; } export interface NetworkNamespace { @@ -86,6 +89,25 @@ export interface Interface { key: string, port: number, ) => Effect.Effect; + /** The shared API listener's port while it is open and serves TLS. */ + readonly apiTlsPort: Effect.Effect; + /** + * Runs `check` while the readiness route answers with `body`. One caller at a time: a + * concurrent one would clear the first one's body. + */ + readonly checkApi: ( + body: string, + check: Effect.Effect, + ) => Effect.Effect; + /** + * Reopens the open shared API listener on its port with its routes when the saved TLS changed + * since it opened, so the TLS a stopped stack takes is the one it serves. When that fails, + * `restoreSaved` saves the previous TLS again before any shared bind can open the listener from + * the saved stack, which then opens with it; a failed `restoreSaved` leaves it closed and owed. + */ + readonly reopenApi: ( + restoreSaved: Effect.Effect, + ) => Effect.Effect; } export class Service extends Context.Service()("@supabase/stack/Network") {} @@ -126,16 +148,49 @@ const makeNetwork = (options: { readonly proxy: HttpProxy; readonly routes: ReadonlyArray; readonly scope: Scope.Closeable; + /** The port its first claimant requested, which a reopen requests again. */ + readonly requested: number | "auto"; + /** The saved TLS it serves, which host addresses follow; none is plain. */ + readonly tls: StackNamespace.ApiTls | undefined; } | undefined >(undefined); // Join routes queued before any claiming endpoint has created the shared listener. const pendingJoins = yield* Ref.make>([]); + /* The port request of a shared listener a failed reopen left closed; its routes wait in + `pendingJoins` until the next reopen or shared bind opens it again. */ + const lostApi = yield* Ref.make(undefined); const listenHost = options.runtime === "native" ? "127.0.0.1" : "0.0.0.0"; const hostAddress = "127.0.0.1"; const runtimeAddress = options.runtime === "native" ? "127.0.0.1" : DOCKER_HOST_ALIAS; + const apiTls = options.state.read(options.stackId).pipe( + Effect.map((saved) => saved?.apiTls), + Effect.mapError((cause) => errorFor("tls", cause)), + ); + + /* The body the readiness route answers with while a start check runs. */ + const checking = yield* Ref.make(undefined); + const proxyTls = (tls: StackNamespace.ApiTls): HttpProxyTls => ({ + cert: tls.cert, + key: tls.key, + check: Ref.get(checking), + }); + + /** Opens the shared API listener, serving the saved TLS when there is one. */ + const openApi = (host: string, port: number, tls: StackNamespace.ApiTls | undefined) => + Effect.gen(function* () { + yield* probe("api", host, port); + const proxy = yield* makeHttpProxy({ + host, + port, + onAccess: options.onAccess, + tls: tls === undefined ? undefined : proxyTls(tls), + }); + return { proxy }; + }); + const routeKey = (route: Pick) => `${route.id}:${route.prefix}`; /** Maps one endpoint's route contributions to routes; shared and joined proxy routes are `gateway` routes. */ @@ -178,6 +233,50 @@ const makeNetwork = (options: { yield* Ref.set(shared, { ...current, routes: next }); }); + /** Opens the shared listener at `requested` serving `tls`, with the routes owed to it. */ + const openShared = (requested: number | "auto", tls: StackNamespace.ApiTls | undefined) => + Effect.uninterruptibleMask((restore) => + Effect.gen(function* () { + const scope = yield* Scope.fork(owner, "sequential"); + const result = yield* restore( + ports + .acquire( + { stackId: options.stackId, key: "api", host: listenHost, port: requested }, + (host, port) => openApi(host, port, tls), + ) + .pipe( + Effect.provideService(Scope.Scope, scope), + Effect.mapError((cause) => errorFor("bind", cause)), + ), + ).pipe( + Effect.onExit((exit) => + Exit.isFailure(exit) ? Scope.close(scope, exit) : Effect.void, + ), + ); + const routes = yield* Ref.get(pendingJoins); + yield* result.listener.proxy.setRoutes(routes); + yield* Ref.set(pendingJoins, []); + yield* Ref.set(lostApi, undefined); + yield* Ref.set(shared, { + claim: result.port, + proxy: result.listener.proxy, + routes, + scope, + requested, + tls, + }); + }), + ); + + /* Opens a listener a failed reopen left closed with the saved TLS, or forgets it once its + routes all closed. */ + const reviveApi = Effect.gen(function* () { + const requested = yield* Ref.get(lostApi); + if (requested === undefined) return; + if ((yield* Ref.get(pendingJoins)).length === 0) return yield* Ref.set(lostApi, undefined); + yield* openShared(requested, yield* apiTls); + }); + const register = Effect.fn("Network.register")(function* ({ id, endpoints, @@ -194,14 +293,17 @@ const makeNetwork = (options: { Effect.gen(function* () { if (yield* Ref.get(closed)) return yield* errorFor("bind", "Network namespace is closed"); + if (Object.values(endpoints).some((endpoint) => endpoint.shared !== undefined)) + yield* reviveApi; for (const [name, endpoint] of Object.entries(endpoints)) { if ((yield* Ref.get(bound)).has(name)) continue; + const key = endpoint.shared === undefined ? `${id}:${name}` : "api"; + const claimed = endpoint.shared === undefined ? undefined : yield* Ref.get(shared); + const tls = + endpoint.shared !== undefined && claimed === undefined ? yield* apiTls : undefined; yield* Effect.uninterruptibleMask((restore) => Effect.gen(function* () { const endpointScope = yield* Scope.fork(owner, "sequential"); - const key = endpoint.shared === undefined ? `${id}:${name}` : "api"; - const claimed = - endpoint.shared === undefined ? undefined : yield* Ref.get(shared); const result = yield* restore( claimed !== undefined ? joinClaim(claimed, endpoint.port) @@ -215,15 +317,8 @@ const makeNetwork = (options: { }, (host, port) => Effect.gen(function* () { - if (endpoint.shared !== undefined) { - yield* probe(key, host, port); - const proxy = yield* makeHttpProxy({ - host, - port, - onAccess: options.onAccess, - }); - return { proxy }; - } + if (endpoint.shared !== undefined) + return yield* openApi(host, port, tls); if (endpoint.protocol === "http") { yield* probe(key, host, port); const proxy = yield* makeHttpProxy({ host, port }); @@ -262,6 +357,8 @@ const makeNetwork = (options: { proxy: result.listener.proxy, routes: seeded, scope: endpointScope, + requested: endpoint.port, + tls, }; if (previous !== undefined) yield* Scope.close(endpointScope, Exit.void); else if (seeded.length > 0) yield* Ref.set(pendingJoins, []); @@ -365,12 +462,21 @@ const makeNetwork = (options: { : endpoint.port; if (port === undefined) return yield* errorFor("address", `Endpoint ${name} is not assigned`); + /* Under TLS host clients use https, as the open listener serves or the next one will; + runtimes keep plain http on the same port. */ + const active = yield* Ref.get(shared); + const secure = + from === "host" && + endpoint.shared !== undefined && + (active === undefined ? (yield* apiTls) !== undefined : active.tls !== undefined); + const https: Pick = secure ? { scheme: "https" } : {}; return { name, protocol: endpoint.protocol, host: from === "host" ? hostAddress : runtimeAddress, port, - }; + ...https, + } satisfies NetworkBinding; }), ); return { @@ -379,10 +485,65 @@ const makeNetwork = (options: { release: release(), releasePorts: releasePorts(), address, - bindings: Ref.get(bound).pipe(Effect.map((values) => [...values.values()])), + /* The shared endpoint's host address follows the TLS its open listener serves. */ + bindings: Effect.all([Ref.get(bound), Ref.get(shared)]).pipe( + Effect.map(([values, active]) => + [...values.values()].map((binding): NetworkBinding => + endpoints[binding.name]?.shared !== undefined && active?.tls !== undefined + ? { ...binding, scheme: "https" } + : binding, + ), + ), + ), } satisfies NetworkNamespace; }); + /* Closes the shared listener, leaving its routes and port request owed to the next open. */ + const loseApi = Effect.uninterruptible( + Effect.gen(function* () { + const current = yield* Ref.get(shared); + if (current === undefined) return; + yield* Scope.close(current.scope, Exit.void); + yield* Ref.set(shared, undefined); + yield* Ref.set(pendingJoins, current.routes); + yield* Ref.set(lostApi, current.requested); + }), + ); + + const reopenApi = (restoreSaved: Effect.Effect) => + gate.withPermits(1)( + Effect.gen(function* () { + const current = yield* Ref.get(shared); + if (current === undefined) return yield* reviveApi; + const tls = yield* apiTls; + if (tls?.cert === current.tls?.cert && tls?.key === current.tls?.key) return; + /* Same-port binds can't overlap portably, so the old listener closes first and stays + owed until a replacement, or failing that the previous TLS again, opens. */ + yield* loseApi; + yield* openShared(current.requested, tls); + }).pipe( + /* Still under the gate, so a shared bind only ever opens the listener with what is + saved once the previous TLS is saved again; if that can't be saved, or the reopen + is interrupted first, a listener still open closes so the next bind opens the saved + TLS. */ + Effect.catch((error) => + restoreSaved.pipe( + Effect.onExit((exit) => (Exit.isFailure(exit) ? loseApi : Effect.void)), + Effect.andThen( + reviveApi.pipe( + Effect.catch((restored) => + Effect.logWarning( + `api: can't reopen the listener with its previous TLS, the next start retries: ${restored.message}`, + ), + ), + ), + ), + Effect.andThen(Effect.fail(error)), + ), + ), + ), + ); + const releaseStack = Effect.fn("Network.releaseStack")(() => ports .releaseStack(options.stackId) @@ -392,6 +553,16 @@ const makeNetwork = (options: { register, releaseStack: releaseStack(), claimNativePort: (key, port) => ports.claimNative(options.stackId, key, port), + apiTlsPort: Ref.get(shared).pipe( + Effect.map((current) => (current?.tls === undefined ? undefined : current.claim)), + ), + checkApi: (body, check) => + Effect.acquireUseRelease( + Ref.set(checking, body), + () => check, + () => Ref.set(checking, undefined), + ), + reopenApi, } satisfies Interface; }); diff --git a/packages/stack/src/Orchestrator.integration.test.ts b/packages/stack/src/Orchestrator.integration.test.ts index d4a61e11ec..345f133549 100644 --- a/packages/stack/src/Orchestrator.integration.test.ts +++ b/packages/stack/src/Orchestrator.integration.test.ts @@ -1420,22 +1420,27 @@ describe("idle races through a real listener", () => { const fs = yield* FileSystem.FileSystem; const root = yield* fs.makeTempDirectoryScoped({ prefix: "orchestrator-listener-" }); const stackId = `listener-${root.split("/").at(-1) ?? "stack"}`; - const state = yield* Layer.build(StackNamespace.layer({ root })).pipe( - Effect.map((context) => Context.get(context, StackNamespace.Service)), + /* The host-wide port registry retries a busy open on the clock, which TestClock never advances. */ + const network = yield* TestClock.withLive( + Effect.gen(function* () { + const state = yield* Layer.build(StackNamespace.layer({ root })).pipe( + Effect.map((context) => Context.get(context, StackNamespace.Service)), + ); + yield* state.save({ + id: stackId, + identity: { projectRoot: root, branchContext: "test", stackName: stackId }, + runtime: "native", + lifetime: "detached", + instances: [], + composition: { members: [], dependencies: [] }, + }); + return yield* Layer.build( + Network.layer({ stackId, runtime: "native" }).pipe( + Layer.provide(Layer.succeed(StackNamespace.Service, state)), + ), + ).pipe(Effect.map((context) => Context.get(context, Network.Service))); + }), ); - yield* state.save({ - id: stackId, - identity: { projectRoot: root, branchContext: "test", stackName: stackId }, - runtime: "native", - lifetime: "detached", - instances: [], - composition: { members: [], dependencies: [] }, - }); - const network = yield* Layer.build( - Network.layer({ stackId, runtime: "native" }).pipe( - Layer.provide(Layer.succeed(StackNamespace.Service, state)), - ), - ).pipe(Effect.map((context) => Context.get(context, Network.Service))); const orchestrator = yield* makeTestOrchestrator(); const address = yield* Ref.make<{ readonly host: string; readonly port: number } | undefined>( undefined, diff --git a/packages/stack/src/Owner.integration.test.ts b/packages/stack/src/Owner.integration.test.ts index d14eec8bdd..3a6af7b3ba 100644 --- a/packages/stack/src/Owner.integration.test.ts +++ b/packages/stack/src/Owner.integration.test.ts @@ -1,10 +1,24 @@ import { NodeCrypto, NodeHttpClient, NodeServices } from "@effect/platform-node"; import { PgClient } from "@effect/sql-pg"; import { describe, expect, it } from "@effect/vitest"; -import { Context, Effect, FileSystem, Layer, Redacted, Ref, Schema, Stream } from "effect"; +import { + Context, + Deferred, + Effect, + Fiber, + FileSystem, + Layer, + Option, + Redacted, + Ref, + Schema, + Stream, +} from "effect"; import { HttpClient } from "effect/http"; import { ChildProcess, ChildProcessSpawner } from "effect/process"; -import { randomUUID } from "node:crypto"; +import { generateKeyPairSync, randomUUID } from "node:crypto"; +import { createServer, type Server } from "node:net"; +import { connect as tlsConnect } from "node:tls"; import { RpcTest } from "effect/rpc"; import * as Owner from "./Owner.ts"; import { OwnerRpc } from "./Rpc.ts"; @@ -12,6 +26,10 @@ import * as PortReservations from "./namespace/PortReservations.ts"; import * as StackNamespace from "./StackNamespace.ts"; import type { SavedStack } from "./StackNamespace.ts"; import { DEFAULT_LOCAL_JWT_SECRET } from "./Defaults.ts"; +import { apiTlsRuntimeLabel } from "./runtime/ApiTlsSupport.ts"; +import { API_TLS_CHECK_PATH } from "./HttpProxy.ts"; +import { DOCKER_HOST_ALIAS } from "./runtime/Container.ts"; +import { containerPeer, isLoopback } from "../tests/api-tls.ts"; import type { ServiceCreationInput } from "./services/Catalog.ts"; import { ownerFor } from "../tests/owner-rpc.ts"; import { engineTarget, testEngine } from "../tests/engine-target.ts"; @@ -932,6 +950,185 @@ it.live("destroying one service deletes its port reservation", () => ), ); +const otherKey = () => + generateKeyPairSync("ec", { namedCurve: "prime256v1" }) + .privateKey.export({ type: "pkcs8", format: "pem" }) + .toString(); + +/* Listens on 127.0.0.1:`port`, or answers none while a listener there holds it. */ +const listenLoopback = (port: number) => + Effect.callback>((resume) => { + const server = createServer((socket) => socket.destroy()); + server.once("error", () => resume(Effect.succeedNone)); + server.listen({ host: "127.0.0.1", port }, () => resume(Effect.succeedSome(server))); + return Effect.sync(() => { + server.close(); + }); + }); + +/* Whether a TLS client trusting `ca` completes a handshake with 127.0.0.1:`port`. */ +const handshake = (port: number, ca: string) => + Effect.callback((resume) => { + const socket = tlsConnect({ host: "127.0.0.1", port, ca, servername: "localhost" }, () => + resume(Effect.succeed(true)), + ); + socket.once("error", () => resume(Effect.succeed(false))); + socket.once("close", () => resume(Effect.succeed(false))); + return Effect.sync(() => socket.destroy()); + }); + +it.live( + "serves the API TLS each recompose saves, or plain without it, on the listener an earlier claim opened, and keeps it on a mismatched pair", + () => + Effect.scoped( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const root = yield* fs.makeTempDirectoryScoped({ prefix: "stack-owner-api-tls-reopen-" }); + const stack = initial(`owner-api-tls-reopen-${randomUUID().slice(0, 8)}`); + const state = yield* stateFor(`${root}/state`); + yield* state.save(stack); + /* From the first state read that finds `holdPort` free, the one a TLS reopen makes once + the old listener closed, a test listener holds it for that one read. */ + const hold: { port: number; server: Server | undefined } = { port: 0, server: undefined }; + const free = Effect.suspend(() => { + const server = hold.server; + hold.server = undefined; + return server === undefined + ? Effect.void + : Effect.callback((resume) => { + server.close(() => resume(Effect.void)); + return Effect.void; + }); + }); + yield* Effect.addFinalizer(() => free); + const owner = yield* ownerFor({ + saved: stack, + state: { + ...state, + read: (id) => + Effect.gen(function* () { + if (hold.server !== undefined) yield* free; + else if (hold.port !== 0) { + hold.server = Option.getOrUndefined(yield* listenLoopback(hold.port)); + if (hold.server !== undefined) hold.port = 0; + } + return yield* state.read(id); + }), + }, + root: `${root}/data`, + cacheRoot, + }); + yield* Effect.addFinalizer(() => owner.namespace.destroy.pipe(Effect.ignore)); + const certs = `${import.meta.dirname}/../tests/certs`; + const apiTls = { + cert: yield* fs.readFileString(`${certs}/trusted.crt`), + key: yield* fs.readFileString(`${certs}/localhost.key`), + }; + const services: ReadonlyArray = [ + { + service: "database", + pin: selection.database, + config: { databasePassword: Redacted.make("api-tls-reopen-password"), jwtExpiry: 3600 }, + endpoints: { sql: { port: "auto" } }, + }, + { + service: "rest", + pin: selection.rest, + config: {}, + endpoints: { http: { port: "auto" } }, + }, + ]; + const api = ( + entries: ReadonlyArray<{ + readonly id: string; + readonly creation: { readonly service: string }; + }>, + ) => + Effect.gen(function* () { + const rest = entries.find(({ creation }) => creation.service === "rest"); + if (rest === undefined) return yield* Effect.die("rest was not composed"); + const { endpoints } = yield* owner.rpc.status({ id: rest.id }); + const http = endpoints.find(({ name }) => name === "http"); + if (http === undefined) return yield* Effect.die("rest has no API endpoint"); + return http; + }); + + /* A plain compose leaves the API listener open, as a startup endpoint claim does. */ + const plain = yield* owner.rpc.supabaseComposition({ services }); + const before = yield* api(plain); + expect(before.scheme).toBeUndefined(); + expect(yield* handshake(before.port, apiTls.cert)).toBe(false); + + const secured = yield* owner.rpc.supabaseComposition({ + services, + reuseIds: plain.map(({ id }) => id), + apiTls, + }); + expect(yield* api(secured)).toMatchObject({ port: before.port, scheme: "https" }); + expect(yield* handshake(before.port, apiTls.cert)).toBe(true); + + for (const invalid of [ + { ...apiTls, key: otherKey() }, + { cert: "", key: "" }, + ]) { + const mismatched = yield* Effect.flip( + owner.rpc.supabaseComposition({ + services, + reuseIds: plain.map(({ id }) => id), + apiTls: invalid, + }), + ); + expect(mismatched.message).toContain("api.tls: invalid certificate or key: "); + expect((yield* state.read(stack.id))?.apiTls).toMatchObject(apiTls); + expect(yield* handshake(before.port, apiTls.cert)).toBe(true); + } + + /* A rotation whose listener can't open keeps both the TLS it saved and the one it serves. */ + const untrusted = yield* fs.readFileString(`${certs}/untrusted.crt`); + const kept = (yield* state.read(stack.id))?.apiTls; + hold.port = before.port; + yield* Effect.flip( + owner.rpc.supabaseComposition({ + services, + reuseIds: plain.map(({ id }) => id), + apiTls: { ...apiTls, cert: untrusted }, + }), + ); + expect(hold.server).toBeUndefined(); + expect((yield* state.read(stack.id))?.apiTls).toEqual(kept); + expect(yield* handshake(before.port, apiTls.cert)).toBe(true); + expect(yield* handshake(before.port, untrusted)).toBe(false); + + const rotated = yield* owner.rpc.supabaseComposition({ + services, + reuseIds: plain.map(({ id }) => id), + apiTls: { ...apiTls, cert: untrusted }, + }); + expect(yield* api(rotated)).toMatchObject({ port: before.port, scheme: "https" }); + expect(yield* handshake(before.port, untrusted)).toBe(true); + expect(yield* handshake(before.port, apiTls.cert)).toBe(false); + + const unsecured = yield* owner.rpc.supabaseComposition({ + services, + reuseIds: plain.map(({ id }) => id), + }); + const after = yield* api(unsecured); + expect(after.port).toBe(before.port); + expect(after.scheme).toBeUndefined(); + expect(yield* handshake(before.port, untrusted)).toBe(false); + }), + ).pipe( + Effect.provide( + Layer.mergeAll( + NodeServices.layer, + NodeCrypto.layer, + NodeHttpClient.layerNodeHttp, + PortReservations.layer.pipe(Layer.provide(NodeServices.layer)), + ), + ), + ), +); + it.live("destroying a stack leaves its data root empty after an owner was killed mid-command", () => Effect.scoped( Effect.gen(function* () { @@ -1308,6 +1505,279 @@ it.live( 120_000, ); +/* What `probingEngine` does with the start check's probes. */ +interface Probes { + count: number; + /* Fails each probe's exec as an engine error would. */ + refuse: boolean; + /* Runs each probe with this host's bash at loopback, saving what it read into `dir`. */ + onHost: boolean; + dir?: string; + /* Holds the next probe until a lifecycle engine command arrives or the guard elapses. */ + hold?: { readonly started: Deferred.Deferred; readonly intruded: Deferred.Deferred }; + /* Whether a probe is held now. */ + holding: boolean; +} + +const probesFor = (onHost: boolean): Probes => ({ + count: 0, + refuse: false, + onHost, + holding: false, +}); + +const LIFECYCLE_VERBS = new Set(["create", "start", "stop", "kill", "rm", "restart"]); + +/* Counts the start check's container probes, passing every other engine command through. Off + `onHost`, a probe runs in the database container as in production. Reading to EOF behaves the + same on bash 3.2, so plain `bash` is enough here. */ +const probingEngine = (probes: Probes) => + Layer.effect( + ChildProcessSpawner.ChildProcessSpawner, + Effect.gen(function* () { + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + return ChildProcessSpawner.make((command) => { + if (!ChildProcess.isStandardCommand(command)) return delegate.spawn(command); + const args = command.args.map(String); + const script = args.at(-1) ?? ""; + if (!script.includes(API_TLS_CHECK_PATH)) { + const hold = probes.hold; + if ( + hold !== undefined && + probes.holding && + LIFECYCLE_VERBS.has(args[engineTarget.argv.length] ?? "") + ) + Deferred.doneUnsafe(hold.intruded, Effect.void); + return delegate.spawn(command); + } + probes.count += 1; + const index = probes.count; + const hold = probes.hold; + /* An overlapping restart's first lifecycle command releases the probe into it, failing the + start; serialised, nothing does, and the guard only bounds that wait. */ + const held = + hold === undefined + ? Effect.void + : Effect.sync(() => { + probes.holding = true; + }).pipe( + Effect.andThen(Deferred.succeed(hold.started, undefined)), + Effect.andThen( + Effect.raceFirst(Deferred.await(hold.intruded), Effect.sleep("2 seconds")), + ), + Effect.andThen( + Effect.sync(() => { + probes.hold = undefined; + probes.holding = false; + }), + ), + ); + const spawned = probes.refuse + ? ChildProcess.make("false") + : probes.onHost + ? ChildProcess.make("bash", [ + "-c", + `${script.replaceAll(DOCKER_HOST_ALIAS, "127.0.0.1")}; printf '%s' "$reply" > '${probes.dir}/probe-${index}'`, + ]) + : command; + return held.pipe(Effect.andThen(delegate.spawn(spawned))); + }); + }), + ).pipe(Layer.provide(NodeServices.layer)); + +/* A container stack with `[api.tls]` composed over a database and REST, owned by this scope. */ +const tlsStack = (name: string) => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const certs = `${import.meta.dirname}/../tests/certs`; + const apiTls = { + cert: yield* fs.readFileString(`${certs}/trusted.crt`), + key: yield* fs.readFileString(`${certs}/localhost.key`), + }; + const stackId = `${name}-${randomUUID().slice(0, 8)}`; + const dataRoot = yield* makeDockerDatabaseRoot(`stack-${name}-`, stackId); + const tempRoot = yield* fs.makeTempDirectoryScoped({ prefix: `stack-${name}-` }); + const stack = initialContainer(stackId); + const state = yield* stateFor(`${tempRoot}/state`); + yield* state.save(stack); + const owner = yield* ownerFor({ saved: stack, state, root: dataRoot, cacheRoot, engineTarget }); + yield* Effect.addFinalizer(() => owner.namespace.destroy.pipe(Effect.ignore)); + const database: ServiceCreationInput = { + service: "database", + pin: selection.database, + config: { + databasePassword: Redacted.make(`${name}-password`), + jwtSecret: Redacted.make(`${name}-jwt-secret-long-enough-to-sign`), + jwtExpiry: 3600, + }, + endpoints: { sql: { port: "auto" } }, + }; + const rest: ServiceCreationInput = { + service: "rest", + pin: selection.rest, + config: {}, + endpoints: { http: { port: "auto" } }, + }; + const stopped = (ids: ReadonlyArray) => + Effect.forEach(ids, (id) => + owner.rpc.status({ id }).pipe(Effect.map(({ lifecycle }) => lifecycle)), + ); + return { + stackId, + apiTls, + owner, + database, + rest, + stopped, + savedTls: state.read(stackId).pipe(Effect.map((saved) => saved?.apiTls)), + }; + }); + +const tlsLayer = (probes: Probes) => + Layer.mergeAll( + NodeServices.layer, + NodeCrypto.layer, + NodeHttpClient.layerNodeHttp, + PortReservations.layer.pipe(Layer.provide(NodeServices.layer)), + probingEngine(probes), + ); + +it.live( + "checks container reach under api.tls after every start and restart, and keeps it on a database recompose", + () => { + const probes = probesFor(false); + return Effect.scoped( + Effect.gen(function* () { + /* Whether this engine's containers reach this host from loopback, measured on its own. */ + const peer = yield* containerPeer(engineTarget); + const { apiTls, owner, database, rest, stopped, savedTls } = + yield* tlsStack("owner-api-tls"); + const runtime = apiTlsRuntimeLabel(engineTarget); + + const [first] = yield* owner.rpc.supabaseComposition({ services: [database], apiTls }); + if (first === undefined) return yield* Effect.die("no database was composed"); + const reuseIds = [first.id]; + /* A database alone opens no API listener, so there is nothing to check. */ + yield* owner.rpc.startComposition(); + expect(probes.count).toBe(0); + const rejected = yield* Effect.flip( + owner.rpc.supabaseComposition({ services: [database] }), + ); + expect(rejected.message).toContain("Composition is already configured"); + expect(yield* savedTls).toEqual(apiTls); + yield* owner.rpc.stopComposition(); + + const created = yield* owner.rpc.supabaseComposition({ + services: [database, rest], + reuseIds, + apiTls, + }); + const ids = created.map(({ id }) => id); + yield* owner.rpc.supabaseComposition({ + services: [database], + reuseIds, + retainMembers: true, + }); + expect(yield* savedTls).toEqual(apiTls); + if (isLoopback(peer)) { + yield* owner.rpc.startComposition(); + yield* owner.rpc.restartComposition(); + } else + for (const operation of [owner.rpc.startComposition(), owner.rpc.restartComposition()]) { + const unsupported = yield* Effect.flip(operation); + expect(unsupported.message).toContain( + `api.tls: unsupported networking on ${runtime}: `, + ); + expect(yield* stopped(ids)).toEqual(ids.map(() => "stopped")); + } + expect(probes.count).toBe(2); + + probes.refuse = true; + const refused = yield* Effect.flip(owner.rpc.restartComposition()); + expect(refused.message).toMatch( + new RegExp( + `^api\\.tls: containers can't reach the api port \\d+ on ${runtime} \\(probe failed for ${DOCKER_HOST_ALIAS}:\\d+: `, + "u", + ), + ); + expect(yield* stopped(ids)).toEqual(ids.map(() => "stopped")); + + yield* owner.rpc.supabaseComposition({ services: [database, rest], reuseIds: ids }); + expect(yield* savedTls).toBeUndefined(); + }), + ).pipe(Effect.provide(tlsLayer(probes))); + }, + { timeout: 240_000 }, +); + +it.live( + "checks overlapping starts and restarts one at a time, and an instance started or restarted alone", + () => { + const probes = probesFor(true); + return Effect.scoped( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + probes.dir = yield* fs.makeTempDirectoryScoped({ prefix: "stack-owner-api-tls-probes-" }); + const { stackId, apiTls, owner, database, rest, stopped } = + yield* tlsStack("owner-api-tls-order"); + const created = yield* owner.rpc.supabaseComposition({ + services: [database, rest], + apiTls, + }); + const ids = created.map(({ id }) => id); + const api = created.find(({ creation }) => creation.service === "rest")?.id; + if (api === undefined) return yield* Effect.die("no REST was composed"); + + /* A restart that overlapped a start's check would stop its containers or clear its reply, so + the start fails; serialised, both pass and each check reads its own reply. */ + const hold = { + started: yield* Deferred.make(), + intruded: yield* Deferred.make(), + }; + probes.hold = hold; + const starting = yield* Effect.forkChild(owner.rpc.startComposition()); + yield* Deferred.await(hold.started); + const restarting = yield* Effect.forkChild(owner.rpc.restartComposition()); + yield* Fiber.join(starting); + yield* Fiber.join(restarting); + expect(probes.count).toBe(2); + /* Each check armed its own reply for this stack. */ + const bodies = yield* Effect.forEach([1, 2], (index) => + fs + .readFileString(`${probes.dir}/probe-${index}`) + .pipe(Effect.map((reply) => reply.slice(reply.indexOf("\r\n\r\n") + 4))), + ); + for (const body of bodies) + expect(body).toMatch(new RegExp(`^supabase-stack ${stackId} [0-9a-f-]{36}$`, "u")); + expect(bodies[0]).not.toBe(bodies[1]); + + yield* owner.rpc.stopService({ id: api }); + yield* owner.rpc.startService({ id: api }); + expect(probes.count).toBe(3); + yield* owner.rpc.restartService({ id: api }); + expect(probes.count).toBe(4); + + /* A failed check stops the instance alone and the composition too. */ + const refusedWith = ( + operation: Effect.Effect, + ) => + Effect.gen(function* () { + probes.refuse = true; + const refused = yield* Effect.flip(operation); + probes.refuse = false; + expect(refused.message).toContain("api.tls: containers can't reach the api port "); + expect(yield* stopped(ids)).toEqual(ids.map(() => "stopped")); + }); + yield* refusedWith(owner.rpc.restartService({ id: api })); + yield* owner.rpc.startComposition(); + yield* owner.rpc.stopService({ id: api }); + yield* refusedWith(owner.rpc.startService({ id: api })); + }), + ).pipe(Effect.provide(tlsLayer(probes))); + }, + { timeout: 240_000 }, +); + // The Docker volume backend has no Podman counterpart: Podman keeps database data in host directories. describe.runIf(testEngine === "docker")("Docker volume storage", () => { it.live( diff --git a/packages/stack/src/Owner.ts b/packages/stack/src/Owner.ts index ec4efec9d1..43b7702eaf 100644 --- a/packages/stack/src/Owner.ts +++ b/packages/stack/src/Owner.ts @@ -26,6 +26,7 @@ import { isSchemaWriter, type SchemaWriterService, } from "./internal/schema-writers.ts"; +import { API_TLS_CHECK_PATH, apiTlsContext } from "./HttpProxy.ts"; import * as Network from "./Network.ts"; import type { NetworkEndpoint, NetworkNamespace } from "./Network.ts"; import * as Orchestrator from "./Orchestrator.ts"; @@ -76,6 +77,7 @@ import { } from "./services/Catalog.ts"; import type { CatalogError } from "./services/Recipe.ts"; import * as Container from "./runtime/Container.ts"; +import { apiTlsRuntimeLabel, checkApiTlsReach } from "./runtime/ApiTlsSupport.ts"; import { projectSegmentFor } from "./identity/Identity.ts"; import { stackError, type OwnerRpc } from "./Rpc.ts"; import { confirmStackDataRoot } from "./namespace/Paths.ts"; @@ -305,6 +307,9 @@ const makeOwner = Effect.fn("Owner.make")(function* ( service: GatewayLog.gatewayLog.service, }); const definitionGate = yield* Semaphore.make(1); + /* Serialises compose, starts and restarts with their checks; when both are needed, + `definitionGate` is taken first. */ + const lifecycle = yield* Semaphore.make(1); const { id: stackId, runtime } = options.saved; const project = projectSegmentFor(options.saved.identity, path); const routeKeys = { @@ -753,6 +758,93 @@ const makeOwner = Effect.fn("Owner.make")(function* ( }, Effect.mapError(serviceError("compose")), ); + /* A stopped stack takes the requested API TLS; a recompose that retains members without one + keeps the saved TLS. */ + const applyApiTls = Effect.fn("Owner.applyApiTls")(function* ( + apiTls: SupabaseCompositionOptions["apiTls"], + retainMembers: boolean, + ) { + if (apiTls === undefined && retainMembers) return; + if (apiTls !== undefined) + yield* apiTlsContext(apiTls).pipe(Effect.mapError(serviceError("bind"))); + const previous = yield* options.state + .withLock( + readSaved.pipe( + Effect.flatMap(({ apiTls: kept, ...current }) => + options.state + .save(apiTls === undefined ? current : { ...current, apiTls }) + .pipe(Effect.as(kept)), + ), + ), + ) + .pipe(Effect.mapError(serviceError("state"))); + /* An endpoint claim at owner startup can have opened the listener with the previous TLS; a + failed reopen saves that TLS again before the listener opens with it. */ + yield* network + .reopenApi( + options.state + .withLock( + readSaved.pipe( + Effect.flatMap(({ apiTls: _failed, ...current }) => + Effect.uninterruptible( + options.state.save( + previous === undefined ? current : { ...current, apiTls: previous }, + ), + ), + ), + ), + ) + .pipe(Effect.mapError(serviceError("state"))), + ) + .pipe(Effect.catchTag("NetworkError", (error) => Effect.fail(serviceError("bind")(error)))); + }); + + /* Under TLS on an engine, the database container must read this check's reply from the API + port in plain after a start or restart; otherwise the stack stops and the start fails. An + instance started alone is checked only while the database runs, and stops too on failure. */ + const reachApiTls = (instance?: string) => + Effect.gen(function* () { + if (runtime === "native" || options.engineTarget === undefined) return; + const members = new Set((yield* orchestrator.composition).members.map(({ id }) => id)); + const database = (yield* orchestrator.instances).find( + (entry) => entry.service === "database" && members.has(entry.id), + )?.id; + if (instance !== undefined) { + const running = + database !== undefined && + (yield* orchestrator.status(database).pipe( + Effect.map((status) => status.lifecycle === "running"), + Effect.orElseSucceed(() => false), + )); + if (!running) return; + } + yield* checkApiTlsReach({ + spawner: Context.get(services, ChildProcessSpawner.ChildProcessSpawner), + target: options.engineTarget, + stack: { id: stackId, root: path.resolve(options.root), database }, + runtime: apiTlsRuntimeLabel(options.engineTarget), + port: yield* network.apiTlsPort, + path: API_TLS_CHECK_PATH, + answering: network.checkApi, + body: crypto.uuidV4().pipe(Effect.map((nonce) => `supabase-stack ${stackId} ${nonce}`)), + /* The composition stops first, so no dependent keeps the instance up; both stops run, and + the first failure is reported. */ + stop: + instance === undefined + ? orchestrator.stopComposition + : Effect.gen(function* () { + const composition = yield* Effect.exit(orchestrator.stopComposition); + const stopped = yield* Effect.exit(orchestrator.stop(instance)); + if (Exit.isFailure(composition)) return yield* Effect.failCause(composition.cause); + if (Exit.isFailure(stopped)) return yield* Effect.failCause(stopped.cause); + }), + }).pipe( + Effect.mapError( + (error) => new ServiceError({ operation: "start", message: error.message }), + ), + ); + }); + const compose = Effect.fn("Owner.compose")( function* ( inputs: ReadonlyArray, @@ -770,13 +862,17 @@ const makeOwner = Effect.fn("Owner.make")(function* ( Effect.map((creation) => ({ id, creation })), ), status: orchestrator.status, + validated: applyApiTls( + compositionOptions.apiTls, + compositionOptions.retainMembers === true, + ), create: addInstance, destroy: orchestrator.destroy, bind: (id) => orchestrator.get(id).pipe(Effect.flatMap((entry) => entry.bind)), address: (id, endpoint, from) => orchestrator.get(id).pipe( Effect.flatMap((entry) => entry.namespace.address(endpoint, from)), - Effect.map(({ host, port }) => publicUrl(host, port)), + Effect.map(({ host, port, scheme }) => publicUrl(host, port, scheme)), ), output: (id, name) => orchestrator @@ -889,15 +985,25 @@ const makeOwner = Effect.fn("Owner.make")(function* ( ); }), ).pipe(rpcError("createService")), - startService: ({ id }) => orchestrator.start(id).pipe(rpcError("startService")), + startService: ({ id }) => + orchestrator.start(id).pipe( + Effect.tap(() => reachApiTls(id)), + lifecycle.withPermit, + rpcError("startService"), + ), readyService: ({ id }) => orchestrator.ready(id).pipe(rpcError("readyService")), stopService: ({ id }) => orchestrator.stop(id).pipe(rpcError("stopService")), // A config-changing restart can adopt saved credentials, so it serializes with definition // changes that introduce or roll them back. - restartService: ({ id, config }) => - (config === undefined ? restart(id, config) : definitionChange(restart(id, config))).pipe( + restartService: ({ id, config }) => { + const checked = restart(id, config).pipe( + Effect.tap(() => reachApiTls(id)), + lifecycle.withPermit, + ); + return (config === undefined ? checked : definitionChange(checked)).pipe( rpcError("restartService"), - ), + ); + }, destroyService: ({ id }) => definitionChange( confirmStackDataRoot(options.state.root, stackId).pipe( @@ -957,18 +1063,25 @@ const makeOwner = Effect.fn("Owner.make")(function* ( ).pipe(rpcError("restoreSnapshot")), resetData: ({ id }) => databaseData(id, ({ resetDatabaseData }) => resetDatabaseData).pipe(rpcError("resetData")), - supabaseComposition: ({ services, reuseIds, keys, eager, retainMembers }) => - definitionChange(compose(services, { reuseIds, keys, eager, retainMembers })).pipe( - rpcError("supabaseComposition"), - ), + supabaseComposition: ({ services, reuseIds, keys, eager, retainMembers, apiTls }) => + definitionChange( + lifecycle.withPermit(compose(services, { reuseIds, keys, eager, retainMembers, apiTls })), + ).pipe(rpcError("supabaseComposition")), configureComposition: (configuration) => definitionChange(configure(configuration)).pipe(rpcError("configureComposition")), startComposition: () => - orchestrator.startComposition.pipe(Effect.flatMap(observeAll), rpcError("startComposition")), + orchestrator.startComposition.pipe( + Effect.tap(() => reachApiTls()), + lifecycle.withPermit, + Effect.flatMap(observeAll), + rpcError("startComposition"), + ), stopComposition: () => orchestrator.stopComposition.pipe(Effect.flatMap(observeAll), rpcError("stopComposition")), restartComposition: () => orchestrator.restartComposition.pipe( + Effect.tap(() => reachApiTls()), + lifecycle.withPermit, Effect.flatMap(observeAll), rpcError("restartComposition"), ), diff --git a/packages/stack/src/Rpc.ts b/packages/stack/src/Rpc.ts index 3c6f9e2f56..2b7e29d6ad 100644 --- a/packages/stack/src/Rpc.ts +++ b/packages/stack/src/Rpc.ts @@ -4,7 +4,7 @@ import { ServiceCreation, ServiceCreationInput, ServiceRestartInput } from "./se import { snapshotScopes } from "./services/DatabaseSnapshot.ts"; import { causeMessage, CompositionConfig, OrchestratorError } from "./Orchestrator.ts"; import { CommandInvocation } from "./Commands.ts"; -import { StackKeysInput } from "./StackNamespace.ts"; +import { ApiTls, StackKeysInput } from "./StackNamespace.ts"; import { failureKind } from "./FailureKind.ts"; import { failureMessage } from "./internal/failure-message.ts"; import { rejectExcessKeys } from "./internal/reject-excess-keys.ts"; @@ -133,6 +133,8 @@ export const Observation = Schema.Struct({ protocol: Schema.Literals(["tcp", "http"]), host: Schema.String, port: Schema.Int, + /** `https` on the shared API endpoint while it serves TLS. */ + scheme: Schema.optionalKey(Schema.Literal("https")), }), ), config: ServiceCreation, @@ -226,6 +228,7 @@ export const OwnerRpc = RpcGroup.make( keys: Schema.optionalKey(StackKeysInput), eager: Schema.optionalKey(Schema.Boolean), retainMembers: Schema.optionalKey(Schema.Boolean), + apiTls: Schema.optionalKey(ApiTls), }, success: Schema.Array(Definition), error: StackError, diff --git a/packages/stack/src/StackNamespace.ts b/packages/stack/src/StackNamespace.ts index eeb61dfc07..9d4c7704d2 100644 --- a/packages/stack/src/StackNamespace.ts +++ b/packages/stack/src/StackNamespace.ts @@ -11,6 +11,7 @@ export { holdExclusiveLock, holdLock, holdSharedLock, isLockBusy } from "./names export { resolveStackDataRoot, stackDataRootLabel, stackLogsRoot } from "./namespace/Paths.ts"; export { publish } from "./namespace/Publication.ts"; export { + ApiTls, SavedStack, StackCredentials, StackKeysInput, diff --git a/packages/stack/src/composition/Supabase.native.integration.test.ts b/packages/stack/src/composition/Supabase.native.integration.test.ts index 5c00f7c4ed..b040bb6f78 100644 --- a/packages/stack/src/composition/Supabase.native.integration.test.ts +++ b/packages/stack/src/composition/Supabase.native.integration.test.ts @@ -69,6 +69,7 @@ it.live("reports the failed binding and cleanup reason with the retained instanc const operations: SupabaseCompositionOperations = { currentComposition: Effect.succeed({ members: [], dependencies: [] }), randomToken: Effect.succeed("token"), + validated: Effect.void, get: unused, status: unused, create: (creation) => Effect.succeed({ id: "retained-mail", creation }), @@ -170,6 +171,7 @@ it.live("cleans created registrations when composition is interrupted", () => const operations: SupabaseCompositionOperations = { currentComposition: Effect.succeed({ members: [], dependencies: [] }), randomToken: Effect.succeed("token"), + validated: Effect.void, get: () => unused("get"), status: () => unused("status"), create: (creation) => diff --git a/packages/stack/src/composition/Supabase.ts b/packages/stack/src/composition/Supabase.ts index ad97e7dfe5..2b5983482a 100644 --- a/packages/stack/src/composition/Supabase.ts +++ b/packages/stack/src/composition/Supabase.ts @@ -137,9 +137,16 @@ const derivedInputs: Partial< analyticsBackend: "analytics", functionsRoot: "functions", }, - functions: { apiUrl: "api", databaseUrl: "database" }, + functions: { apiUrl: "api", hostApiUrl: "api", databaseUrl: "database" }, }; +/** + * A Functions instance's `hostApiUrl`: only an HTTPS host API origin differs from the banner's + * plain loopback default, so a plain one is left out. + */ +export const functionsHostApiUrl = (apiHostUrl: string | undefined): string | undefined => + apiHostUrl?.startsWith("https:") === true ? apiHostUrl : undefined; + /** Derived inputs a project may set itself; a plan compares one whenever the request sets it. */ const overridableInputs: Partial>> = { studio: ["publicApiUrl"], @@ -202,6 +209,11 @@ export interface SupabaseCompositionOperations { creation: ServiceCreation, ) => Effect.Effect; readonly configure: (configuration: CompositionConfig) => Effect.Effect; + /** + * Runs once the request is valid, before any instance or binding changes; a later failure keeps + * its effects. + */ + readonly validated: Effect.Effect; } export interface SupabaseCompositionOptions { @@ -215,6 +227,8 @@ export interface SupabaseCompositionOptions { * endpoint start eagerly, and other members start on their first connection. */ readonly eager?: boolean; + /** Serves the shared API port over HTTPS with this PEM pair; plain HTTP only from loopback. */ + readonly apiTls?: { readonly cert: string; readonly key: string }; } /** How a saved instance differs from a requested creation once package-managed inputs are set aside. */ @@ -677,6 +691,7 @@ export const makeSupabaseComposition = Effect.fn("Supabase.compose")( } } + yield* operations.validated; const createdIds: Array = []; const compose = Effect.gen(function* () { const replacedByKind = new Map(); @@ -777,7 +792,7 @@ export const makeSupabaseComposition = Effect.fn("Supabase.compose")( } const configured = yield* Effect.forEach(configuredEntries, (entry) => Effect.gen(function* () { - const extra: Record = + const extra: Record = entry.creation.service === "auth" && apiHostUrl !== undefined ? { externalApiUrl: `${apiHostUrl}/auth/v1`, @@ -796,7 +811,7 @@ export const makeSupabaseComposition = Effect.fn("Supabase.compose")( publicApiUrl: entry.creation.config.publicApiUrl ?? apiHostUrl, } : entry.creation.service === "functions" && apiRuntimeUrl !== undefined - ? { apiUrl: apiRuntimeUrl } + ? { apiUrl: apiRuntimeUrl, hostApiUrl: functionsHostApiUrl(apiHostUrl) } : {}; const values = { ...configInputs.get(entry.id), ...extra }; if (entry.creation.service === "studio") { @@ -817,7 +832,7 @@ export const makeSupabaseComposition = Effect.fn("Supabase.compose")( database !== undefined && endpointNames(database.creation).includes("sql") ) - values.databaseUrl = yield* operations.output(database.id, "databaseUrl"); + values.databaseUrl = yield* operations.output(database.id, "functionsDatabaseUrl"); if (Object.keys(values).length > 0) { return yield* operations.updateCreation(entry.id, values); } diff --git a/packages/stack/src/composition/Supabase.unit.test.ts b/packages/stack/src/composition/Supabase.unit.test.ts index 74745e287f..9bfc756dc3 100644 --- a/packages/stack/src/composition/Supabase.unit.test.ts +++ b/packages/stack/src/composition/Supabase.unit.test.ts @@ -117,6 +117,7 @@ it.live( const operations: SupabaseCompositionOperations = { currentComposition: Effect.succeed({ members: [], dependencies: [] }), randomToken: Effect.succeed("token"), + validated: Effect.void, get: () => Effect.die("get is unused"), status: () => Effect.die("status is unused"), create: (creation) => Effect.succeed({ id: idFor(creation.service), creation }), @@ -150,6 +151,14 @@ it.live( if (configuredStudio?.creation.service !== "studio") return yield* Effect.die("Studio was not configured"); expect(configuredStudio.creation.config.functionsUrl).toBe(`url::${functionsId}`); + const configuredFunctions = configured.find( + ({ creation }) => creation.service === "functions", + ); + if (configuredFunctions?.creation.service !== "functions") + return yield* Effect.die("Functions was not configured"); + expect(configuredFunctions.creation.config.databaseUrl).toBe( + `functionsDatabaseUrl::${idFor("database")}`, + ); const orchestrator = yield* Orchestrator.make(); const database = yield* makeInstance(orchestrator, idFor("database"), { @@ -212,6 +221,73 @@ it.live( ).pipe(Effect.provide(TestClock.layer())), ); +it.effect("gives Auth, Studio and Functions the API's HTTPS host URL, keeping Studio's own", () => + Effect.gen(function* () { + const host = "https://127.0.0.1:54321"; + const runtime = "http://host.supabase.internal:54321"; + const derived = (studio: Record) => + Effect.gen(function* () { + const inputs: ReadonlyArray = [ + { + service: "auth", + pin: selection.auth, + config: { jwtSecret: "https-host-jwt-secret-with-32-chars", jwtExpiry: 3600 }, + endpoints: { http: { port: "auto" } }, + }, + { + service: "functions", + pin: selection.functions, + config: { functionsRoot: "/project/supabase/functions" }, + endpoints: { http: { port: "auto" } }, + }, + withValues( + { + service: "studio", + pin: selection.studio, + config: {}, + endpoints: { http: { port: "auto" } }, + }, + studio, + ), + ]; + const byId = new Map( + inputs.map((creation) => [creation.service, creation]), + ); + const configured = yield* makeSupabaseComposition( + { + currentComposition: Effect.succeed({ members: [], dependencies: [] }), + randomToken: Effect.succeed("token"), + validated: Effect.void, + get: () => Effect.die("get is unused"), + status: () => Effect.die("status is unused"), + create: (creation) => Effect.succeed({ id: creation.service, creation }), + destroy: () => Effect.die("destroy is unused"), + bind: () => Effect.void, + address: (_id, _endpoint, from) => Effect.succeed(from === "host" ? host : runtime), + output: (id, name) => Effect.succeed(`${name}::${id}`), + updateCreation: (id, values) => { + const base = byId.get(id); + return base === undefined + ? Effect.die(`Unknown instance ${id}`) + : Effect.succeed({ id, creation: withValues(base, values) }); + }, + replaceCreation: () => Effect.die("replaceCreation is unused"), + configure: () => Effect.void, + }, + inputs, + ); + return new Map(configured.map(({ creation }) => [creation.service, creation.config])); + }); + const configs = yield* derived({}); + expect(configs.get("auth")).toMatchObject({ externalApiUrl: `${host}/auth/v1` }); + expect(configs.get("studio")).toMatchObject({ apiUrl: runtime, publicApiUrl: host }); + expect(configs.get("functions")).toMatchObject({ apiUrl: runtime, hostApiUrl: host }); + expect( + (yield* derived({ publicApiUrl: "https://studio.example.com" })).get("studio"), + ).toMatchObject({ publicApiUrl: "https://studio.example.com" }); + }), +); + it("does not let an excluded sibling's stale fixed port mask a shared endpoint's own change", () => { const fixedPort = 54_321; const saved: Pick = { diff --git a/packages/stack/src/effect.ts b/packages/stack/src/effect.ts index 6caca1fab8..f9421d51a4 100644 --- a/packages/stack/src/effect.ts +++ b/packages/stack/src/effect.ts @@ -78,6 +78,7 @@ import type { export { initialization, postgres } from "./Commands.ts"; export { resolveNativePostgresUser } from "./runtime/postgres-user.ts"; export { apiRoute, sharesApiEndpoint } from "./host/Endpoints.ts"; +export { apiTlsContext } from "./HttpProxy.ts"; export { gatewayLog }; export { StackError } from "./Rpc.ts"; /** Atomically writes a file so readers only ever see the prior or the complete new content. */ @@ -299,6 +300,10 @@ export interface Stack { readonly credentials: { readonly get: Effect.Effect; }; + /** The certificate the API port serves HTTPS with since the last start, for host clients. */ + readonly apiTls: { + readonly get: Effect.Effect<{ readonly cert: string } | undefined, StackError>; + }; readonly composition: { readonly supabase: ( services: ReadonlyArray, @@ -861,6 +866,14 @@ const makeHandle = Effect.fn("Stack.makeHandle")(function* ( Effect.mapError((cause) => failure("credentials", cause)), ), }, + apiTls: { + get: state.read(saved.id).pipe( + Effect.map((current) => + current?.apiTls === undefined ? undefined : { cert: current.apiTls.cert }, + ), + Effect.mapError((cause) => failure("apiTls", cause)), + ), + }, composition: { supabase: ( services: ReadonlyArray, @@ -875,6 +888,7 @@ const makeHandle = Effect.fn("Stack.makeHandle")(function* ( ...(options?.retainMembers === undefined ? {} : { retainMembers: options.retainMembers }), + ...(options?.apiTls === undefined ? {} : { apiTls: options.apiTls }), }), ).pipe(Effect.map((definitions) => definitions.map(instance))), plan: Effect.fn("Stack.plan")(function* ( diff --git a/packages/stack/src/functions/generated/serve-main-bundle.ts b/packages/stack/src/functions/generated/serve-main-bundle.ts index 9ba90e6311..c41f5266d9 100644 --- a/packages/stack/src/functions/generated/serve-main-bundle.ts +++ b/packages/stack/src/functions/generated/serve-main-bundle.ts @@ -1,3 +1,3 @@ // Generated by packages/stack/scripts/generate-functions-bootstrap.ts; run `pnpm generate`. /** Bundled Edge Runtime main service used when a Functions creation has no bootstrap. */ -export const defaultFunctionsBootstrap = "var Bq=Object.defineProperty;var An=(e,t)=>{for(var r in t)Bq(e,r,{get:t[r],enumerable:!0})};var te=(e,t)=>{switch(t.length){case 0:return e;case 1:return t[0](e);case 2:return t[1](t[0](e));case 3:return t[2](t[1](t[0](e)));case 4:return t[3](t[2](t[1](t[0](e))));case 5:return t[4](t[3](t[2](t[1](t[0](e)))));case 6:return t[5](t[4](t[3](t[2](t[1](t[0](e))))));case 7:return t[6](t[5](t[4](t[3](t[2](t[1](t[0](e)))))));case 8:return t[7](t[6](t[5](t[4](t[3](t[2](t[1](t[0](e))))))));case 9:return t[8](t[7](t[6](t[5](t[4](t[3](t[2](t[1](t[0](e)))))))));default:{let r=e;for(let n=0,o=t.length;nt(r,...arguments)};switch(e){case 0:case 1:throw new RangeError(`Invalid arity ${e}`);case 2:return function(r,n){return arguments.length>=2?t(r,n):function(o){return t(o,r)}};case 3:return function(r,n,o){return arguments.length>=3?t(r,n,o):function(s){return t(s,r,n)}};default:return function(){if(arguments.length>=e)return t.apply(this,arguments);let r=arguments;return function(n){return t(n,...r)}}}};var D=e=>e;var gt=e=>()=>e,Cn=gt(!0),ap=gt(!1),Mb=gt(null),Vn=gt(void 0),zr=Vn;function Fb(e,...t){return te(e,t)}function gO(e,t,r,n,o,s,a,i,c){switch(arguments.length){case 1:return e;case 2:return function(){return t(e.apply(this,arguments))};case 3:return function(){return r(t(e.apply(this,arguments)))};case 4:return function(){return n(r(t(e.apply(this,arguments))))};case 5:return function(){return o(n(r(t(e.apply(this,arguments)))))};case 6:return function(){return s(o(n(r(t(e.apply(this,arguments))))))};case 7:return function(){return a(s(o(n(r(t(e.apply(this,arguments)))))))};case 8:return function(){return i(a(s(o(n(r(t(e.apply(this,arguments))))))))};case 9:return function(){return c(i(a(s(o(n(r(t(e.apply(this,arguments)))))))))}}}function on(e){let t=new WeakMap;return r=>{let n=t.get(r);if(n!==void 0)return n;let o=e(r);return t.set(r,o),o}}function qs(e){let t=new WeakMap;return r=>{let n=t.get(r);if(n!==void 0)return n;let o=e(r);return t.set(r,o),o!==r&&t.set(o,o),o}}var er={};An(er,{AsyncFiberError:()=>dJ,AsyncFiberErrorTypeId:()=>lJ,Done:()=>o0,DoneTypeId:()=>nJ,ExceededCapacityError:()=>s0,ExceededCapacityErrorTypeId:()=>fJ,IllegalArgumentError:()=>ud,IllegalArgumentErrorTypeId:()=>iJ,InterruptorStackTrace:()=>ZI,NoSuchElementError:()=>rJ,NoSuchElementErrorTypeId:()=>tJ,ReasonTypeId:()=>$3,StackTrace:()=>VI,TimeoutError:()=>aJ,TimeoutErrorTypeId:()=>oJ,TypeId:()=>L3,UnknownError:()=>xJ,UnknownErrorTypeId:()=>mJ,annotate:()=>gJ,annotations:()=>yJ,combine:()=>z3,die:()=>Rc,done:()=>ue,empty:()=>B3,fail:()=>j3,filterInterruptors:()=>Q3,findDefect:()=>cd,findDie:()=>G3,findError:()=>q3,findErrorOption:()=>r0,findFail:()=>W3,findInterrupt:()=>Z3,fromReasons:()=>gs,hasDies:()=>J3,hasFails:()=>t0,hasInterrupts:()=>V3,hasInterruptsOnly:()=>e0,interrupt:()=>H3,interruptors:()=>Y3,isAsyncFiberError:()=>pJ,isCause:()=>id,isDieReason:()=>QI,isDone:()=>Pc,isExceededCapacityError:()=>uJ,isFailReason:()=>ai,isIllegalArgumentError:()=>cJ,isInterruptReason:()=>K3,isNoSuchElementError:()=>eJ,isReason:()=>YI,isTimeoutError:()=>sJ,isUnknownError:()=>hJ,makeDieReason:()=>Cf,makeFailReason:()=>Af,makeInterruptReason:()=>XI,map:()=>fa,pretty:()=>n0,prettyErrors:()=>X3,reasonAnnotations:()=>ng,squash:()=>rg});var ip=e=>{let t=new Set(Reflect.ownKeys(e));if(e.constructor===Object)return t;e instanceof Error&&t.delete(\"stack\");let r=Object.getPrototypeOf(e),n=r;for(;n!==null&&n!==Object.prototype;){let o=Reflect.ownKeys(n);for(let s=0;snew Uint8Array(e.buffer,e.byteOffset,e.byteLength),up=e=>e instanceof ArrayBuffer||typeof SharedArrayBuffer<\"u\"&&e instanceof SharedArrayBuffer,fp=e=>{try{return new Uint8Array(e)}catch{return}};var ec=0,SO=()=>{ec++};function Wr(e){return typeof e==\"string\"}function lp(e){return typeof e==\"number\"}function Th(e){return typeof e==\"boolean\"}function bO(e){return typeof e==\"bigint\"}function Nb(e){return typeof e==\"symbol\"}function vh(e){return Wr(e)||lp(e)||Nb(e)}function qr(e){return typeof e==\"function\"}function EO(e){return e===void 0}function cs(e){return e!==void 0}function kh(e){return e!=null}function IO(e){return!1}function Ub(e){return!0}function fr(e){return typeof e==\"object\"&&e!==null&&!Array.isArray(e)}function pp(e){return typeof e==\"object\"&&e!==null||qr(e)}var A=l(2,(e,t)=>pp(e)&&t in e),Wt=l(2,(e,t)=>A(e,\"_tag\")&&e._tag===t);function wO(e){return e instanceof Error}function Js(e){return A(e,Symbol.iterator)||Wr(e)}var re=\"~effect/Hash\",V=e=>{switch(typeof e){case\"number\":return Lt(e);case\"bigint\":return Pe(e.toString(10));case\"string\":return Pe(e);case\"function\":case\"object\":{if(e===null)break;if(e instanceof Date)return Number.isNaN(e.getTime())?Pe(\"Invalid Date\"):Pe(e.toISOString());if(e instanceof RegExp)return Pe(e.toString());{if(Hu.has(e))return Db(e);let t=CO.get(e);if(t!==void 0)return t;if(Kb.has(e))return SO(),Pe(\"[Circular]\");Kb.add(e);let r=ec,n;try{if(jq(e))n=e[re]();else if(typeof e==\"function\")n=Db(e);else if(up(e)){let o=fp(e);n=o===void 0?Db(e):wo(o)}else e instanceof DataView?n=wo(cp(e)):Array.isArray(e)||ArrayBuffer.isView(e)?n=wo(e):e instanceof Map?n=Hq(e):e instanceof Set?n=zq(e):n=mp(e)}finally{Kb.delete(e)}return r===ec&&CO.set(e,n),n}}}return lr(TO(Pe(String(e))))},Db=e=>($b.has(e)||$b.set(e,lr(Math.random()*4294967296|0)),$b.get(e)),TO=e=>(e^=e>>>16,e=Math.imul(e,2246822507),e^=e>>>13,e=Math.imul(e,3266489909),e^e>>>16),Ee=l(2,(e,t)=>TO(Math.imul(e,2654435761)+Math.imul(t,2246822507))),lr=e=>e&3221225471|e>>>1&1073741824,jq=e=>A(e,re)&&typeof e[re]==\"function\",Lb=new DataView(new ArrayBuffer(8)),Lt=e=>{let t=e|0;return t===e?lr(t):(Lb.setFloat64(0,e!==e?NaN:e),lr(Ee(Lb.getInt32(0),Lb.getInt32(4))))},Pe=e=>{let t=5381,r=e.length;for(;r;)t=t*33^e.charCodeAt(--r);return lr(t)},dp=(e,t)=>{let r=12289;for(let n of t)r^=Ee(V(n),V(e[n]));return lr(r)},mp=e=>dp(e,ip(e)),vO=(e,t)=>r=>{let n=e;for(let o of r)n^=t(o);return lr(n)},wo=e=>{let t=6151;for(let r of e)t=Ee(t,V(r));return lr(t)},Hq=vO(Pe(\"Map\"),([e,t])=>Ee(V(e),V(t))),AO=Pe(\"Set\"),zq=vO(AO,e=>Ee(AO,V(e))),$b=new WeakMap,CO=new WeakMap,Kb=new WeakSet;var ne=\"~effect/Equal\";function Z(){return arguments.length===1?e=>tc(e,arguments[0]):tc(arguments[0],arguments[1])}function tc(e,t){if(e===t)return!0;if(e==null||t==null)return!1;let r=typeof e;return r!==typeof t?!1:r===\"number\"&&e!==e&&t!==t?!0:r!==\"object\"&&r!==\"function\"||Hu.has(e)||Hu.has(t)?!1:Wq(e,t)}function Wq(e,t){let r=Oh.length;for(let s=r;s-- >0;)if(Oh[s]===e&&jb[s]===t)return!0;if(r)return kO(e,t);let n=OO.get(e);n||OO.set(e,n=new WeakMap);let o=n.get(t);return o===void 0&&n.set(t,o=kO(e,t)),o}function kO(e,t){Oh.push(e),jb.push(t);try{return qq(e,t)}finally{Oh.pop(),jb.pop()}}var Oh=[],jb=[],OO=new WeakMap;function qq(e,t){if(V(e)!==V(t))return!1;if(e instanceof Date){if(!(t instanceof Date))return!1;let n=e.getTime(),o=t.getTime();return n===o||Number.isNaN(n)&&Number.isNaN(o)}else if(e instanceof RegExp)return t instanceof RegExp&&e.toString()===t.toString();let r=_O(e);if(r!==_O(t)||typeof e==\"function\"&&!r)return!1;if(r)return e[ne](t);if(Array.isArray(e))return!Array.isArray(t)||e.length!==t.length?!1:Jq(e,t);if(up(e)){if(!up(t)||e instanceof ArrayBuffer!=t instanceof ArrayBuffer)return!1;let n=fp(e),o=fp(t);return n!==void 0&&o!==void 0&&Bb(n,o)}else if(ArrayBuffer.isView(e)){let n=e instanceof DataView;return!ArrayBuffer.isView(t)||e.byteLength!==t.byteLength||n!==t instanceof DataView?!1:n?Bb(cp(e),cp(t)):Bb(e,t)}else{if(e instanceof Map)return!(t instanceof Map)||e.size!==t.size?!1:Hb(e,t,Vq,Zq);if(e instanceof Set)return!(t instanceof Set)||e.size!==t.size?!1:Hb(e,t,V,tc)}return Gq(e,t)}function Jq(e,t){for(let r=0;rV(e[0]),Zq=(e,t)=>tc(e[0],t[0])&&tc(e[1],t[1]),Yq=()=>0;function _h(e,t){return hp((r,n)=>e(r[0],n[0])&&t(r[1],n[1]))}function hp(e){return function(r,n){return Hb(r,n,Yq,e)}}var _O=e=>A(e,ne)&&typeof e[ne]==\"function\",xp=()=>Z;var Rh=e=>(Hu.add(e),e);var Gs=Symbol.for(\"~effect/Redactable\"),Qq=e=>A(e,Gs);function Ao(e){return Qq(e)?zb(e):e}function zb(e){return e[Gs](globalThis[rc]?.context??Xq)}var rc=\"~effect/Fiber/currentFiber\",RO=new Map,Xq={\"~effect/Context\":{},base:RO,depth:0,mapUnsafe:RO,pipe(){return te(this,arguments)}};function K(e,t){let r=t?.space??0,n=new WeakSet,o=r?typeof r==\"number\"?\" \".repeat(r):r:\"\",s=f=>o.repeat(f),a=(f,p)=>{let d=f?.constructor;return d&&d!==Object.prototype.constructor&&d.name?`${d.name}(${p})`:p},i=f=>{try{return Reflect.ownKeys(f)}catch{return[\"[ownKeys threw]\"]}};function c(f,p=0){try{return u(f,p)}catch{return(typeof f==\"object\"&&f!==null||typeof f==\"function\")&&n.delete(f),\"[inspection threw]\"}}function u(f,p=0){if(typeof f==\"string\")return JSON.stringify(f);if(typeof f==\"number\"||f==null||typeof f==\"boolean\"||typeof f==\"symbol\")return String(f);if(typeof f==\"bigint\")return String(f)+\"n\";if(typeof f==\"object\"||typeof f==\"function\"){if(n.has(f))return e6;n.add(f);let d;if(Gs in f)d=c(zb(f),p);else if(Array.isArray(f))d=!o||f.length<=1?`[${f.map(m=>c(m,p)).join(\",\")}]`:`[\n${s(p+1)}${f.map(m=>c(m,p+1)).join(`,\n`+s(p+1))}\n${s(p)}]`;else if(f instanceof Date)d=qb(f);else if(!t?.ignoreToString&&A(f,\"toString\")&&typeof f.toString==\"function\"&&f.toString!==Object.prototype.toString&&f.toString!==Array.prototype.toString){let m=t6(f);d=f instanceof Error&&f.cause!==void 0?`${m} (cause: ${c(f.cause,p)})`:m}else if(Symbol.iterator in f)d=`${f.constructor.name}(${c(Array.from(f),p)})`;else{let m=i(f);if(!o||m.length<=1){let h=`{${m.map(y=>`${us(y)}:${c(PO(f,y),p)}`).join(\",\")}}`;d=a(f,h)}else{let h=`{\n${m.map(y=>`${s(p+1)}${us(y)}: ${c(PO(f,y),p+1)}`).join(`,\n`)}\n${s(p)}}`;d=a(f,h)}}return n.delete(f),d}return String(f)}return c(e,0)}var e6=\"[Circular]\";function us(e){return typeof e==\"string\"?JSON.stringify(e):String(e)}function Ph(e){return e.map(t=>`[${us(t)}]`).join(\"\")}function qb(e){try{return e.toISOString()}catch{return\"Invalid Date\"}}function t6(e){try{let t=e.toString();return typeof t==\"string\"?t:String(t)}catch{return\"[toString threw]\"}}function PO(e,t){try{return e[t]}catch{return\"[property access threw]\"}}function nc(e,t){let r=[],n=new WeakMap;return JSON.stringify(e,function(o,s){let a=Object.getOwnPropertyDescriptor(n.get(this)??this,o)?.value,i=A(a,Gs)?Ao(a):Ao(s);if(typeof i==\"bigint\")return K(i);if(typeof i!=\"object\"||i===null)return i;let c=i instanceof Error&&!A(i,\"toJSON\")?{...i,name:i.name,message:i.message}:i;for(;r.length>0&&r[r.length-1]!==this;)r.pop();if(r.includes(i))return;if(r.push(i),c!==i&&r.push(c),!r6(c)||o6(c))return c;let u=n6(c);return n.set(u,c),r.push(u),u},t?.space)??\"null\"}function r6(e){for(let t of Object.getOwnPropertyNames(e))if(Object.getOwnPropertyDescriptor(e,t)?.get!==void 0)return!0;return!1}function n6(e){let t=Array.isArray(e)?[]:{},r=Array.isArray(e)?Array.from({length:e.length},(n,o)=>String(o)):Object.keys(e);for(let n of r)Object.defineProperty(t,n,{enumerable:!0,get:()=>{let o=Reflect.get(e,n);return Object.getOwnPropertyDescriptor(e,n)?.get!==void 0?Ao(o):o}});return t}function o6(e){for(let t of[Number.prototype.valueOf,Boolean.prototype.valueOf,String.prototype.valueOf])try{return Reflect.apply(t,e,[]),!0}catch{}return!1}var Je=Symbol.for(\"nodejs.util.inspect.custom\"),qt=e=>{try{return e=Ao(e),A(e,\"toJSON\")&&qr(e.toJSON)&&e.toJSON.length===0?e.toJSON():Array.isArray(e)?e.map(qt):e}catch{return\"[toJSON threw]\"}},FO=(e,t=2)=>{if(typeof e==\"string\")return e;try{return typeof e==\"object\"?nc(e,{space:t}):K(e,{space:t})}catch{return String(e)}},$t={toJSON(){return qt(this)},[Je](){return this.toJSON()},toString(){return K(this.toJSON())}},MO=class{[Je](){return this.toJSON()}toString(){return K(this.toJSON())}};var a6=()=>{let e=Object.getOwnPropertyDescriptor(Error,\"stackTraceLimit\");return e===void 0?Object.isExtensible(Error):Object.hasOwn(e,\"writable\")?e.writable===!0:e.set!==void 0},i6=a6(),Co=()=>Error.stackTraceLimit,pr=e=>{i6&&(Error.stackTraceLimit=e)};var Ha=class{constructor(t){this.value=t,this.done=!1}next(t){return this.done?(this.value=t,this):(this.done=!0,{value:this.value,done:!1})}},c6=()=>{let e=\"~effect/Utils/internal\",t={[e]:s=>s()},r={[e]:s=>s()},n=Co();if(n===0)return r[e];pr(2);let o=t[e](()=>new Error);return pr(n),o.stack?.includes(e)===!0?t[e]:r[e]},za=c6();function B(e,t,r){t===\"__proto__\"?Object.defineProperty(e,t,{value:r,writable:!0,enumerable:!0,configurable:!0}):e[t]=r}function Mh(e,t){if(!Object.hasOwn(t,\"__proto__\")){Object.assign(e,t);return}for(let r of Reflect.ownKeys(t))Object.prototype.propertyIsEnumerable.call(t,r)&&B(e,r,t[r])}var fs=\"~effect/Effect\",oc=\"~effect/Exit\",f6={_A:D,_E:D,_R:D},Jb=`${fs}/identifier`,xe=`${fs}/args`,lt=`${fs}/evaluate`,Gt=`${fs}/successCont`,Tn=`${fs}/failureCont`,sc=`${fs}/ensureCont`,uc=Symbol.for(\"effect/Effect/Yield\"),kr={pipe(){return te(this,arguments)},toJSON(){return{...this}},toString(){return K(this.toJSON(),{ignoreToString:!0,space:2})},[Je](){return this.toJSON()}},UO={[re](){return dp(this,Object.keys(this))},[ne](e){let t=Object.keys(this),r=Object.keys(e);if(t.length!==r.length)return!1;for(let n=0;nA(e,fs),Sp=e=>A(e,oc),gp=\"~effect/Cause\",zu=\"~effect/Cause/Reason\",qu=e=>A(e,gp),DO=e=>A(e,zu),To=class{constructor(t){this[gp]=gp,this.reasons=t}pipe(){return te(this,arguments)}toJSON(){return{_id:\"Cause\",reasons:this.reasons.map(t=>t.toJSON())}}toString(){return`Cause(${K(this.reasons)})`}[Je](){return this.toJSON()}[ne](t){return qu(t)&&this.reasons.length===t.reasons.length&&this.reasons.every((r,n)=>Z(r,t.reasons[n]))}[re](){return wo(this.reasons)}},NO=new WeakMap,Wu=class{[zu];annotations;_tag;constructor(t,r,n){if(this[zu]=zu,this._tag=t,r!==bp&&typeof n==\"object\"&&n!==null&&r.size>0){let o=NO.get(n);o&&(r=new Map([...o,...r])),NO.set(n,r)}this.annotations=r}annotate(t,r){if(t.mapUnsafe.size===0)return this;let n=new Map(this.annotations);if(t.mapUnsafe.forEach((s,a)=>{r?.overwrite!==!0&&n.has(a)||n.set(a,s)}),r?.overwrite!==!0&&n.size===this.annotations.size)return this;let o=Object.assign(Object.create(Object.getPrototypeOf(this)),this);return o.annotations=n,o}pipe(){return te(this,arguments)}toString(){return K(this)}[Je](){return this.toString()}},bp=new Map,ac=class extends Wu{constructor(t,r=bp){super(\"Fail\",r,t),this.error=t}toString(){return`Fail(${K(this.error)})`}toJSON(){return{_tag:\"Fail\",error:this.error}}[ne](t){return fc(t)&&Z(this.error,t.error)&&Z(this.annotations,t.annotations)}[re](){return Ee(Pe(this._tag))(Ee(V(this.error))(V(this.annotations)))}},ls=e=>new To(e),p6=(e,t)=>{let r=new Map,n=[];for(let o of e.concat(t)){let s=V(o),a=r.get(s);if(a===void 0)r.set(s,[o]);else{if(a.some(i=>Z(i,o)))continue;a.push(o)}n.push(o)}return n},Ep=l(2,(e,t)=>{if(e.reasons.length===0)return t;if(t.reasons.length===0)return e;let r=new To(p6(e.reasons,t.reasons));return Z(e,r)?e:r}),Gb=(e,t)=>{let r=e.reasons.slice();for(let n of t.reasons)Zs(n)&&!r.some(o=>Zs(o)&&o.fiberId===n.fiberId&&o.annotations===n.annotations)&&r.push(n);return r.length===e.reasons.length?e:new To(r)},Fh=new To([]),Ju=e=>new To([new ac(e)]),ic=class extends Wu{constructor(t,r=bp){super(\"Die\",r,t),this.defect=t}toString(){return`Die(${K(this.defect)})`}toJSON(){return{_tag:\"Die\",defect:this.defect}}[ne](t){return lc(t)&&Z(this.defect,t.defect)&&Z(this.annotations,t.annotations)}[re](){return Ee(Pe(this._tag))(Ee(V(this.defect))(V(this.annotations)))}},Vb=e=>new To([new ic(e)]),Gu=l(e=>qu(e[0]),(e,t,r)=>t.mapUnsafe.size===0?e:new To(e.reasons.map(n=>n.annotate(t,r)))),fc=e=>e._tag===\"Fail\",lc=e=>e._tag===\"Die\",Zs=e=>e._tag===\"Interrupt\";function d6(e){return Jr(\"Effect.evaluate: Not implemented\")}var vn=e=>({...l6,[Jb]:e.op,[lt]:e[lt]??d6,[Gt]:e[Gt],[Tn]:e[Tn],[sc]:e[sc]}),Zn=e=>{let t=vn(e),r=function(n){this[xe]=n};return r.prototype=t,function(n){return new r(n)}},LO=e=>{let t={[oc]:oc,_tag:e.op,get[e.prop](){return this[xe]},...vn(e),toString(){return`${e.op}(${K(this[xe])})`},toJSON(){return{_id:\"Exit\",_tag:e.op,[e.prop]:this[xe]}},[ne](n){return Sp(n)&&n._tag===this._tag&&Z(this[xe],n[xe])},[re](){return Ee(Pe(e.op),V(this[xe]))}},r=function(n){this[xe]=n};return r.prototype=t,function(n){return new r(n)}},We=LO({op:\"Success\",prop:\"value\",[lt](e){let t=e.getCont(Gt);return t?t[Gt](this[xe],e,this):e.yieldWith(this)}}),Nh={key:\"effect/Cause/StackTrace\"},Zb={key:\"effect/Cause/InterruptorStackTrace\"},Nt=LO({op:\"Failure\",prop:\"cause\",[lt](e){let t=this[xe],r=!1;e.cache.stackFrame&&(t=Gu(t,{mapUnsafe:new Map([[Nh.key,e.cache.stackFrame]])}),r=!0);let n=e.getCont(Tn),o=e._interruptedCause;if(o&&e.interruptible){let s=!1;for(;n&&e.interruptible;)s||=Jb in n,n=e.getCont(Tn);s&&(t=ls(t.reasons.filter(a=>a._tag!==\"Fail\"))),t=Gb(t,o),r=!0}return n?n[Tn](t,e,r?void 0:this):e.yieldWith(r?Nt(t):this)}}),ko=e=>Nt(Ju(e)),Jr=e=>Nt(Vb(e)),se=Zn({op:\"WithFiber\",[lt](e){return this[xe](e)}}),$O=Zn({op:\"WithFiberSucceed\",[lt](e){let t=this[xe](e),r=e.getCont(Gt);return r?r[Gt](t,e):e.yieldWith(We(t))}}),m6=(function(){class e extends globalThis.Error{}let t=vn({op:\"YieldableError\",[lt](){return ko(this)}});return delete t.toString,Object.assign(e.prototype,t),e})(),Ip=(function(){let e=Symbol.for(\"effect/Data/Error/plainArgs\");return class extends m6{constructor(r){super(r?.message,r?.cause?{cause:r.cause}:void 0),r&&(Mh(this,r),Object.defineProperty(this,e,{value:r,enumerable:!1}))}toJSON(){return{...this[e],...this}}}})(),Ys=e=>{class t extends Ip{_tag=e}return t.prototype.name=e,t},yp=\"~effect/Cause/NoSuchElementError\",Uh=e=>A(e,yp),vo=class extends Ys(\"NoSuchElementError\"){[yp]=yp;constructor(t){super({message:t})}},cc=\"~effect/Cause/Done\",Dh=e=>A(e,cc),KO={[cc]:cc,_tag:\"Done\",value:void 0},pc=e=>e===void 0?KO:{[cc]:cc,_tag:\"Done\",value:e},h6=ko(KO),BO=e=>e===void 0?h6:ko(pc(e));var Lh=e=>vn({op:e.label,[lt]:e.evaluate});var ye={};An(ye,{Do:()=>Q6,all:()=>$6,andThen:()=>M6,as:()=>n_,asVoid:()=>R6,bind:()=>Y6,bindTo:()=>V6,composeK:()=>D6,contains:()=>J6,containsWith:()=>c_,exists:()=>G6,filter:()=>hc,filterMap:()=>j6,firstSomeOf:()=>O6,flatMap:()=>dc,flatMapNullishOr:()=>F6,flatten:()=>mc,fromIterable:()=>w6,fromNullOr:()=>oE,fromNullishOr:()=>vp,fromUndefinedOr:()=>nE,gen:()=>X6,getFailure:()=>C6,getOrElse:()=>Tp,getOrNull:()=>Zh,getOrThrow:()=>sE,getOrThrowWith:()=>Yh,getOrUndefined:()=>ps,getSuccess:()=>A6,isNone:()=>ge,isOption:()=>tf,isSome:()=>Ce,let:()=>Z6,lift2:()=>W6,liftNullishOr:()=>_6,liftPredicate:()=>q6,liftThrowable:()=>Oo,makeCombinerFailFast:()=>u_,makeEquivalence:()=>H6,makeOrder:()=>z6,makeReducer:()=>e4,makeReducerFailFast:()=>t4,map:()=>Vt,match:()=>Zt,none:()=>v,orElse:()=>T6,orElseResult:()=>k6,orElseSome:()=>v6,partitionMap:()=>B6,product:()=>s_,productMany:()=>L6,reduceCompact:()=>K6,some:()=>_,tap:()=>o_,toArray:()=>i_,toRefinement:()=>I6,void:()=>P6,zipLeft:()=>U6,zipRight:()=>N6,zipWith:()=>a_});function jO(e){return{combine:e}}function Qb(e,t,r){return{combine:e,initialValue:t,combineAll:r??(n=>{let o=t;for(let s of n)o=e(o,s);return o})}}var Kt=e=>(t,r)=>t===r||e(t,r),x6=(e,t)=>e===t,Wa=()=>x6;function WO(e){return Kt((t,r)=>{if(t.length!==r.length)return!1;for(let n=0;n{if(t.length!==r.length)return!1;for(let n=0;nl(3,(t,r,n)=>e(t,o=>({...o,[r]:n(o)}))),Kh=e=>l(2,(t,r)=>e(t,n=>({[r]:n}))),Bh=(e,t)=>l(3,(r,n,o)=>t(r,s=>e(o(s),a=>({...s,[n]:a}))));var JO=\"~effect/Option\",GO={[JO]:{_A:e=>e},...kr,[Symbol.iterator](){return new Ha(this)}},g6=Object.defineProperty(Object.assign(Object.create(GO),{_tag:\"Some\",_op:\"Some\",[ne](e){return jh(e)&&Xb(e)&&Z(this.value,e.value)},[re](){return Ee(V(this._tag))(V(this.value))},toString(){return`some(${K(this.value)})`},toJSON(){return{_id:\"Option\",_tag:this._tag,value:qt(this.value)}}}),\"valueOrUndefined\",{get(){return this.value}}),y6=V(\"None\"),S6=Object.assign(Object.create(GO),{_tag:\"None\",_op:\"None\",valueOrUndefined:void 0,[ne](e){return jh(e)&&Hh(e)},[re](){return y6},toString(){return\"none()\"},toJSON(){return{_id:\"Option\",_tag:this._tag}}}),jh=e=>A(e,JO),Hh=e=>e._tag===\"None\",Xb=e=>e._tag===\"Some\",wp=Object.create(S6),VO=function(e){this.value=e};VO.prototype=g6;var Ap=e=>new VO(e);var YO=\"~effect/Result\",QO={[YO]:{_A:e=>e,_E:e=>e},...kr,[Symbol.iterator](){return new Ha(this)}},b6=Object.assign(Object.create(QO),{_tag:\"Success\",_op:\"Success\",[ne](e){return zh(e)&&Yu(e)&&Z(this.success,e.success)},[re](){return Ee(V(this._tag))(V(this.success))},toString(){return`success(${K(this.success)})`},toJSON(){return{_id:\"Result\",_tag:this._tag,value:qt(this.success)}}}),E6=Object.assign(Object.create(QO),{_tag:\"Failure\",_op:\"Failure\",[ne](e){return zh(e)&&Zu(e)&&Z(this.failure,e.failure)},[re](){return Ee(V(this._tag))(V(this.failure))},toString(){return`failure(${K(this.failure)})`},toJSON(){return{_id:\"Result\",_tag:this._tag,failure:qt(this.failure)}}}),zh=e=>A(e,YO),Zu=e=>e._tag===\"Failure\",Yu=e=>e._tag===\"Success\",XO=function(e){this.failure=e};XO.prototype=E6;var Wh=e=>new XO(e),e_=function(e){this.success=e};e_.prototype=b6;var qh=e=>new e_(e),eE=e=>Yu(e)?wp:Ap(e.failure),tE=e=>Zu(e)?wp:Ap(e.success);function qa(e){return(t,r)=>t===r?0:e(t,r)}var r_=qa((e,t)=>eglobalThis.Number.isNaN(e)&&globalThis.Number.isNaN(t)?0:globalThis.Number.isNaN(e)?-1:globalThis.Number.isNaN(t)?1:eeqa((r,n)=>e(t(r),t(n)))),Xu=rE(Qs,e=>e.getTime());var Jh=e=>l(2,(t,r)=>e(t,r)===-1),ef=e=>l(2,(t,r)=>e(t,r)===1),Gh=e=>l(2,(t,r)=>e(t,r)!==1),Vh=e=>l(2,(t,r)=>e(t,r)!==-1);var v=()=>wp,_=Ap,tf=jh,ge=Hh,Ce=Xb,Zt=l(2,(e,{onNone:t,onSome:r})=>ge(e)?t():r(e.value)),I6=e=>t=>Ce(e(t)),w6=e=>{for(let t of e)return _(t);return v()},A6=tE,C6=eE,Tp=l(2,(e,t)=>ge(e)?t():e.value),T6=l(2,(e,t)=>ge(e)?t():e),v6=l(2,(e,t)=>ge(e)?_(t()):e),k6=l(2,(e,t)=>ge(e)?Vt(t(),qh):Vt(e,Wh)),O6=e=>{let t=v();for(t of e)if(Ce(t))return t;return t},vp=e=>e==null?v():_(e),nE=e=>e===void 0?v():_(e),oE=e=>e===null?v():_(e),_6=e=>(...t)=>vp(e(...t)),Zh=Tp(Mb),ps=Tp(Vn),Oo=e=>(...t)=>{try{return _(e(...t))}catch{return v()}},Yh=l(2,(e,t)=>{if(Ce(e))return e.value;throw t()}),sE=Yh(()=>new Error(\"getOrThrow called on a None\")),Vt=l(2,(e,t)=>ge(e)?v():_(t(e.value))),n_=l(2,(e,t)=>Vt(e,()=>t)),R6=n_(void 0),P6=_(void 0);var dc=l(2,(e,t)=>ge(e)?v():t(e.value)),M6=l(2,(e,t)=>dc(e,r=>{let n=qr(t)?t(r):t;return tf(n)?n:_(n)})),F6=l(2,(e,t)=>ge(e)?v():vp(t(e.value))),mc=dc(D),N6=l(2,(e,t)=>dc(e,()=>t)),U6=l(2,(e,t)=>o_(e,()=>t)),D6=l(2,(e,t)=>r=>dc(e(r),t)),o_=l(2,(e,t)=>dc(e,r=>Vt(t(r),()=>r))),s_=l(2,(e,t)=>Ce(e)&&Ce(t)?_([e.value,t.value]):v()),L6=l(2,(e,t)=>{if(ge(e))return v();let r=[e.value];for(let n of t){if(ge(n))return v();r.push(n.value)}return _(r)}),$6=e=>{if(Symbol.iterator in e){let r=[];for(let n of e){if(ge(n))return v();r.push(n.value)}return _(r)}let t={};for(let r of Object.keys(e)){let n=e[r];if(ge(n))return v();B(t,r,n.value)}return _(t)},a_=l(3,(e,t,r)=>Vt(s_(e,t),([n,o])=>r(n,o))),K6=l(3,(e,t,r)=>{let n=t;for(let o of e)Ce(o)&&(n=r(n,o.value));return n}),i_=e=>ge(e)?[]:[e.value],B6=l(2,(e,t)=>{if(ge(e))return[v(),v()];let r=t(e.value);return Zu(r)?[v(),_(r.failure)]:[_(r.success),v()]}),j6=l(2,(e,t)=>{if(ge(e))return v();let r=t(e.value);return Yu(r)?_(r.success):v()}),hc=l(2,(e,t)=>ge(e)?v():t(e.value)?_(e.value):v()),H6=e=>Kt((t,r)=>ge(t)?ge(r):ge(r)?!1:e(t.value,r.value)),z6=e=>qa((t,r)=>Ce(t)?Ce(r)?e(t.value,r.value):1:-1),W6=e=>l(2,(t,r)=>a_(t,r,e)),q6=l(2,(e,t)=>t(e)?_(e):v()),c_=e=>l(2,(t,r)=>ge(t)?!1:e(t.value,r)),J6=c_(xp()),G6=l(2,(e,t)=>ge(e)?!1:t(e.value)),V6=Kh(Vt),Z6=$h(Vt);var Y6=Bh(Vt,dc),Q6=_({}),X6=(...e)=>{let r=(e.length===1?e[0]:e[1].bind(e[0]))(),n=r.next();for(;!n.done;){let o=n.value;if(ge(o))return o;n=r.next(o.value)}return _(n.value)};function e4(e){return Qb((t,r)=>ge(t)?r:ge(r)?t:_(e.combine(t.value,r.value)),v())}function u_(e){return jO((t,r)=>ge(t)||ge(r)?v():_(e.combine(t.value,r.value)))}function t4(e){let t=u_(e).combine,r=_(e.initialValue);return Qb(t,r,n=>{let o=r;for(let s of n)if(o=t(o,s),ge(o))return o;return o})}var f_=\"~effect/Context/Service\",Et=function(){function e(){}let t=e;Object.setPrototypeOf(t,r4);let r=(n,o)=>(t.key=n,o?.defaultValue&&(t[iE]=iE,t.defaultValue=o.defaultValue),o?.make&&(t.make=o.make),o?.fiberCached&&l_.add(n),t);return arguments.length>0?r(arguments[0],arguments[1]):r},r4={[f_]:f_,...Lh({label:\"Service\",evaluate(e){return We(Me(e.context,this))}}),toJSON(){return{_id:\"Service\",key:this.key}},of(e){return e},context(e){return xc(this,e)},use(e){return se(t=>e(Me(t.context,this)))},useSync(e){return se(t=>We(e(Me(t.context,this))))}},l_=new Set,iE=\"~effect/Context/Reference\",p_=\"~effect/Context\",n4=8,Qh=(e,t,r,n,o)=>{let s=Object.create(s4);return s.cacheRoot=e??s,s.base=t,s.overlay=r,s.depth=n,s._flat=void 0,s.baseHits=0,s.maxDepth=o,s},cE=(e,t)=>{t&&(cE(e,t.parent),e.set(t.key,t.value))},d_=e=>{if(e._flat)return e._flat;if(!e.overlay)return e._flat=e.base;let t=new Map(e.base);return cE(t,e.overlay),e._flat=t},o4=(e,t)=>{let r=new Map(e.mapUnsafe);return t(r),Qh(void 0,r,void 0,0,e.maxDepth)},Xh=Symbol(),uE=(e,t)=>{let r=e;for(let o=r.overlay;o;o=o.parent)if(o.key===t)return o.value;let n=r.base.get(t);return n===void 0&&!r.base.has(t)?Xh:(r.overlay&&++r.baseHits>=r.base.size&&r.baseHits>=n4&&(r.base=d_(r),r.overlay=void 0,r.depth=0),n)},Xs=(e,t)=>{let r=t?.maxDepth;return Qh(void 0,e,void 0,0,Number.isInteger(r)&&r>=0?r:8)},s4={get mapUnsafe(){return d_(this)},...kr,[p_]:{_Services:e=>e},toJSON(){return{_id:\"Context\",services:Array.from(this.mapUnsafe).map(([e,t])=>({key:e,value:t}))}},[ne](e){if(!kp(e))return!1;let t=this.mapUnsafe,r=e.mapUnsafe;if(t.size!==r.size)return!1;for(let[n,o]of t)if(!r.has(n)||!Z(o,r.get(n)))return!1;return!0},[re](){return Lt(this.mapUnsafe.size)}},m_=(e,t)=>e.cacheRoot===t.cacheRoot,kp=e=>A(e,p_);var h_=e=>!!e[iE],Pr=()=>a4,a4=Xs(new Map),xc=(e,t)=>Xs(new Map([[e.key,t]])),dr=l(3,(e,t,r)=>i4(e,t.key,r)),i4=(e,t,r)=>{let n=e,o=l_.has(t)?void 0:n.cacheRoot;if(n.depth>=n.maxDepth){let s=new Map(n._flat??n.base);return n._flat||cE(s,n.overlay),s.set(t,r),Qh(o,s,void 0,0,n.maxDepth)}return Qh(o,n.base,{key:t,value:r,parent:n.overlay},n.depth+1,n.maxDepth)};var ex=l(2,(e,t)=>Op(e,t.key)),Op=(e,t)=>{let r=uE(e,t);return r===Xh?void 0:r},ds=l(2,(e,t)=>{let r=uE(e,t.key);if(r===Xh){if(h_(t))return x_(t);throw c4(t)}return r}),Me=ds,aE=\"~effect/Context/defaultValue\",x_=e=>aE in e?e[aE]:e[aE]=e.defaultValue(),c4=e=>{let t=new Error(`Service not found${e.key?`: ${String(e.key)}`:\"\"}`);if(t.stack){let r=t.stack.split(`\n`);r.splice(1,3),t.stack=r.join(`\n`)}return t},tx=l(2,(e,t)=>{let r=uE(e,t.key);return r!==Xh?_(r):h_(t)?_(x_(t)):v()}),rx=l(2,(e,t)=>e.mapUnsafe.size===0?t:t.mapUnsafe.size===0?e:o4(e,r=>t.mapUnsafe.forEach((n,o)=>r.set(o,n)))),g_=(...e)=>{let t=new Map;for(let r=0;r{t.set(o,n)});return Xs(t)};var Te=Et;var fE=e=>e.length>0;var It=e=>e>0?Math.floor(e):0,Xn=e=>Math.max(1,It(e));var j=qh,q=Wh;var lE=e=>{if(qr(e))try{return j(e())}catch(t){return q(t)}else try{return j(e.try())}catch(t){return q(e.catch(t))}};var y_=zh,ae=Zu,rt=Yu;var rf=l(2,(e,t)=>ae(e)?q(t(e.failure)):e),sr=l(2,(e,t)=>rt(e)?j(t(e.success)):e),mr=l(2,(e,{onFailure:t,onSuccess:r})=>ae(e)?t(e.failure):r(e.success));var _p=l(2,(e,t)=>ae(e)?t(e.failure):e.success);var f4=l(2,(e,t)=>{if(rt(e))return e.success;throw t(e.failure)}),ms=f4(D);var Yt=l(2,(e,t)=>ae(e)?q(e.failure):t(e.success));var pE=e=>{if(Symbol.iterator in e){let r=[];for(let n of e){if(ae(n))return n;r.push(n.success)}return j(r)}let t={};for(let r of Object.keys(e)){let n=e[r];if(ae(n))return n;B(t,r,n.success)}return j(t)};var S_=WO;var l4=(e,t)=>{let r=t?.length!==void 0?Xn(t.length):1/0;return{[Symbol.iterator](){let n=0;return{next(){return nd4(l4(()=>e,{length:t}))),E_=e=>p4(e,1/0);var I_=e=>{let r=e[Symbol.iterator]().next();if(r.done)throw new Error(\"headUnsafe: empty iterable\");return r.value};var w_=l(2,(e,t)=>{let r=0;for(let n of e){let o=t(n,r);if(Th(o)){if(o)return _(n)}else if(Ce(o))return o;r++}return v()});var d4=e=>({[Symbol.iterator](){let t=e[Symbol.iterator](),r;function n(){for(;;){if(r===void 0){let s=t.next();if(s.done)return s;r=s.value[Symbol.iterator]()}let o=r.next();if(!o.done)return o;r=void 0}}return{next:n}}});var A_=l(2,(e,t)=>({[Symbol.iterator](){let r=e[Symbol.iterator](),n=0;return{next(){let o=r.next();for(;!o.done;){if(t(o.value,n++))return{done:!1,value:o.value};o=r.next()}return{done:!0,value:void 0}}}}}));var m4=l(2,(e,t)=>Object.hasOwn(e,t));var gc=l(2,(e,t)=>{let r={...e};for(let n of C_(e))B(r,n,t(e[n],n));return r});var C_=e=>Object.keys(e);var h4=e=>l(2,(t,r)=>{for(let n of C_(t))if(!m4(r,n)||!e(t[n],r[n]))return!1;return!0});var T_=e=>{let t=h4(e);return(r,n)=>t(r,n)&&t(n,r)};var nx=globalThis.Array;var ox=l(2,(e,t)=>{let r=Xn(e),n=new nx(r);for(let o=0;oe<=t?ox(t-e+1,r=>e+r):[e];var wt=e=>nx.isArray(e)?e:nx.from(e);var sx=l(2,(e,t)=>[...e,t]),mE=l(2,(e,t)=>wt(e).concat(wt(t)));var v_=nx.isArray;var Mr=fE,yt=fE;function nf(e){let t=Number(e);return String(t)===e&&Number.isInteger(t)&&t>=0&&t<2**32-1}function x4(e,t){return!Number.isFinite(e)||e<0||e>=t.length}var k_=l(2,(e,t)=>{let r=Math.floor(t);if(x4(r,e))throw new Error(`Index out of bounds: ${r}`);return e[r]});var ax=e=>e[e.length-1];var hE=w_;var g4=(e,t)=>{let r=V(t),n=e.get(r);if(n===void 0)return e.set(r,[t]),!0;for(let o of n)if(Z(o,t))return!1;return n.push(t),!0};var Qt=()=>[],Oe=e=>[e],kn=l(2,(e,t)=>e.map(t));var O_=e=>{let t=[];for(let r of e)Ce(r)&&t.push(r.value);return t};var ix=l(2,(e,t)=>{let r=wt(e),n=[];for(let o=0;o{let r=[],n=[],o=0;for(let s of e){let a=t(s,o++);rt(a)?r.push(a.success):n.push(a.failure)}return[r,n]});var __=Vu;var cx=e=>{let t=wt(e);if(t.length<2)return[...t];let r=new Map,n=[];for(let o of t)g4(r,o)&&n.push(o);return n};var fx=\"~effect/Duration\",ar=BigInt(0),U_=BigInt(1),y4=BigInt(2),S4=BigInt(10),R_=BigInt(24),ux=BigInt(60),lx=BigInt(1e3),ea=BigInt(1e6),sf=BigInt(1e9),px=BigInt(6e10),dx=BigInt(36e11),mx=BigInt(864e11),D_=BigInt(6048e11),L_=e=>BigInt(Math.sign(e)*Math.round(Math.abs(e))),yE=e=>Number.isInteger(e)?BigInt(e)*ea:L_(e*1e6),P_=e=>hr(Number.isFinite(e)?L_(e):e),$_=(e,t)=>{let r=Number(e);if(Number.isFinite(r))return r/t;let n=BigInt(t);return Number(e/n)+Number(e%n)/t},gE=(e,t)=>{let r=e.indexOf(\".\");if(r===-1)return BigInt(e)*t;let n=e[0]===\"-\",o=e.slice(r+1),s=S4**BigInt(o.length),a=(BigInt(e.slice(n?1:0,r))*s+BigInt(o))*t;return b4(n?-a:a,s)},b4=(e,t)=>{let r=e=t?U_:ar);return e{let r=Number(e)*t;if(!Number.isFinite(r))return hr(r);let n=gE(e,BigInt(t)*ea);return hr(Number.isInteger(r)&&BigInt(r)*ea===n?r:n)};var E4=/^(-?\\d+(?:\\.\\d+)?)\\s+(nanos?|micros?|millis?|seconds?|minutes?|hours?|days?|weeks?)$/,ct=e=>{switch(typeof e){case\"number\":return na(e);case\"bigint\":return On(e);case\"string\":{if(e===\"Infinity\")return ra;if(e===\"-Infinity\")return af;let t=E4.exec(e);if(!t)break;let[r,n,o]=t;if(o===\"nano\"||o===\"nanos\")return On(gE(n,U_));if(o===\"micro\"||o===\"micros\")return On(gE(n,lx));switch(o){case\"milli\":case\"millis\":return of(n,1);case\"second\":case\"seconds\":return of(n,1e3);case\"minute\":case\"minutes\":return of(n,6e4);case\"hour\":case\"hours\":return of(n,36e5);case\"day\":case\"days\":return of(n,864e5);case\"week\":case\"weeks\":return of(n,6048e5)}break}case\"object\":{if(e===null)break;if(fx in e)return e;if(Array.isArray(e)){if(e.length!==2||!e.every(lp))return F_(e);if(Number.isNaN(e[0])||Number.isNaN(e[1]))return ta;if(e[0]===-1/0||e[1]===-1/0)return af;if(e[0]===1/0||e[1]===1/0)return ra;let s=e[0]*1e9+e[1];return Number.isFinite(s)&&Number.isInteger(e[0])&&Number.isInteger(e[1])?hr(BigInt(e[0])*sf+BigInt(e[1])):P_(s)}let t=e,r=0;if(t.weeks&&(r+=t.weeks*6048e5),t.days&&(r+=t.days*864e5),t.hours&&(r+=t.hours*36e5),t.minutes&&(r+=t.minutes*6e4),t.seconds&&(r+=t.seconds*1e3),t.milliseconds&&(r+=t.milliseconds),!t.microseconds&&!t.nanoseconds){if(!Number.isFinite(r))return hr(r);let s=M_(t);return s===void 0||BigInt(r)*ea===s?hr(r):hr(s)}let n=r*1e6+(t.microseconds??0)*1e3+(t.nanoseconds??0),o=Number.isFinite(n)?M_(t):void 0;return o===void 0?P_(n):hr(o)}}return F_(e)},Ga=e=>!e||Number.isInteger(e),M_=e=>{if(!Ga(e.weeks)||!Ga(e.days)||!Ga(e.hours)||!Ga(e.minutes)||!Ga(e.seconds)||!Ga(e.milliseconds)||!Ga(e.microseconds)||!Ga(e.nanoseconds))return;let t=ar;return e.weeks&&(t+=BigInt(e.weeks)*D_),e.days&&(t+=BigInt(e.days)*mx),e.hours&&(t+=BigInt(e.hours)*dx),e.minutes&&(t+=BigInt(e.minutes)*px),e.seconds&&(t+=BigInt(e.seconds)*sf),e.milliseconds&&(t+=BigInt(e.milliseconds)*ea),e.microseconds&&(t+=BigInt(e.microseconds)*lx),e.nanoseconds&&(t+=BigInt(e.nanoseconds)),t},F_=e=>{throw new Error(`Invalid Input: ${e}`)},K_=Oo(ct),N_={_tag:\"Millis\",millis:0},I4={_tag:\"Infinity\"},w4={_tag:\"NegativeInfinity\"},A4={[fx]:fx,[re](){switch(this.value._tag){case\"Millis\":return V(yE(this.value.millis));case\"Nanos\":return V(this.value.nanos);default:return mp(this.value)}},[ne](e){return Fp(e)&&T4(this,e)},toString(){switch(this.value._tag){case\"Infinity\":return\"Infinity\";case\"NegativeInfinity\":return\"-Infinity\";case\"Nanos\":return`${this.value.nanos} nanos`;case\"Millis\":return`${this.value.millis} millis`}},toJSON(){switch(this.value._tag){case\"Millis\":return{_id:\"Duration\",_tag:\"Millis\",millis:this.value.millis};case\"Nanos\":return{_id:\"Duration\",_tag:\"Nanos\",nanos:String(this.value.nanos)};case\"Infinity\":return{_id:\"Duration\",_tag:\"Infinity\"};case\"NegativeInfinity\":return{_id:\"Duration\",_tag:\"NegativeInfinity\"}}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},hr=e=>{let t=Object.create(A4);return typeof e==\"number\"?isNaN(e)||e===0||Object.is(e,-0)?t.value=N_:Number.isFinite(e)?Number.isInteger(e)?t.value={_tag:\"Millis\",millis:e}:t.value={_tag:\"Nanos\",nanos:yE(e)}:t.value=e>0?I4:w4:e===ar?t.value=N_:t.value={_tag:\"Nanos\",nanos:e},t},Fp=e=>A(e,fx),sn=e=>e.value._tag!==\"Infinity\"&&e.value._tag!==\"NegativeInfinity\",Sc=e=>{switch(e.value._tag){case\"Millis\":return e.value.millis===0;case\"Nanos\":return e.value.nanos===ar;case\"Infinity\":case\"NegativeInfinity\":return!1}},hx=e=>{switch(e.value._tag){case\"Millis\":return e.value.millis<0;case\"Nanos\":return e.value.nanos{switch(e.value._tag){case\"Infinity\":case\"NegativeInfinity\":return ra;case\"Millis\":return e.value.millis<0?hr(-e.value.millis):e;case\"Nanos\":return e.value.nanoshr(e);var na=e=>hr(e),cf=e=>hr(e*1e3);var Nr=e=>j_(ct(e),{onMillis:D,onNanos:t=>$_(t,1e6),onInfinity:()=>1/0,onNegativeInfinity:()=>-1/0}),hs=e=>j_(ct(e),{onMillis:t=>t/1e3,onNanos:t=>$_(t,1e9),onInfinity:()=>1/0,onNegativeInfinity:()=>-1/0});var yc=e=>{let t=ct(e);switch(t.value._tag){case\"Infinity\":case\"NegativeInfinity\":throw new Error(\"Cannot convert infinite duration to nanos\");case\"Nanos\":return t.value.nanos;case\"Millis\":return yE(t.value.millis)}},B_=Oo(yc);var j_=l(2,(e,t)=>{switch(e.value._tag){case\"Millis\":return t.onMillis(e.value.millis);case\"Nanos\":return t.onNanos(e.value.nanos);case\"Infinity\":return t.onInfinity();case\"NegativeInfinity\":return(t.onNegativeInfinity??t.onInfinity)()}}),H_=l(3,(e,t,r)=>e.value._tag===\"Infinity\"||e.value._tag===\"NegativeInfinity\"||t.value._tag===\"Infinity\"||t.value._tag===\"NegativeInfinity\"?r.onInfinity(e,t):e.value._tag===\"Millis\"?t.value._tag===\"Millis\"?r.onMillis(e.value.millis,t.value.millis):r.onNanos(yc(e),t.value.nanos):r.onNanos(e.value.nanos,yc(t)));var z_=(e,t)=>H_(e,t,{onMillis:(r,n)=>r===n,onNanos:(r,n)=>r===n,onInfinity:(r,n)=>r.value._tag===n.value._tag});var W_=l(2,(e,t)=>H_(e,t,{onMillis:(r,n)=>hr(r-n),onNanos:(r,n)=>hr(r-n),onInfinity:(r,n)=>{let o=r.value._tag,s=n.value._tag;return o===\"Infinity\"?s===\"Infinity\"?ta:ra:o===\"NegativeInfinity\"?s===\"NegativeInfinity\"?ta:af:s===\"Infinity\"?af:ra}}));var T4=l(2,(e,t)=>z_(e,t)),v4=e=>{if(e.value._tag===\"Infinity\")return{days:1/0,hours:1/0,minutes:1/0,seconds:1/0,millis:1/0,nanos:1/0};if(e.value._tag===\"NegativeInfinity\")return{days:-1/0,hours:-1/0,minutes:-1/0,seconds:-1/0,millis:-1/0,nanos:-1/0};let t=yc(e),r=t{if(e.value._tag===\"Infinity\")return\"Infinity\";if(e.value._tag===\"NegativeInfinity\")return\"-Infinity\";if(Sc(e))return\"0\";if(hx(e))return\"-\"+SE(C4(e));let t=v4(e),r=[];return t.days!==0&&r.push(`${t.days}d`),t.hours!==0&&r.push(`${t.hours}h`),t.minutes!==0&&r.push(`${t.minutes}m`),t.seconds!==0&&r.push(`${t.seconds}s`),t.millis!==0&&r.push(`${t.millis}ms`),t.nanos!==0&&r.push(`${t.nanos}ns`),r.join(\" \")},q_=e=>{if(!sn(e))return v();let t=yc(e),r=t(e===void 0?ar:BigInt(e)*r)+(t===void 0?ar:BigInt(t.padEnd(9,\"0\"))*(r/sf)),J_=e=>{let t=k4.exec(e);if(t===null)return v();let[,r,n,o,s,a,i,c,u,f]=t;if(a!==void 0&&(i!==void 0||u!==void 0)||c!==void 0&&u!==void 0)return v();let p=Mp(n,void 0,D_)+Mp(o,void 0,mx)+Mp(s,a,dx)+Mp(i,c,px)+Mp(u,f,sf),d=r===\"-\"?-p:p,m=Number(d/ea);return _(d%ea===ar&&Number.isSafeInteger(m)?na(m):On(d))};var bE=l(2,(e,t)=>r=>{let n=e(r);if(ae(n))return q(r);let o=t(n.success);return ae(o)?q(r):o}),G_=e=>t=>{let r=e(t);return ae(r)?v():_(r.success)};var uf=Te(\"effect/Scheduler\",{fiberCached:!0,defaultValue:()=>new bc}),Z_=e=>{let t=!1;return Promise.resolve().then(()=>{t||e()}),()=>{t=!0}},O4=\"setImmediate\"in globalThis?e=>{let t=globalThis.setImmediate(e);return()=>globalThis.clearImmediate(t)}:e=>{let t=setTimeout(e,0);return()=>clearTimeout(t)},Y_=e=>{try{return O4(e)}catch{return Z_(e)}},EE=class{buckets=[];scheduleTask(t,r){let n=this.buckets,o=n.length,s,a=0;for(;ar);a++)s=n[a];s&&s[0]===r?s[1].push(t):a===o?n.push([r,[t]]):n.splice(a,0,[r,[t]])}drain(){let t=this.buckets;return this.buckets=[],t}},bc=class{executionMode;setImmediate;constructor(t=\"async\",r){this.executionMode=t,this.setImmediate=r??(t===\"sync\"?Z_:Y_)}shouldYield(t){return t.currentOpCount>=t.cache.maxOpsBeforeYield}makeDispatcher(){return new IE(this.setImmediate)}},IE=class{tasks=new EE;running=void 0;setImmediate;constructor(t=Y_){this.setImmediate=t}scheduleTask(t,r){this.tasks.scheduleTask(t,r),this.running===void 0&&(this.running=this.setImmediate(this.afterScheduled))}afterScheduled=()=>{this.running=void 0,this.runTasks()};runTasks(){let t=this.tasks.drain();for(let r=0;r0;)this.running!==void 0&&(this.running(),this.running=void 0),this.runTasks()}},Q_=Te(\"effect/Scheduler/MaxOpsBeforeYield\",{fiberCached:!0,defaultValue:()=>2048}),X_=Te(\"effect/Scheduler/PreventSchedulerYield\",{fiberCached:!0,defaultValue:()=>!1});var an={};An(an,{Class:()=>xx,Error:()=>Np,TaggedClass:()=>_4,TaggedError:()=>Ut,taggedEnum:()=>R4});var xx=class extends ja{constructor(e){super(),e&&Mh(this,e)}},_4=e=>class extends xx{_tag=e},R4=()=>new Proxy({},{get(e,t,r){return t===\"$is\"?Wt:t===\"$match\"?P4:n=>({...n,_tag:t})}});function P4(){if(arguments.length===1){let r=arguments[0];return function(n){return r[n._tag](n)}}let e=arguments[0];return arguments[1][e._tag](e)}var Np=Ip,Ut=Ys;var eR=\"~effect/encoding/EncodingError\",to=class extends Ut(\"EncodingError\"){[eR]=eR};var gx=e=>tR(typeof e==\"string\"?U4.encode(e):e),AE=e=>{switch(e){case 16:return F4();case 32:return N4();default:{let t=\"\";for(let r=e>>>3;r>0;r--)t+=M4();return t}}},ce=Uint8Array.from(\"0123456789abcdef\",e=>e.charCodeAt(0)),Ec=()=>Math.random()*4294967296>>>0,M4=()=>{let e=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15])},F4=()=>{let e=Ec(),t=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15],ce[t>>>28],ce[t>>>24&15],ce[t>>>20&15],ce[t>>>16&15],ce[t>>>12&15],ce[t>>>8&15],ce[t>>>4&15],ce[t&15])},N4=()=>{let e=Ec(),t=Ec(),r=Ec(),n=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15],ce[t>>>28],ce[t>>>24&15],ce[t>>>20&15],ce[t>>>16&15],ce[t>>>12&15],ce[t>>>8&15],ce[t>>>4&15],ce[t&15],ce[r>>>28],ce[r>>>24&15],ce[r>>>20&15],ce[r>>>16&15],ce[r>>>12&15],ce[r>>>8&15],ce[r>>>4&15],ce[r&15],ce[n>>>28],ce[n>>>24&15],ce[n>>>20&15],ce[n>>>16&15],ce[n>>>12&15],ce[n>>>8&15],ce[n>>>4&15],ce[n&15])},CE=e=>{let t=new TextEncoder().encode(e);if(t.length%2!==0)return q(new to({module:\"Hex\",kind:\"Decode\",input:e,message:`Length must be a multiple of 2, but is ${t.length}`}));try{let r=t.length/2,n=new Uint8Array(r);for(let o=0;osr(CE(e),t=>D4.decode(t)),U4=new TextEncoder,D4=new TextDecoder,L4=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,\"0\")),tR=e=>{let t=\"\";for(let r=0;r{if(48<=e&&e<=57)return e-48;if(97<=e&&e<=102)return e-97+10;if(65<=e&&e<=70)return e-65+10;throw new TypeError(\"Invalid input\")};var kE=\"effect/Tracer/ParentSpan\",Ic=class extends Et()(kE,{fiberCached:!0}){},$4=e=>e;var yx=Te(\"effect/Tracer/DisablePropagation\",{defaultValue:ap}),oR=Te(\"effect/Tracer/CurrentTraceLevel\",{defaultValue:()=>\"Info\"}),sR=Te(\"effect/Tracer/MinimumTraceLevel\",{defaultValue:()=>\"All\"}),OE=\"effect/Tracer\",_E=Te(OE,{fiberCached:!0,defaultValue:()=>RE}),RE=$4({span:e=>new vE(e)}),vE=class{_tag=\"Span\";sampled;name;parent;annotations;links;startTime;kind;status;_traceId=void 0;_spanId=void 0;_attributes=void 0;_events=void 0;constructor(t){this.name=t.name,this.parent=t.parent,this.annotations=t.annotations,this.links=t.links,this.startTime=t.startTime,this.kind=t.kind,this.sampled=t.sampled,this.status={_tag:\"Started\",startTime:t.startTime}}get traceId(){return this._traceId??=ps(this.parent)?.traceId??AE(32)}get spanId(){return this._spanId??=AE(16)}get attributes(){return this._attributes??=new Map}get events(){return this._events??=[]}end(t,r){this.status._tag!==\"Ended\"&&(this.status={_tag:\"Ended\",endTime:t,exit:r,startTime:this.status.startTime})}attribute(t,r){this.status._tag!==\"Ended\"&&this.attributes.set(t,r)}event(t,r,n){this.status._tag!==\"Ended\"&&this.events.push([t,r,n??{}])}addLinks(t){this.status._tag!==\"Ended\"&&this.links.push(...t)}};var iR=\"effect/Metric/FiberRuntimeMetrics\";var cR=Te(\"effect/ErrorReporter/CurrentErrorReporters\",{defaultValue:()=>new Set}),Up=Te(\"effect/References/CurrentStackFrame\",{fiberCached:!0,defaultValue:Vn}),Sx=Te(\"effect/References/TracerEnabled\",{fiberCached:!0,defaultValue:Cn}),wc=Te(\"effect/References/TracerTimingEnabled\",{defaultValue:Cn}),Dp=Te(\"effect/References/TracerSpanAnnotations\",{defaultValue:()=>({})}),Lp=Te(\"effect/References/TracerSpanLinks\",{defaultValue:()=>[]}),oa=Te(\"effect/References/CurrentLogAnnotations\",{defaultValue:()=>({})}),PE=Te(\"effect/References/CurrentLogLevel\",{fiberCached:!0,defaultValue:()=>\"Info\"}),ME=Te(\"effect/References/MinimumLogLevel\",{fiberCached:!0,defaultValue:()=>\"Info\"}),FE=Te(\"effect/References/UnhandledLogLevel\",{defaultValue:()=>\"Error\"}),bx=Te(\"effect/References/CurrentLogSpans\",{defaultValue:()=>[]});var Va=e=>{if(e?.captureStackTrace===!1)return e;if(e?.captureStackTrace!==void 0&&typeof e.captureStackTrace!=\"boolean\")return e;let t=Co();if(t===0&&e?.captureStackTrace!==!0)return{...e,captureStackTrace:!1};pr(3);let r=new Error;return pr(t),{...e,captureStackTrace:j4(()=>r.stack)}},NE=e=>t=>{let r;return()=>{if(r!==void 0)return r;let n=t();if(!n)return;let o=n.split(`\n`);if(o[e]!==void 0)return r=o[e].trim(),r}},j4=NE(3);var Ex=class extends Wu{constructor(t,r=bp){super(\"Interrupt\",r,\"Interrupted\"),this.fiberId=t}toString(){return`Interrupt(${this.fiberId})`}toJSON(){return{_tag:\"Interrupt\",fiberId:this.fiberId}}[ne](t){return Zs(t)&&this.fiberId===t.fiberId&&this.annotations===t.annotations}[re](){return Pe(`${this._tag}:${this.fiberId}`)}},xR=e=>new Ex(e),Ya=e=>new To([new Ex(e)]),kx=e=>e.reasons.some(fc),gR=e=>{let t=e.reasons.find(fc);return t?j(t):q(e)},mf=e=>{for(let t=0;te.reasons.some(lc),Ox=e=>hf(e)&&kx(e)?ls(e.reasons.map(t=>t._tag===\"Fail\"&&!Dh(t.error)?new ic(t.error,t.annotations):t)):e,cn=e=>hf(e)?q(Ox(e)):mf(e),SR=e=>{let t=e.reasons.find(lc);return t?j(t):q(e)},Gp=e=>{let t=e.reasons.find(lc);return t?j(t.defect):q(e)},_x=e=>e.reasons.some(Zs),bR=e=>{let t=e.reasons.find(Zs);return t?j(t):q(e)},Rx=e=>{let t;for(let r=0;r{let t=Rx(e);return ae(t)?H4:t.success},H4=new Set,Px=e=>e.reasons.length>0&&e.reasons.every(Zs),IR=e=>Xs(e.annotations),wR=e=>{let t=new Map;for(let r of e.reasons)if(r.annotations.size>0)for(let[n,o]of r.annotations)t.set(n,o);return Xs(t)},xf=l(2,(e,t)=>{let r=!1,n=e.reasons.map(o=>fc(o)?(r=!0,new ac(t(o.error),o.annotations)):o);return r?ls(n):e}),Mx=e=>{let t;for(let r of e.reasons){if(r._tag===\"Fail\")return r.error;r._tag===\"Die\"&&(t??=r)}return t!==void 0?t.defect:e.reasons.length>0?new globalThis.Error(\"All fibers interrupted without error\"):new globalThis.Error(\"Empty cause\")},qE=(e,t)=>{let r=[],n=[];if(e.reasons.length===0)return r;let o=Co();o!==0&&pr(1);try{for(let s of e.reasons){if(s._tag===\"Interrupt\"){n.push(s);continue}r.push(DE(s._tag===\"Die\"?s.defect:s.error,s.annotations,t))}if(r.length===0){let s=new Error(\"The fiber was interrupted by:\");s.name=\"InterruptCause\",s.stack=J4(s,n);let a=new globalThis.Error(\"All fibers interrupted without error\",{cause:s});a.name=\"InterruptError\",a.stack=`${a.name}: ${a.message}`,r.push(DE(a,n[0].annotations,t))}}finally{o!==0&&pr(o)}return r},DE=(e,t,r,n=new Set)=>{let o=typeof e,s;if(e&&o===\"object\"){n.add(e);let a=e.cause;if(s=new globalThis.Error(z4(e),{cause:a!==void 0&&!n.has(a)?DE(a,void 0,void 0,n):void 0}),typeof e.name==\"string\"&&(s.name=e.name),typeof e.stack==\"string\")s.stack=q4(e.stack,s,t);else{let i=`${s.name}: ${s.message}`;s.stack=t?LE(i,t):i}r?.includeCauseInStack&&(s.stack=CR(s));for(let i of Object.keys(e))i in s||(s[i]=e[i])}else{s=new globalThis.Error(e?o===\"string\"?e:nc(e):`Unknown error: ${e}`);let a=`${s.name}: ${s.message}`;s.stack=t?LE(a,t):a}return s},z4=e=>{if(typeof e.message==\"string\")return e.message;if(typeof e.toString==\"function\"&&e.toString!==Object.prototype.toString&&e.toString!==Array.prototype.toString)try{return e.toString()}catch{}return nc(e)},W4=/\\((.*)\\)/g,q4=(e,t,r)=>{let n=`${t.name}: ${t.message}`,o=(e.startsWith(n)?e.slice(n.length):e).split(`\n`),s=[n];for(let a=1;a{let r=t?.get(Nh.key);return r&&(e=`${e}\n${AR(r)}`),e},J4=(e,t)=>{let r=[`${e.name}: ${e.message}`];for(let n of t){let o=n.fiberId!==void 0?`#${n.fiberId}`:\"unknown\",s=n.annotations.get(Zb.key);r.push(` at fiber (${o})`),s&&r.push(AR(s))}return r.join(`\n`)},AR=e=>{let t=[],r=e,n=0;for(;r&&n<10;){let o=r.stack();if(o){let s=o.matchAll(W4),a=!1;for(let[,i]of s)a=!0,t.push(` at ${r.name} (${i})`);a||t.push(` at ${r.name} (${o.replace(/^at /,\"\")})`)}else t.push(` at ${r.name}`);r=r.parent,n++}return t.join(`\n`)},Fx=e=>qE(e).map(CR).join(`\n`),CR=e=>e.cause?`${e.stack} {\n${TR(e.cause,\" \")}\n}`:e.stack,TR=(e,t)=>{let r=e.stack.split(`\n`),n=`${t}[cause]: ${r[0]}`;for(let o=1,s=r.length;o{try{return globalThis.process?.getBuiltinModule?.(\"node:async_hooks\")?.AsyncResource}catch{return}})(),vR=()=>uR===void 0?void 0:new uR(\"effect/Fiber\"),sa=()=>globalThis[rc],ff=class{constructor(t,r=!0){this.setContext(t),this.id=++V4.id,this.currentOpCount=0,this.interruptible=r,this._stack=[],this._observers=void 0,this._exit=void 0,this._children=void 0,this._interruptedCause=void 0,this._yielded=void 0,this._running=!1,this._deferredInterrupt=!1,this._parent=void 0,this._asyncContext=void 0,this.cache.runtimeMetrics?.recordFiberStart(this.context)}get[JE](){return G4}get currentDispatcher(){return this._dispatcher??=this.cache.scheduler.makeDispatcher()}getRef(t){return Me(this.context,t)}addObserver(t){return this._exit?(t(this._exit),zr):(this._observers===void 0?this._observers=[t]:this._observers.push(t),()=>this.removeObserver(t))}removeObserver(t){if(this._exit||this._observers===void 0)return;let r=this._observers.indexOf(t);r>=0&&this._observers.splice(r,1)}interruptUnsafe(t,r){if(this._exit)return;let n=Ya(t);this.cache.stackFrame&&(n=Gu(n,xc(Nh,this.cache.stackFrame))),r&&(n=Gu(n,r)),this._interruptedCause=this._interruptedCause?Gb(this._interruptedCause,n):n,this.interruptible&&(this._running?this._deferredInterrupt=!0:this.evaluate(Le(this._interruptedCause)))}pollUnsafe(){return this._exit}evaluate(t){if(this._exit)return;if(this._asyncContext!==void 0){let s=this._asyncContext;this._asyncContext=void 0;try{return s.runInAsyncScope(this.evaluate,this,t)}finally{s.emitDestroy()}}else if(this._yielded!==void 0){let s=this._yielded;this._yielded=void 0,s()}let r=this.runLoop(t);if(r===uc){this._asyncContext=vR();return}let n=$E.interruptChildren&&$E.interruptChildren(this);if(n!==void 0)return this.evaluate(oe(n,()=>r));if(this._exit=r,this.cache.runtimeMetrics?.recordFiberEnd(this.context,this._exit),this._parent&&(this._parent._children?.delete(this),this._parent=void 0),this._observers!==void 0){let s=this._observers;this._observers=void 0;for(let a=0;ai)}if(s=a.tracerContext?a.tracerContext(s,this):s[lt](this),s===uc){let i=this._yielded;if(oc in i)return this._deferredInterrupt=!1,this._yielded=void 0,i;if(this._deferredInterrupt){this._yielded=void 0,i();continue}return uc}}catch(a){if(!A(s,lt))return Jr(`Fiber.runLoop: Not a valid effect: ${String(s)}`);s=Jr(a)}}finally{this._running=n,globalThis[rc]=r}}getCont(t){if(this._deferredInterrupt)return this._deferredInterrupt=!1,Y4;for(;;){let r=this._stack.pop();if(!r)return;let n=r[sc];if(n!==void 0){let o=n.call(r,this);if(o)return o[t]=o,o}if(r[t])return r}}succeedWith(t){if((++this.currentOpCount&Q4-1)===0)return We(t);let r=this.getCont(Gt);return r?r[Gt](t,this):this.yieldWith(We(t))}yieldWith(t){return this._yielded=t,uc}children(){return this._children??=new Set}pipe(){return te(this,arguments)}setContext(t){let r=this.context;if(this.context=t,r!==void 0&&m_(r,t))return;let n=t.cacheRoot,o=n._fiberCache??=Z4(t);this.cache?.scheduler!==o.scheduler&&(this._dispatcher=void 0),this.cache=o}get currentSpanLocal(){let t=this.cache.span;return t?._tag===\"Span\"?t:void 0}},Z4=e=>{let t=Op(e,OE);return{scheduler:Me(e,uf),tracer:t,tracerContext:t?t.context:void 0,tracerEnabled:Me(e,Sx),span:Op(e,kE),logLevel:Me(e,PE),minimumLogLevel:Me(e,ME),stackFrame:Me(e,Up),runtimeMetrics:Op(e,iR),maxOpsBeforeYield:Me(e,Q_),preventYield:Me(e,X_)}},Y4={[Gt](e,t){return Le(t._interruptedCause)},[Tn](e,t){return Le(t._interruptedCause)}},Q4=32,$E={interruptChildren:void 0},Nx=e=>{if(!e.cache.stackFrame)return;let t=new Map;return t.set(Zb.key,e.cache.stackFrame),Xs(t)},X4=e=>{if(!(e._children===void 0||e._children.size===0))return lf(e._children)},GE=e=>{let t=e;return t._exit?z(t._exit):Dt(r=>t._exit?r(z(t._exit)):X(e.addObserver(n=>r(z(n)))))},Ux=e=>Dt(t=>{let r=e[Symbol.iterator](),n=[],o;function s(){let a=r.next();for(;!a.done;){if(a.value._exit){n.push(a.value._exit),a=r.next();continue}o=a.value.addObserver(i=>{n.push(i),s()});return}t(z(n))}return s(),X(()=>o?.())}),Ix=e=>{let t=e;return t._exit?t._exit:Dt(r=>t._exit?r(t._exit):X(e.addObserver(r)))},kR=e=>Dt(t=>{let r=Array.from(e);if(r.length===0)return t(z(Qt()));let n=new Array(r.length),o=Qt(),s=()=>{for(let c=0;c{if(a++,f._tag===\"Failure\")return i=!0,s(),t(f);n[c]=f.value,a===r.length&&t(z(n))};o.push(u),r[c].addObserver(u)}return X(()=>{i=!0,s()})}),Dx=e=>se(t=>OR(e,t.id)),OR=l(e=>A(e[0],JE),(e,t,r)=>se(n=>{let o=Nx(n);return o=o&&r?rx(o,r):o??r,e.interruptUnsafe(t,o),Zp(GE(e))})),lf=e=>se(t=>{let r=Nx(t),n=Qt();for(let o of e)o.interruptUnsafe(t.id,r),n.push(o);return Zp(Ux(n))});var z=We,Le=Nt,dt=ko,X=Zn({op:\"Sync\",[lt](e){let t=this[xe],r=t(),n=e.getCont(Gt);return n?n[Gt](r,e):e.yieldWith(We(r))}}),be=Zn({op:\"Suspend\",[lt](e){let t=this[xe];return t()}}),VE=l(e=>e.length>=2||tf(e[0]),(e,t)=>ge(e)?t?QE(t):dt(new vo(\"Effect.fromOption: Option.none\")):z(e.value)),gf=mr({onFailure:dt,onSuccess:z}),_R=e=>e==null?dt(new vo):z(e),ZE=Zn({op:\"Yield\",[lt](e){let t=!1;return e.currentDispatcher.scheduleTask(()=>{t||e.evaluate(Ur)},this[xe]??0),e.yieldWith(()=>{t=!0})}}),yf=ZE(0),YE=e=>z(_(e)),Tc=z(v()),RR=e=>ge(e)?Tc:Fe(e.value,_),PR=e=>be(()=>Le(e())),Qa=e=>Jr(e),QE=e=>be(()=>dt(e())),Se=z(void 0);var MR=e=>{let t=typeof e==\"function\"?e:e.try,r=typeof e==\"function\"?n=>new df(n,\"An error occurred in Effect.try\"):e.catch;return be(()=>{try{return z(t())}catch(n){return dt(r(n))}})};var XE=e=>eI(function(t,r){e(r).then(n=>t(z(n)),n=>t(Qa(n)))},e.length!==0),FR=e=>{let t=typeof e==\"function\"?e:e.try,r=typeof e==\"function\"?n=>new df(n,\"An error occurred in Effect.tryPromise\"):e.catch;return eI(function(n,o){let s=a=>be(()=>{try{return dt(za(()=>r(a)))}catch(i){return Qa(i)}});try{t(o).then(a=>n(z(a)),a=>n(s(a)))}catch(a){n(s(a))}},t.length!==0)},e3=e=>se(t=>e(t.id)),NR=se(z),UR=e3(z),eI=(function(){let e=vn({op:\"Async\",[lt](r){let n=!1,o=!1,s=this.withSignal?new AbortController:void 0,a=this.register.call(r.cache.scheduler,i=>{n||(n=!0,o?r.evaluate(i):o=i)},s?.signal);return o!==!1?o:(o=!0,r.yieldWith(()=>{n=!0}),s===void 0&&a===void 0?uc:(r._stack.push(t3(()=>(n=!0,s?.abort(),a??Ur))),uc))}}),t=function(r,n){this.register=r,this.withSignal=n};return t.prototype=e,function(r,n){return new t(r,n)}})(),t3=Zn({op:\"AsyncFinalizer\",[sc](e){e.interruptible&&(e.interruptible=!1,e._stack.push(od))},[Tn](e,t){return _x(e)?oe(jP(Nt(e),this[xe]()),()=>Le(e)):Le(e)}}),Dt=e=>eI(e,e.length>=2),Lx=Dt(zr),DR=(...e)=>{if(e.length===1){let n=e[0];return be(()=>Cc(n()))}let[t,r]=e;return be(()=>Cc(r.call(t.self)))},tI=(e,t)=>typeof e==\"function\"?e:t.shift().bind(e.self),rI=(e,...t)=>{let r=tI(e,t),n=t.length===0?function(){return be(()=>Cc(r.apply(this,arguments)))}:function(){let o=be(()=>Cc(r.apply(this,arguments)));for(let s=0;sObject.defineProperty(t,\"length\",{value:e,configurable:!0}),fR=NE(2),LR=function(){let e=typeof arguments[0]==\"string\",t=e?arguments[0]:\"Effect.fn\",r=e?arguments[1]:void 0,n=Co(),o;return n!==0&&(pr(2),o=new globalThis.Error,pr(n)),e?(s,...a)=>lR(t,s,o,a,e,r):lR(t,arguments[0],o,Array.prototype.slice.call(arguments,1),e,r)},lR=(e,t,r,n,o,s)=>{let a=tI(t,n),i=`${e} (definition)`,c=r?fR(()=>r.stack):Vn,u=f=>p=>({name:e,stack:f?fR(()=>f.stack):Vn,parent:{name:i,stack:c,parent:p}});return nI(a.length,function(...f){let p=be(()=>{let h=a.apply(this,arguments);return de(h)?h:Cc(h)});for(let h=0;hzE(p,h)):p,Up,u(m))})},$R=(e,...t)=>{let r=tI(e,t);return nI(r.length,t.length===0?function(){return pR(()=>r.apply(this,arguments))}:function(){let n=pR(()=>r.apply(this,arguments));for(let o of t)n=o(n,...arguments);return n})},pR=e=>{try{let t=e(),r;for(;;){let n=t.next(r);if(n.done)return z(n.value);let o=n.value;if(o&&o._tag===\"Success\"){r=o.value;continue}else{if(o&&o._tag===\"Failure\")return n.value;{let s=!0;return be(()=>s?(s=!1,oe(n.value,a=>Cc(t,a))):be(()=>Cc(e())))}}}}catch(t){return Qa(t)}},Cc=(function(){let e=vn({op:\"Iterator\",[Gt](r,n){let o=this.iterator;for(;;){let s=o.next(r);if(s.done)return z(s.value);if(Ve(s.value)){if(s.value._tag===\"Failure\")return s.value}else return n._stack.push(this),s.value;r=s.value.value}},[lt](r){return this[Gt](this.initial,r)}}),t=function(r,n){this.iterator=r,this.initial=n};return t.prototype=e,function(r,n){return new t(r,n)}})(),Rn=l(2,(e,t)=>new aa(e,oI,z(t))),$x=function(e){return e._stack.push(this),this[xe]},r3=vn({op:\"OnSuccess\",[lt]:$x}),aa=function(e,t,r){this[xe]=e,this[Gt]=t,this.payload=r};aa.prototype=r3;var oI=function(){return this.payload},KR=function(e,t){return t.succeedWith(this.payload)},Kx=(()=>{let e=Co();if(e===0)return!1;let t=\"~effect/Effect/stackProbe\",r={[t]:function(){return new Error}};pr(1);let n=r[t]();return pr(e),n.stack?.includes(\"[as \"+t+\"]\")===!0})(),n3=function(e,t){let r=this.payload;return t.succeedWith(Kx?r(e):za(()=>r(e)))},BR=function(e){let t=this.payload;return t(e)},o3=function(e){let t=this.payload;return new aa(t(e),KR,e)},s3=function(e){return new aa(this.payload,KR,e)},Sf=e=>Fe(e,_),jR=e=>ed(e,{onFailure:z,onSuccess:dt}),xs=l(2,(e,t)=>new aa(e,de(t)?oI:BR,t)),Vp=l(2,(e,t)=>new aa(e,de(t)?s3:o3,t)),Zp=e=>new aa(e,oI,Ur),HR=e=>un(e,dt),sI=(e,t)=>se(r=>{let n=new Set;return oi(r,()=>n.size===0?void 0:lf(n)),Dt(o=>{let s=wt(e),a=s.length,i=0,c=!1,u=[],f=(p,d,m)=>{if(i++,p._tag===\"Failure\"){u.push(...p.cause.reasons),i>=a&&o(Le(Ox(ls(u))));return}let h=!c;c=!0,o(p),h&&t?.onWinner&&t.onWinner({fiber:d,index:m,parentFiber:r})};for(let p=0;p{n.delete(d),f(m,d,p)}),c)break}})}),aI=(e,t)=>se(r=>{let n=new Set;return oi(r,()=>n.size===0?void 0:lf(n)),Dt(o=>{let s=!1,a=0;for(let i of e){if(s)break;let c=a++,u=_c(r,i,!0,!0,!1);n.add(u),u.addObserver(f=>{n.delete(u);let p=!s;s=!0,o(f),p&&t?.onWinner&&t.onWinner({fiber:u,index:c,parentFiber:r})})}})}),zR=l(e=>de(e[1]),(e,t,r)=>sI([e,t],r)),iI=l(e=>de(e[1]),(e,t,r)=>aI([e,t],r)),oe=l(2,(e,t)=>new aa(e,BR,t)),WR=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?t.onSuccess(e.value):t.onFailure(e.cause):_o(e,t)),Ve=e=>e[oc]!==void 0,qR=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?t(e.value):e:oe(e,t)),JR=e=>oe(e,D),Fe=l(2,(e,t)=>new aa(e,n3,t)),GR=l(2,(e,t)=>Ve(e)?lI(e,t):Fe(e,t)),VR=l(2,(e,t)=>Ve(e)?pI(e,t):EI(e,t)),ZR=l(2,(e,t)=>Ve(e)?dI(e,t):II(e,t)),YR=l(2,(e,t)=>{if(Ve(e)){if(e._tag===\"Success\")return e;let r=cn(e.cause);return ae(r)?Nt(r.failure):t(r.success)}return ti(e,t)}),bf=e=>Nt(Ya(e)),Xa=e=>e._tag===\"Success\",QR=e=>e._tag===\"Success\"?j(e):q(e),XR=e=>e._tag===\"Success\"?j(e.value):q(e),cI=e=>e._tag===\"Failure\",eP=e=>e._tag===\"Failure\"?j(e):q(e),Yp=e=>e._tag===\"Failure\"?j(e.cause):q(e),uI=bE(Yp,mf),tP=bE(Yp,Gp),fI=e=>e._tag===\"Failure\"&&_x(e.cause),rP=e=>e._tag===\"Failure\"&&hf(e.cause),nP=e=>e._tag===\"Failure\"&&kx(e.cause),Ur=We(void 0),lI=l(2,(e,t)=>e._tag===\"Success\"?We(t(e.value)):e),pI=l(2,(e,t)=>e._tag===\"Success\"?e:Nt(xf(e.cause,t))),dI=l(2,(e,t)=>e._tag===\"Success\"?We(t.onSuccess(e.value)):Nt(xf(e.cause,t.onFailure))),a3=l(2,(e,t)=>Xa(e)?We(t):e),oP=l(2,(e,t)=>Xa(e)?t:e),sP=l(2,(e,t)=>Xa(e)?t.onSuccess(e.value):t.onFailure(e.cause)),aP=a3(void 0),mI=e=>{let t=[];for(let r of e)r._tag===\"Failure\"&&t.push(...r.cause.reasons);return t.length===0?Ur:Nt(ls(t))},iP=e=>Xa(e)?_(e.value):v(),cP=e=>cI(e)?_(e.cause):v(),uP=e=>{let t=uI(e);return ae(t)?v():_(t.success)},fP=e=>e,lP=e=>se(t=>z(tx(t.context,e))),i3=e=>se(t=>VE(tx(t.context,e))),Ef=l(2,(e,t)=>se(r=>{let n=r.context,o=t(n);return n===o||(r.setContext(o),oi(r,()=>{r.setContext(n)})),e})),ia=l(3,(e,t,r)=>Ef(e,n=>{let o=ds(n,t),s=r(o);return o===s?n:dr(n,t,s)})),pP=(e,t,r)=>Oc(se(n=>{let o=ds(n.context,e),s=t(o);return n.setContext(dr(n.context,e,s)),ni(ds(n.context,ri),a=>{let i=tx(n.context,e);if(ge(i))return Se;let c=i.value,u;if(r?.reset===void 0){if(c!==s)return Se;u=o}else u=r.reset(o,s,c);return n.setContext(dr(n.context,e,u)),Se})})),hI=()=>c3,c3=se(e=>z(e.context)),ei=e=>se(t=>e(t.context)),dP=l(2,(e,t)=>Ef(e,gt(t))),Pn=l(2,(e,t)=>Ve(e)?e:Ef(e,rx(t))),Lr=function(){return arguments.length===1?l(2,(e,t)=>dR(e,arguments[0],t)):l(3,(e,t,r)=>dR(e,t,r)).apply(this,arguments)},dR=(e,t,r)=>Ef(e,dr(t,r)),Bx=l(3,(e,t,r)=>oe(r,n=>Lr(e,t,n))),mP=l(e=>de(e[1]),(e,t,r)=>xI(e,t,(n,o)=>[n,o],r)),xI=l(e=>de(e[1]),(e,t,r,n)=>n?.concurrent?Fe(sd([e,t],{concurrency:2}),([o,s])=>r(o,s)):oe(e,o=>Fe(t,s=>r(o,s)))),hP=l(e=>de(e[0]),(e,t,r)=>DI(e,t,r?n=>dt(r(n)):()=>dt(new vo))),xP=l(2,(e,t)=>oe(t,r=>r?Sf(e):Tc)),gI=l(2,(e,t)=>Array.from({length:t},()=>e)),gP=l(e=>de(e[0]),(e,t,r)=>sd(gI(e,t),r)),yP=l(e=>de(e[0]),(e,t)=>si({while:Cn,body:gt(t?.disableYield?e:oe(e,r=>yf)),step:zr})),un=l(2,(e,t)=>new SP(e,t.length!==1?r=>t(r):t)),u3=vn({op:\"OnFailure\",[lt]:$x}),SP=function(e,t){this[xe]=e,this[Tn]=t};SP.prototype=u3;var yI=l(3,(e,t,r)=>un(e,n=>t(n)?r(n):Le(n))),ca=l(3,(e,t,r)=>un(e,n=>{let o=t(n);return ae(o)?Le(o.failure):r(o.success,n)})),ti=l(2,(e,t)=>ca(e,cn,r=>t(r))),bP=e=>ed(e,{onFailure:t=>Uh(t)?Tc:dt(t),onSuccess:YE}),EP=l(2,(e,t)=>ca(e,Gp,t)),IP=l(2,(e,t)=>un(e,r=>xs(t(r),Le(r)))),wP=l(3,(e,t,r)=>yI(e,t,n=>xs(r(n),Le(n)))),jx=l(3,(e,t,r)=>un(e,n=>{let o=t(n);return ae(o)?Le(n):xs(r(o.success,n),Le(n))})),SI=l(2,(e,t)=>jx(e,mf,r=>t(r))),AP=l(3,(e,t,r)=>{let n=Array.isArray(t)?o=>A(o,\"_tag\")&&t.includes(o._tag):Wt(t);return SI(e,o=>n(o)?r(o):Se)}),CP=l(2,(e,t)=>jx(e,Gp,r=>t(r))),Qp=l(e=>de(e[0]),(e,t,r,n)=>un(e,o=>{let s=cn(o);return ae(s)?Le(s.failure):t(s.success)?r(s.success):n?n(s.success):Le(o)})),Hx=l(e=>de(e[0]),(e,t,r,n)=>un(e,o=>{let s=cn(o);if(ae(s))return Le(s.failure);let a=t(s.success);return ae(a)?n?n(a.failure):Le(o):r(a.success)})),bI=l(e=>de(e[0]),(e,t,r,n)=>{let o=Array.isArray(t)?s=>A(s,\"_tag\")&&t.includes(s._tag):Wt(t);return Qp(e,o,r,n)}),TP=l(e=>de(e[0]),(e,t,r)=>{let n;return Hx(e,o=>(n??=Object.keys(t),A(o,\"_tag\")&&Wr(o._tag)&&n.includes(o._tag)?j(o):q(o)),o=>t[o._tag](o),r)}),vP=l(e=>de(e[0]),(e,t,r,n,o)=>Qp(e,s=>Wt(s,t)&&A(s,\"reason\")&&(o!==void 0||Wt(s.reason,r)),s=>{let a=s.reason;return Wt(a,r)?n(a,s):o?o(a,s):dt(s)})),kP=l(e=>de(e[0]),(e,t,r,n)=>{let o;return Qp(e,s=>Wt(s,t)&&A(s,\"reason\")&&A(s.reason,\"_tag\")&&Wr(s.reason._tag)&&(n!==void 0||(o??=Object.keys(r)).includes(s.reason._tag)),s=>{let a=s.reason;return o??=Object.keys(r),o.includes(a._tag)?r[a._tag](a,s):n?n(a,s):dt(s)})}),OP=l(2,(e,t)=>Hx(e,r=>Wt(r,t)&&A(r,\"reason\")?j(r.reason):q(r),dt)),EI=l(2,(e,t)=>un(e,r=>Le(xf(r,t)))),II=l(2,(e,t)=>_o(e,{onFailure:r=>Le(xf(r,t.onFailure)),onSuccess:r=>X(()=>t.onSuccess(r))})),wI=e=>ti(e,Qa),_P=l(2,(e,t)=>ti(e,r=>X(()=>t(r)))),RP=e=>be(()=>{let t=e[Symbol.iterator](),r=t.next();if(r.done)return Qa(new Error(\"Received an empty collection of effects\"));function n(o){let s=t.next();return s.done?o.value:ti(o.value,a=>n(s))}return n(r)}),AI=e=>ti(e,t=>oe(yf,()=>AI(e))),Xp=e=>e===\"Unhandled\"?(...t)=>se(r=>{let n=r.getRef(FE);return n===void 0?Se:Ro(n)(...t)}):Ro(e===!0?void 0:e),PP=l(e=>de(e[0]),(e,t)=>{if(!t?.log)return ed(e,{onFailure:n=>Se,onSuccess:n=>Se});let r=Xp(t.log);return _o(e,{onFailure(n){let o=cn(n);return ae(o)?Le(o.failure):t.message===void 0?r(n):r(t.message,n)},onSuccess:n=>Se})}),zx=l(e=>de(e[0]),(e,t)=>{if(!t?.log)return _o(e,{onFailure:n=>Se,onSuccess:n=>Se});let r=Xp(t.log);return _o(e,{onFailure:n=>t.message===void 0?r(n):r(t.message,n),onSuccess:n=>Se})}),MP=e=>Wx(e,{onFailure:v,onSuccess:_}),Za=e=>td(e,{onFailure:q,onSuccess:j}),_o=l(2,(e,t)=>new FP(e,t.onSuccess.length!==1?r=>t.onSuccess(r):t.onSuccess,t.onFailure.length!==1?r=>t.onFailure(r):t.onFailure)),f3=vn({op:\"OnSuccessAndFailure\",[lt]:$x}),FP=function(e,t,r){this[xe]=e,this[Gt]=t,this[Tn]=r};FP.prototype=f3;var l3=function(e,t){let r=this.payload;return t.succeedWith(Kx?r.onSuccess(e):za(()=>r.onSuccess(e)))},NP=(e,t)=>{let r=vn({op:e,[lt]:$x,[Gt]:l3,[Tn]:t}),n=function(o,s){this[xe]=o,this.payload=s};return n.prototype=r,n},p3=NP(\"Match\",function(e,t){let r=cn(e);if(ae(r))return Le(r.failure);let n=this.payload;return t.succeedWith(Kx?n.onFailure(r.success):za(()=>n.onFailure(r.success)))}),d3=NP(\"MatchCause\",function(e,t){let r=this.payload;return t.succeedWith(Kx?r.onFailure(e):za(()=>r.onFailure(e)))}),CI=l(2,(e,t)=>new d3(e,t)),ed=l(2,(e,t)=>_o(e,{onFailure:r=>{let n=cn(r);return ae(n)?Le(n.failure):t.onFailure(n.success)},onSuccess:t.onSuccess})),Wx=l(2,(e,t)=>new p3(e,t)),td=l(2,(e,t)=>{if(Ve(e)){if(e._tag===\"Success\")return We(t.onSuccess(e.value));let r=cn(e.cause);return ae(r)?Nt(r.failure):We(t.onFailure(r.success))}return Wx(e,t)}),UP=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?We(t.onSuccess(e.value)):We(t.onFailure(e.cause)):CI(e,t)),rd=e=>Ve(e)?We(e):m3(e),m3=Zn({op:\"Exit\",[lt](e){return e._stack.push(this),this[xe]},[Gt](e,t,r){return t.succeedWith(r??We(e))},[Tn](e,t,r){return t.succeedWith(r??Nt(e))}}),DP=td({onFailure:()=>!0,onSuccess:()=>!1}),LP=td({onFailure:()=>!1,onSuccess:()=>!0}),$P=l(2,(e,t)=>xs(wf(t),e)),TI=l(2,(e,t)=>oe(vI(e,t.duration),r=>ge(r)?t.orElse():z(r.value))),h3=e=>new jp(`Operation timed out after '${SE(e)}'`),KP=l(2,(e,t)=>{let r=ct(t);return TI(e,{duration:r,orElse:()=>dt(h3(r))})}),vI=l(2,(e,t)=>iI(Sf(e),Rn(wf(t),v()))),BP=e=>Mo(t=>{let r=t.monotonicTimeNanosUnsafe();return Fe(e,n=>[On(t.monotonicTimeNanosUnsafe()-r),n])}),KE=\"~effect/Scope\",BE=\"~effect/Scope/Closeable\",ri=Et(\"effect/Scope\"),kI=(e,t)=>se(r=>(S3(r),qx(e,t)??Se)),qx=(e,t)=>{let r=e.state;if(r._tag===\"Closed\"||(e.state={_tag:\"Closed\",exit:t},e.parent!==void 0&&Ax(e.parent,e),r._tag===\"Empty\"))return;if(r.finalizer!==void 0)return wx(r.finalizer,t);let n=r.finalizers;return n.size===1?wx(n.values().next().value,t):x3(e,n,t)},wx=(e,t)=>{try{return e(t)}catch(r){return Jr(r)}},jP=(e,t)=>Xa(e)?t:un(t,r=>Le(Ox(Ep(e.cause,r)))),x3=rI(function*(e,t,r){let n=[],o=[],s=Array.from(t),a=sa();for(let i=s.length-1;i>=0;i--){let[c,u]=s[i];e.strategy===\"sequential\"?n.push(yield*rd(wx(u,r))):c!==a&&o.push(_c(a,wx(u,r),!0,!0,\"inherit\"))}return o.length>0&&(n=yield*Ux(o)),yield*mI(n)});var HP=(e,t)=>{let r=zP(t,e);return e.state._tag===\"Closed\"?(r.state=e.state,r):(If(e,r,n=>kI(r,n)),r)},ni=(e,t)=>be(()=>e.state._tag===\"Closed\"?t(e.state.exit):(If(e,{},t),Se)),Jx=(e,t)=>ni(e,gt(t)),If=(e,t,r)=>{if(e.state._tag===\"Empty\")e.state={_tag:\"Open\",finalizerKey:t,finalizer:r,finalizers:void 0};else if(e.state._tag===\"Open\"){let n=e.state;n.finalizer!==void 0&&(n.finalizers=new Map([[n.finalizerKey,n.finalizer]]),n.finalizerKey=void 0,n.finalizer=void 0),n.finalizers.set(t,r)}},Ax=(e,t)=>{if(e.state._tag!==\"Open\")return;let r=e.state;r.finalizerKey===t?e.state=jE:r.finalizers!==void 0&&(r.finalizers.delete(t),r.finalizers.size===0&&(e.state=jE))},Gx=e=>zP(e,void 0),zP=(e=\"sequential\",t)=>({[BE]:BE,[KE]:KE,strategy:e,parent:t,state:jE}),jE={_tag:\"Empty\"};var vc=ri,WP=Lr(ri),OI=e=>se(t=>{let r=t.context,n=Gx();return t.setContext(dr(t.context,ri,n)),oi(t,o=>(t.setContext(r),qx(n,o))),e});var Vx=e=>be(()=>{let t=Gx();return Mn(e(t),r=>be(()=>qx(t,r)??Se))}),kc=(e,t,r)=>ei(n=>ro(o=>oe(vc,s=>Vp(r?.interruptible?o(e):e,a=>ni(s,i=>Pn(t(a,i),n)))))),_I=e=>oe(vc,t=>ei(r=>ni(t,n=>Pn(e(n),r)))),qP=(function(){let e=vn({op:\"OnExit\",[lt](r){return r._stack.push(this),this.effect},[sc](r){r.interruptible&&this.interruptible!==!0&&(r._stack.push(od),r.interruptible=!1)},[Gt](r,n,o){o??=We(r);let s;try{s=this.onExit(o)}catch(a){s=Jr(a)}return s?oe(s,a=>o):o},[Tn](r,n,o){o??=Nt(r);let s;try{s=this.onExit(o)}catch(a){s=Jr(a)}return s?oe(jP(o,s),a=>o):o}}),t=function(r,n,o){this.effect=r,this.onExit=n,this.interruptible=o};return t.prototype=e,t})(),Po=(e,t,r)=>new qP(e,t,r),oi=(e,t)=>{e._stack.push(new qP(void 0,t,void 0))},Mn=l(2,Po),JP=l(2,(e,t)=>Mn(e,r=>t)),RI=l(3,(e,t,r)=>Mn(e,n=>t(n)?r(n):Se)),PI=l(3,(e,t,r)=>Mn(e,n=>{let o=t(n);return ae(o)?Se:r(o.success,n)})),MI=l(2,(e,t)=>PI(e,Yp,t)),GP=l(3,(e,t,r)=>RI(e,n=>n._tag!==\"Failure\"?!1:t(n.cause),n=>r(n.cause))),FI=l(3,(e,t,r)=>Mn(e,n=>{if(n._tag!==\"Failure\")return Se;let o=t(n.cause);return ae(o)?Se:r(o.success,n.cause)})),VP=l(2,(e,t)=>FI(Rx,t)(e)),nd=(e,t,r)=>ro(n=>oe(e,o=>Po(be(()=>n(t(o))),s=>r(o,s),!0))),ZP=e=>kc(e,t=>A(t,Symbol.asyncDispose)?XE(()=>t[Symbol.asyncDispose]()):X(()=>t[Symbol.dispose]())),NI=l(2,(e,t)=>X(()=>YP(e,typeof t==\"function\"?r=>Nr(ct(t(r))):gt(Nr(ct(t)))))),g3=gt(1/0),YP=(e,t)=>{let r=0,n,o,s=(a,i)=>(i.awaiters++,oi(a,()=>{if(!(--i.awaiters>0||i.done))return o===i&&(o=void 0),Dx(i.fiber)}),Ix(i.fiber));return[se(a=>{if(o!==void 0)return a===o.fiber?Ix(o.fiber):s(a,o);if(n!==void 0&&(r===1/0||a.getRef(Dr).currentTimeMillisUnsafe(){if(c.done=!0,o!==c||(o=void 0,fI(f)))return;let p=t(f);r=p===1/0?1/0:i.currentTimeMillisUnsafe()+p,n=f})),c.fiber._exit??u}),X(()=>{o=void 0,n=void 0})]},QP=l(2,(e,t)=>Fe(NI(e,t),r=>r[0])),XP=e=>X(()=>YP(e,g3)[0]),eM=se(e=>Le(Ya(e.id))),Oc=e=>se(t=>(t.interruptible&&(t.interruptible=!1,t._stack.push(od)),e)),tM=Zn({op:\"SetInterruptible\",[sc](e){if(e.interruptible=this[xe],e._interruptedCause&&e.interruptible)return()=>Le(e._interruptedCause)}}),od=tM(!0),y3=tM(!1),rM=e=>{if(e.interruptible=!0,e._stack.push(y3),e._interruptedCause)return Le(e._interruptedCause)},S3=e=>{let t=e;t.interruptible&&(t.interruptible=!1,t._stack.push(od))};var Zx=e=>se(t=>t.interruptible?e:rM(t)??e),ro=e=>se(t=>t.interruptible?(t.interruptible=!1,t._stack.push(od),e(Zx)):e(D)),nM=e=>se(t=>{if(t.interruptible)return e(D);let r=rM(t),n=e(Oc);return r??n}),oM=Fe(kc(X(()=>new AbortController),e=>X(()=>e.abort())),e=>e.signal),sd=(e,t)=>Js(e)?t?.mode===\"result\"?_n(e,Za,t):_n(e,D,t):t?.discard?t.mode===\"result\"?_n(Object.values(e),Za,t):_n(Object.values(e),D,t):be(()=>Fe(_n(Object.entries(e),([r,n])=>Fe(t?.mode===\"result\"?Za(n):n,o=>[r,o]),{concurrency:t?.concurrency}),Object.fromEntries)),UI=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>Fe(_n(e,(n,o)=>Za(t(n,o)),r),n=>xE(n,D))),sM=l(3,(e,t,r)=>{let n=wt(e);return n.length===0?X(t):be(()=>{let o=0,s=t();return Fe(si({while:()=>or(s,n[o],o),step(a){s=a,o++}}),()=>s)})}),aM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>oe(UI(e,t,{concurrency:r?.concurrency}),([n,o])=>Mr(o)?dt(o):r?.discard?Se:z(n))),iM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=e[Symbol.iterator](),n=r.next();return n.done?z(v()):cM(r,0,t,n.value)})),cM=(e,t,r,n)=>oe(r(n,t),o=>{if(o)return z(_(n));let s=e.next();return s.done?z(v()):cM(e,t+1,r,s.value)}),uM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=e[Symbol.iterator](),n=r.next();return n.done?z(v()):fM(r,0,t,n.value)})),fM=(e,t,r,n)=>oe(r(n,t),o=>{if(rt(o))return z(_(o.success));let s=e.next();return s.done?z(v()):fM(e,t+1,r,s.value)}),si=Zn({op:\"While\",[Gt](e,t){return this[xe].step(e),this[xe].while()?(t._stack.push(this),this[xe].body()):Ur},[lt](e){return this[xe].while()?(e._stack.push(this),this[xe].body()):Ur}}),_n=l(e=>typeof e[1]==\"function\",(e,t,r)=>be(()=>{let n=ad(r?.concurrency);if(n===1)return b3(e,t,r);let o=wt(e),s=o.length;if(s===0)return r?.discard?Se:z([]);let a=r?.discard?void 0:new Array(s),i=E3({f:t,out:a},o,{concurrency:n});return i?Rn(i,a):z(a)})),lM=e=>oe(e,t=>{let r=t[Symbol.iterator]().next();return r.done?dt(new vo):z(r.value)}),b3=(e,t,r)=>be(()=>{let n=r?.discard?void 0:[],o=e[Symbol.iterator](),s=o.next(),a=0;return Rn(si({while:()=>!s.done,body:()=>t(s.value,a++),step:i=>{n&&n.push(i),s=o.next()}}),n)}),ad=e=>e===\"unbounded\"?Number.POSITIVE_INFINITY:Math.max(1,e??1),Yx=()=>e=>{let t=e.onItem,r=e.step,n=(s,a,i,c,u)=>oe(rd(u),f=>r(s,a[i],f,i)??o(s,a,i+1,c)??Se),o=(s,a,i=0,c=a.length)=>{for(;i{let t=e.onItem,r=e.step;return(n,o,s)=>{let a=0,i=s.end??o.length,c=s.concurrency,u=!1,f,p,d,m,h,y=b=>{let x=Jr(b);return m=x,u=!0,p&&p.size>0?oe(Oc(lf(Array.from(p))),()=>m??x):x},S=()=>{let b=!1;for(;!m&&a{p.delete(I);try{if(m){if(P._tag===\"Failure\"){let G=P.cause.reasons.filter(he=>he._tag!==\"Interrupt\");if(G.length>0){let he=ls(G);m=Nt(m._tag===\"Failure\"?Ox(Ep(m.cause,he)):he)}}}else{let G=r(n,x,P,T);G&&(m=G,S())}if(b){let G=S();G&&d(G)}else u&&p.size===0&&d(m??Se)}catch(G){d(y(G))}}),p.size{f=sa(),p=new Set,h=w,d=I;let T;try{T=S()}catch(P){return I(y(P))}return T?I(T):be(()=>(m??=Ur,oe(p?lf(p):Se,()=>m?._tag===\"Failure\"?m:Se)))})}if(u=!0,m){if(p&&p.size>0){let x=Nx(f);p.forEach(w=>w.interruptUnsafe(f.id,x));return}if(d||m._tag===\"Failure\")return m}else if(d)if(p)p.size===0&&d(Se);else return Ur};return S()}},Qx=()=>e=>pM(e),E3=pM({onItem(e,t,r){return e.f(t,r)},step(e,t,r,n){if(r._tag===\"Failure\")return r;e.out&&(e.out[n]=r.value)}}),DI=l(3,(e,t,r)=>oe(e,n=>t(n)?z(n):r(n))),LI=l(3,(e,t,r)=>oe(e,n=>{let o=t(n);return ae(o)?r(o.failure):z(o.success)})),dM=l(e=>de(e[0]),(e,t,r)=>LI(e,t,r?n=>dt(r(n)):()=>dt(new vo))),mM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>Fe(_n(e,(n,o)=>{let s=t(n,o);return typeof s==\"boolean\"?z(s?_(n):v()):Fe(s,a=>a?_(n):v())},r),O_)),hM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=[];for(let n of e){let o=t(n);rt(o)&&r.push(o.success)}return z(r)})),xM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>be(()=>{let n=[];return Rn(_n(e,o=>Fe(t(o),s=>{rt(s)&&n.push(s.success)}),{discard:!0,concurrency:r?.concurrency}),n)})),gM=z({}),yM=Kh(Fe),SM=Bh(Fe,oe),bM=$h(Fe);var EM=l(e=>de(e[0]),(e,t)=>se(r=>(U3(),z(_c(r,e,t?.startImmediately,!1,t?.uninterruptible??!1))))),_c=(e,t,r=!1,n=!1,o=!1)=>{let s=e,a=o===\"inherit\"?s.interruptible:!o,i=new ff(s.context,a);return n||(s.children().add(i),i._parent=s),r?i.evaluate(t):(i._asyncContext=vR(),s.currentDispatcher.scheduleTask(()=>i.evaluate(t),0)),i},IM=l(e=>de(e[0]),(e,t)=>se(r=>z(_c(r,e,t?.startImmediately,!0,t?.uninterruptible)))),wM=e=>se(t=>{let r=t._children&&new Set(t._children),n=t.interruptible;return Po(e,o=>{let s=t._children;if(s===void 0||s.size===0)return Se;r&&(s=A_(s,i=>!r.has(i)));let a=Zp(Ux(s));return n?Zx(a):a})}),AM=e=>()=>se(t=>t===e?Se:Dx(e)),$I=l(e=>de(e[0]),(e,t,r)=>se(n=>{let o=t.state._tag===\"Closed\"?new ff(n.context):_c(n,e,r?.startImmediately,!0,r?.uninterruptible);return o._exit||(t.state._tag!==\"Closed\"?(If(t,o,AM(o)),o.addObserver(()=>Ax(t,o))):o.interruptUnsafe(n.id,Nx(n))),z(o)})),CM=l(e=>de(e[0]),(e,t)=>oe(vc,r=>$I(e,r,t))),ua=e=>(t,r)=>{let n=new ff(r?.scheduler?dr(e,uf,r.scheduler):e,r?.uninterruptible!==!0);if(n.evaluate(t),n._exit)return n;if(r?.signal)if(r.signal.aborted)n.interruptUnsafe();else{let o=()=>n.interruptUnsafe();r.signal.addEventListener(\"abort\",o,{once:!0}),n.addObserver(()=>r.signal.removeEventListener(\"abort\",o))}return r?.onFiberStart&&r.onFiberStart(n),n},TM=l(2,(e,t)=>e._exit?e:t.state._tag===\"Closed\"?(e.interruptUnsafe(e.id),e):(Ax(t,e),If(t,e,AM(e)),e.addObserver(()=>Ax(t,e)),e)),vM=ua(Pr()),KI=e=>{let t=ua(e);return(r,n)=>{let o=t(r,n);return n?.onExit&&o.addObserver(n.onExit),s=>o.interruptUnsafe(s)}},kM=KI(Pr()),Xx=e=>{let t=ua(e);return(r,n)=>{let o=t(r,n);return new Promise(s=>{o.addObserver(a=>s(a))})}},OM=Xx(Pr()),BI=e=>{let t=Xx(e);return(r,n)=>t(r,n).then(o=>{if(o._tag===\"Failure\")throw Mx(o.cause);return o.value})},_M=BI(Pr()),eg=e=>{let t=ua(e);return r=>{if(Ve(r))return r;let n=new bc(\"sync\"),o=t(r,{scheduler:n});return o._dispatcher?.flush(),o._exit??Jr(new qp(o))}},RM=eg(Pr()),jI=e=>{let t=eg(e);return r=>{let n=t(r);if(n._tag===\"Failure\")throw Mx(n.cause);return n.value}},PM=jI(Pr()),mR=z(!0),hR=z(!1),HE=class{waiters=[];scheduled=void 0;_isOpen;constructor(t){this._isOpen=t}scheduleUnsafe(t){if(this.waiters.length===0)return mR;if(this.scheduled===void 0)this.scheduled=this.waiters,t.currentDispatcher.scheduleTask(this.flushScheduled,0);else for(let r=0;r{if(this.scheduled===void 0)return;let t=this.scheduled;this.scheduled=void 0;for(let r=0;rthis._isOpen?hR:(this._isOpen=!0,this.scheduleUnsafe(t)));release=se(t=>this._isOpen?hR:this.scheduleUnsafe(t));openUnsafe(){return this._isOpen?!1:(this._isOpen=!0,this.flushWaiters(),!0)}await=Dt(t=>this._isOpen?t(Se):(this.waiters.push(t),X(()=>{let r=this.waiters.indexOf(t);r!==-1?this.waiters.splice(r,1):this.scheduled!==void 0&&(r=this.scheduled.indexOf(t),r!==-1&&this.scheduled.splice(r,1))})));closeUnsafe(){return this._isOpen?(this._isOpen=!1,!0):!1}close=X(()=>this.closeUnsafe());whenOpen=t=>oe(this.await,()=>t);isOpen(){return this._isOpen}},HI=e=>new HE(e??!1),MM=e=>X(()=>HI(e)),FM=se(e=>z(e.getRef(_E))),NM=l(2,(e,t)=>Lr(e,_E,t)),UM=Lr(Sx),DM=Lr(wc),Cx=BigInt(0),I3={_tag:\"Span\",spanId:\"noop\",traceId:\"noop\",sampled:!1,status:{_tag:\"Ended\",startTime:Cx,endTime:Cx,exit:Ur},attributes:new Map,links:[],kind:\"internal\",attribute(){},event(){},end(){},addLinks(){}},w3=e=>Object.assign(Object.create(I3),e),LM=e=>e?Me(e.annotations,yx)?e._tag===\"Span\"?LM(ps(e.parent)):v():_(e):v(),zI=(e,t,r)=>{let n=!e.cache.tracerEnabled||r?.annotations&&Me(r.annotations,yx),o=r?.parent!==void 0?_(r.parent):r?.root?v():LM(e.cache.span),s;if(n)s=w3({name:t,parent:o,annotations:dr(r?.annotations??Pr(),yx,!0)});else{let a=e.cache.tracer??RE,i=e.getRef(Dr),c=e.getRef(wc),u=e.getRef(Dp),f=e.getRef(Lp),p=r?.level??e.getRef(oR),d=r?.links!==void 0?[...f,...r.links]:f.length===0?[]:f.slice();s=a.span({name:t,parent:o,annotations:r?.annotations??Pr(),links:d,startTime:c?i.currentTimeNanosUnsafe():Cx,kind:r?.kind??\"internal\",root:r?.root??!1,sampled:r?.sampled??(Ce(o)&&o.value.sampled===!1?!1:!r1(e.getRef(sR),p))});for(let m in u)s.attribute(m,u[m]);if(r?.attributes!==void 0)for(let m in r.attributes)s.attribute(m,r.attributes[m])}return s},$M=(e,t)=>se(r=>z(zI(r,e,t))),$p=(e,t)=>Oc(se(r=>{let n=ds(r.context,ri),o=zI(r,e,t??{}),s=r.getRef(Dr),a=r.getRef(wc);return Rn(ni(n,i=>tg(o,i,s,a)),o)})),KM=function(){let e=typeof arguments[0]!=\"string\",t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return oe($p(t,r),o=>pf(n,o,r))}return n=>oe($p(t,r),o=>pf(n,o,r))},A3=(e,t)=>(t=typeof t==\"function\"?t:Vn,ia(Up,r=>({name:e,stack:t,parent:r}))),BM=Dp,jM=Lp,HM=l(e=>de(e[0]),(e,t,r={})=>{let o=(Array.isArray(t)?t:[t]).map(s=>({span:s,attributes:r}));return ia(e,Lp,s=>[...s,...o])}),tg=(e,t,r,n)=>X(()=>{e.status._tag!==\"Ended\"&&e.end(n?r.currentTimeNanosUnsafe():Cx,t)}),Kp=(e,...t)=>{let r=t.length===1?void 0:t[0],n=t[t.length-1];return se(o=>{let s=zI(o,e,r),a=o.getRef(Dr),i=o.getRef(wc);return oi(o,c=>tg(s,c,a,i)),n(s)})},zE=Lr(Ic),pf=function(){let e=de(arguments[0]),t=e?arguments[1]:arguments[0],r=e?arguments[2]:arguments[1],n=D;return t._tag===\"Span\"&&(r=Va(r),n=A3(t.name,r?.captureStackTrace)),e?zE(n(arguments[0]),t):o=>zE(n(o),t)},zM=function(){let e=typeof arguments[0]!=\"string\",t=e?arguments[1]:arguments[0],r=Va(arguments[2]);if(e){let s=arguments[0];return Kp(t,arguments[2],a=>pf(s,a,r))}let n=typeof arguments[1]==\"function\"?arguments[1]:void 0,o=n?void 0:arguments[1];return(s,...a)=>Kp(t,n?n(...a):o,i=>pf(s,i,r))},WM=l(e=>de(e[0]),(e,...t)=>ia(e,Dp,r=>{let n=t.length===1?{...r,...t[0]}:{...r};return t.length===1||B(n,t[0],t[1]),n})),qM=(...e)=>se(t=>{let r=t.currentSpanLocal;if(r&&r.status._tag!==\"Ended\")if(e.length===1)for(let[n,o]of Object.entries(e[0]))r.attribute(n,o);else r.attribute(e[0],e[1]);return Se}),JM=se(e=>{let t=e.currentSpanLocal;return t?z(t):dt(new vo)}),GM=i3(Ic),Dr=Te(\"effect/Clock\",{defaultValue:()=>new WE}),UE=2**31-1,WE=class{currentTimeMillisUnsafe(){return Date.now()}currentTimeMillis=X(()=>this.currentTimeMillisUnsafe());currentTimeNanosUnsafe(){return C3()}currentTimeNanos=X(()=>this.currentTimeNanosUnsafe());monotonicTimeNanosUnsafe(){return ZM()}monotonicTimeNanos=X(()=>this.monotonicTimeNanosUnsafe());sleep(t){return this.sleepMillis(Nr(t))}sleepMillis(t){return t<=0?yf:Number.isFinite(t)?Dt(r=>{let n=t>UE?this.sleepMillis(t-UE):Se,o=setTimeout(()=>r(n),Math.min(t,UE));return X(()=>clearTimeout(o))}):Lx}},VM=BigInt(1e6),ZM=(function(){let e=globalThis.process?.hrtime;if(typeof e?.bigint==\"function\")return()=>e.bigint();if(typeof performance<\"u\"&&typeof performance.now==\"function\")return()=>BigInt(Math.round(performance.now()*1e6));let t=BigInt(0);return()=>{let r=BigInt(Date.now())*VM;return r>t&&(t=r),t}})(),C3=(function(){let e=BigInt(1e9),t;return()=>{let r=ZM(),n=BigInt(Date.now())*VM;if(t===void 0)t=n-r;else{let o=t+r;(n>o?n-o:o-n)>e&&(t=n-r)}return t+r}})(),Mo=e=>se(t=>e(t.getRef(Dr))),wf=e=>Mo(t=>t.sleep(ct(e))),WI=Mo(e=>e.currentTimeMillis);var Bp=\"~effect/Cause/TimeoutError\",YM=e=>A(e,Bp),jp=class extends Ys(\"TimeoutError\"){[Bp]=Bp;constructor(t){super({message:t})}},Hp=\"~effect/Cause/IllegalArgumentError\",QM=e=>A(e,Hp),Tx=class extends Ys(\"IllegalArgumentError\"){[Hp]=Hp;constructor(t){super({message:t})}},zp=\"~effect/Cause/ExceededCapacityError\",XM=e=>A(e,zp),vx=class extends Ys(\"ExceededCapacityError\"){[zp]=zp;constructor(t){super({message:t})}},Wp=\"~effect/Cause/AsyncFiberError\",e1=e=>A(e,Wp),qp=class extends Ys(\"AsyncFiberError\"){[Wp]=Wp;constructor(t){super({message:\"An asynchronous Effect was executed with Effect.runSync\",fiber:t})}},Jp=\"~effect/Cause/UnknownError\",t1=e=>A(e,Jp),df=class extends Ys(\"UnknownError\"){[Jp]=Jp;constructor(t,r){super({message:r,cause:t})}},qI=Te(\"effect/Console\",{defaultValue:()=>globalThis.console}),T3=e=>{switch(e){case\"All\":return Number.MIN_SAFE_INTEGER;case\"Fatal\":return 5e4;case\"Error\":return 4e4;case\"Warn\":return 3e4;case\"Info\":return 2e4;case\"Debug\":return 1e4;case\"Trace\":return 0;case\"None\":return Number.MAX_SAFE_INTEGER}},v3=rE(Qs,T3),r1=ef(v3),JI=Te(\"effect/Logger/CurrentLoggers\",{defaultValue:()=>new Set([F3,N3])}),k3=Te(\"effect/Logger/LogToStderr\",{defaultValue:ap}),n1=function(){let e=typeof arguments[0]==\"string\"?[[arguments[0],arguments[1]]]:Object.entries(arguments[0]);return Oc(se(t=>{let r=t.getRef(oa),n={...r};for(let o=0;o{let s=t.getRef(oa),a={...s};for(let i=0;i{let t=Object.create(_3);return t.log=e,t},R3=e=>e.replace(/[\\s=\"]/g,\"_\"),P3=(e,t)=>`${R3(e[0])}=${t-e[1]}ms`;var Ro=e=>(...t)=>{let r;for(let n=0,o=t.length;n{let o=e??n.cache.logLevel;if(r1(n.cache.minimumLogLevel,o))return Se;let s=n.getRef(Dr),a=n.getRef(JI);if(a.size>0){let i=new Date(s.currentTimeMillisUnsafe());for(let c of a)c.log({cause:r,fiber:n,date:i,logLevel:o,message:t})}return Se})};var Ac={bold:\"1\",red:\"31\",green:\"32\",yellow:\"33\",blue:\"34\",cyan:\"36\",white:\"37\",gray:\"90\",black:\"30\",bgBrightRed:\"101\"},lpe={None:[],All:[],Trace:[Ac.gray],Debug:[Ac.blue],Info:[Ac.green],Warn:[Ac.yellow],Error:[Ac.red],Fatal:[Ac.bgBrightRed,Ac.black]};var M3=e=>`${e.getHours().toString().padStart(2,\"0\")}:${e.getMinutes().toString().padStart(2,\"0\")}:${e.getSeconds().toString().padStart(2,\"0\")}.${e.getMilliseconds().toString().padStart(3,\"0\")}`;var F3=o1(({cause:e,date:t,fiber:r,logLevel:n,message:o})=>{let s=Array.isArray(o)?o.slice():[o];e.reasons.length>0&&s.push(Fx(e));let a=t.getTime(),i=r.getRef(bx),c=\"\";for(let d of i)c+=` ${P3(d,a)}`;let u=r.getRef(oa);Object.keys(u).length>0&&s.push(u);let f=r.getRef(qI);(r.getRef(k3)?f.error:f.log)(`[${M3(t)}] ${n.toUpperCase()} (#${r.id})${c}:`,...s)}),N3=o1(({cause:e,fiber:t,logLevel:r,message:n})=>{let o=t.getRef(Dr),s=t.getRef(oa),a=t.cache.span;if(a===void 0||a._tag===\"ExternalSpan\"||a.status._tag===\"Ended\")return;let i={};for(let[c,u]of Object.entries(s))B(i,c,u);i[\"effect.fiberId\"]=t.id,i[\"effect.logLevel\"]=r.toUpperCase(),e.reasons.length>0&&(i[\"effect.cause\"]=Fx(e)),a.event(FO(Array.isArray(n)&&n.length===1?n[0]:n),o.currentTimeNanosUnsafe(),i)});function U3(){$E.interruptChildren??=X4}var GI=z(void 0);var s1=l(e=>de(e[0]),(e,t)=>MI(e,r=>se(n=>(D3(n,r,t?.defectsOnly),Se)))),D3=(e,t,r)=>{let n=e.getRef(cR);if(n.size===0||r&&!hf(t))return;let o={cause:t,fiber:e,timestamp:e.getRef(Dr).currentTimeNanosUnsafe()};n.forEach(s=>s.report(o))};var L3=gp,$3=zu,id=qu,YI=DO,ai=fc,QI=lc,K3=Zs,gs=ls,B3=Fh,j3=Ju,Rc=Vb,H3=Ya,Af=e=>new ac(e),Cf=e=>new ic(e),XI=xR,e0=Px,fa=xf,z3=Ep,rg=Mx,t0=kx,W3=gR,q3=mf,r0=yR,J3=hf,G3=SR,cd=Gp,V3=_x,Z3=bR,Y3=ER,Q3=Rx,X3=qE,n0=Fx,eJ=Uh,tJ=yp,rJ=vo,Pc=Dh,nJ=cc,o0=pc,ue=BO,oJ=Bp,sJ=YM,aJ=jp,iJ=Hp,cJ=QM,ud=Tx,uJ=XM,fJ=zp,s0=vx,lJ=Wp,pJ=e1,dJ=qp,mJ=Jp,hJ=t1,xJ=df,gJ=Gu,ng=IR,yJ=wR,VI=class extends Et()(\"effect/Cause/StackTrace\"){},ZI=class extends Et()(\"effect/Cause/InterruptorStackTrace\"){};var $={};An($,{Do:()=>H5,Transaction:()=>Rf,TypeId:()=>N5,abortSignal:()=>cG,acquireDisposable:()=>Y8,acquireRelease:()=>Wc,acquireUseRelease:()=>pF,addFinalizer:()=>Q8,all:()=>Eg,andThen:()=>Zr,annotateCurrentSpan:()=>SG,annotateLogs:()=>YG,annotateLogsScoped:()=>QG,annotateSpans:()=>yG,as:()=>jt,asSome:()=>wg,asVoid:()=>pi,awaitAllChildren:()=>MG,bind:()=>q5,bindTo:()=>z5,cached:()=>nG,cachedInvalidateWithTTL:()=>sG,cachedWithTTL:()=>oG,callback:()=>Mf,catch:()=>Uo,catchCause:()=>nt,catchCauseFilter:()=>p8,catchCauseIf:()=>l8,catchDefect:()=>i8,catchEager:()=>$f,catchFilter:()=>u8,catchIf:()=>c8,catchNoSuchElement:()=>f8,catchReason:()=>o8,catchReasons:()=>s8,catchTag:()=>r8,catchTags:()=>n8,clockWith:()=>qc,context:()=>Hc,contextWith:()=>Od,currentParentSpan:()=>EG,currentSpan:()=>bG,delay:()=>j0,die:()=>yr,effectify:()=>fV,ensuring:()=>hi,eventually:()=>y8,exit:()=>so,fail:()=>F,failCause:()=>$e,failCauseSync:()=>da,failSync:()=>Ig,fiber:()=>FG,fiberId:()=>NG,filter:()=>z0,filterMap:()=>M8,filterMapEffect:()=>W0,filterMapOrElse:()=>N8,filterMapOrFail:()=>D8,filterOrElse:()=>F8,filterOrFail:()=>U8,findFirst:()=>$5,findFirstFilter:()=>K5,firstSuccessOf:()=>T8,flatMap:()=>C,flatMapEager:()=>Ct,flatten:()=>K0,flip:()=>e8,fn:()=>jG,fnUntraced:()=>_e,fnUntracedEager:()=>ew,forEach:()=>ui,forever:()=>ir,forkChild:()=>Uf,forkDetach:()=>PG,forkIn:()=>rr,forkScoped:()=>Df,fromNullishOr:()=>Y5,fromOption:()=>V5,fromResult:()=>jc,gen:()=>kt,head:()=>B5,ignore:()=>I8,ignoreCause:()=>di,interrupt:()=>io,interruptible:()=>aG,interruptibleMask:()=>iG,isEffect:()=>ws,isFailure:()=>H8,isSuccess:()=>z8,let:()=>W5,linkSpans:()=>AG,log:()=>zG,logDebug:()=>GG,logError:()=>X0,logFatal:()=>WG,logInfo:()=>JG,logTrace:()=>VG,logWarning:()=>qG,logWithLevel:()=>HG,makeSpan:()=>Z0,makeSpanScoped:()=>CG,map:()=>W,mapBoth:()=>d8,mapBothEager:()=>Sr,mapEager:()=>fn,mapError:()=>Do,mapErrorEager:()=>Lf,match:()=>q0,matchCause:()=>$8,matchCauseEager:()=>K8,matchCauseEffect:()=>As,matchCauseEffectEager:()=>B8,matchEager:()=>L8,matchEffect:()=>j8,never:()=>Bc,onError:()=>Lo,onErrorFilter:()=>eG,onErrorIf:()=>X8,onExit:()=>Dn,onExitFilter:()=>rG,onExitIf:()=>tG,onExitPrimitive:()=>_d,onInterrupt:()=>V0,option:()=>X5,orDie:()=>m8,orElseSucceed:()=>C8,partition:()=>U5,promise:()=>Pf,provide:()=>W8,provideContext:()=>ao,provideService:()=>Cs,provideServiceEffect:()=>Z8,race:()=>P8,raceAll:()=>H0,raceAllFirst:()=>R8,raceFirst:()=>Nf,reduce:()=>D5,repeat:()=>uG,repeatOrElse:()=>fG,replicate:()=>lG,replicateEffect:()=>pG,request:()=>_G,requestUnsafe:()=>RG,result:()=>Q5,retry:()=>S8,retryOrElse:()=>b8,runCallback:()=>DG,runCallbackWith:()=>UG,runFork:()=>Rd,runForkWith:()=>co,runPromise:()=>Y0,runPromiseExit:()=>kg,runPromiseExitWith:()=>LG,runPromiseWith:()=>Q0,runSync:()=>$G,runSyncExit:()=>Ts,runSyncExitWith:()=>BG,runSyncWith:()=>KG,sandbox:()=>E8,satisfiesErrorType:()=>pV,satisfiesServicesType:()=>dV,satisfiesSuccessType:()=>lV,schedule:()=>dG,scheduleFrom:()=>dF,scope:()=>zc,scoped:()=>Tg,scopedWith:()=>vg,service:()=>J0,serviceOption:()=>G0,setContext:()=>q8,sleep:()=>mi,spanAnnotations:()=>IG,spanLinks:()=>wG,succeed:()=>g,succeedNone:()=>li,succeedSome:()=>$0,suspend:()=>L,sync:()=>Y,tap:()=>Yr,tapCause:()=>fF,tapCauseFilter:()=>g8,tapCauseIf:()=>x8,tapDefect:()=>lF,tapError:()=>Ag,tapErrorTag:()=>h8,timed:()=>_8,timeout:()=>v8,timeoutOption:()=>k8,timeoutOrElse:()=>O8,tracer:()=>mG,track:()=>eV,trackDefects:()=>nV,trackDuration:()=>oV,trackErrors:()=>rV,trackSuccesses:()=>tV,transposeOption:()=>Z5,try:()=>Ff,tryPromise:()=>fi,tx:()=>sV,txRetry:()=>uV,undefined:()=>j5,uninterruptible:()=>ma,uninterruptibleMask:()=>$o,unwrapReason:()=>a8,updateContext:()=>J8,updateService:()=>G8,updateServiceScoped:()=>V8,useSpan:()=>TG,validate:()=>L5,void:()=>ie,when:()=>Cg,whileLoop:()=>No,withErrorReporting:()=>A8,withExecutionPlan:()=>w8,withFiber:()=>Un,withFiberSucceed:()=>G5,withLogSpan:()=>XG,withLogger:()=>ZG,withParentSpan:()=>OG,withSpan:()=>vG,withSpanScoped:()=>kG,withTracer:()=>hG,withTracerEnabled:()=>xG,withTracerTiming:()=>gG,yieldNow:()=>kd,yieldNowWith:()=>J5,zip:()=>B0,zipWith:()=>t8});var Or={};An(Or,{asVoid:()=>_J,asVoidAll:()=>pd,die:()=>a0,fail:()=>la,failCause:()=>Fn,filterCause:()=>AJ,filterFailure:()=>wJ,filterSuccess:()=>EJ,filterValue:()=>IJ,findDefect:()=>TJ,findError:()=>CJ,findErrorOption:()=>MJ,getCause:()=>PJ,getSuccess:()=>RJ,hasDies:()=>bJ,hasFails:()=>SJ,hasInterrupts:()=>i0,interrupt:()=>ld,isExit:()=>fd,isFailure:()=>no,isSuccess:()=>ut,map:()=>vJ,mapBoth:()=>OJ,mapError:()=>kJ,match:()=>c0,succeed:()=>Gr,void:()=>Bt});var fd=Sp,Gr=We,Fn=Nt,la=ko,a0=Jr,ld=bf,Bt=Ur;var ut=Xa,no=cI,SJ=nP,bJ=rP,i0=fI,EJ=QR,IJ=XR,wJ=eP,AJ=Yp,CJ=uI,TJ=tP,c0=sP,vJ=lI,kJ=pI,OJ=dI,_J=aP,pd=mI,RJ=iP,PJ=cP,MJ=uP;var FJ=\"~effect/Deferred\";var NJ={[FJ]:{_A:D,_E:D},pipe(){return te(this,arguments)}},a1=function(){this.resumes=void 0,this.effect=void 0};a1.prototype=NJ;var Mc=()=>new a1;var og=e=>Dt(t=>e.effect?t(e.effect):(e.resumes??=[],e.resumes.push(t),X(()=>{let r=e.resumes;if(r===void 0)return;let n=r.indexOf(t);n>=0&&r.splice(n,1)})));var UJ=l(2,(e,t)=>X(()=>ys(e,t))),DJ=UJ;var LJ=l(2,(e,t)=>DJ(e,Nt(t)));var u0=l(2,(e,t)=>LJ(e,Ya(t)));var ys=(e,t)=>{if(e.effect)return!1;if(e.effect=t,e.resumes){let r=e.resumes;e.resumes=void 0;for(let n=0;n{let r={observers:0,deferred:Mc(),scope:oo(),finalizer:n=>be(()=>--r.observers>0?Se:(e.map.delete(t),Xe(r.scope,n)))};return r},l1=(e,t)=>t.state._tag===\"Closed\"?!1:(e.observers++,If(t,{},e.finalizer),!0),m1=e=>A(e,d1),BJ={[d1]:{_ROut:D,_E:D,_RIn:D},pipe(){return te(this,arguments)}},h1=e=>{let t=Object.create(BJ);return t.build=e,t},jJ=e=>h1((t,r)=>{let n=tr(r);return Mn(e(t,n),o=>o._tag===\"Failure\"?Xe(n,o):Se)}),f0=e=>{let t=jJ((r,n)=>r.getOrElseMemoize(t,n,e));return t},ag=class{get[f1](){return f1}parent;constructor(t){this.parent=t}map=new Map;get(t,r){let n=this.map.get(t);return n?(l1(n,r),n.deferred.effect??og(n.deferred)):this.parent?.get(t,r)}getOrElseMemoize(t,r,n){return be(()=>{let o;return Po(be(()=>{let s=this.get(t,r);if(s)return s;let a=KJ(this,t);return l1(a,r)?(o=a.deferred,this.map.set(t,a),n(this,a.scope)):n(this,r)}),s=>{o&&ys(o,s)})})}},md=()=>new ag,HJ=e=>new ag(e);var dd=class e extends Et()(\"effect/Layer/CurrentMemoMap\"){static forkOrCreate(t){let r=ex(t,e);return r?HJ(r):md()}},hd=l(3,(e,t,r)=>Lr(Fe(be(()=>e.build(t,r)),dr(dd,t)),dd,t));var cg=l(2,(e,t)=>se(r=>hd(e,dd.forkOrCreate(r.context),t))),x1=function(){return arguments.length===1?e=>ig(xc(arguments[0],e)):ig(xc(arguments[0],arguments[1]))},ig=e=>h1(gt(z(e)));var pa=function(){return arguments.length===1?e=>p1(arguments[0],e):p1(arguments[0],arguments[1])},p1=(e,t)=>zJ(Fe(t,r=>xc(e,r))),zJ=e=>f0((t,r)=>Ss(e,r));var g1=(e,t,r)=>{let n=tr(r,\"parallel\");return _n(e,o=>o.build(t,tr(n,\"sequential\")),{concurrency:e.length}).pipe(Fe(o=>g_(...o)))},y1=(...e)=>f0((t,r)=>g1(e,t,r));var WJ=(e,t,r)=>f0((n,o)=>oe(Array.isArray(t)?g1(t,n,o):t.build(n,o),s=>e.build(n,o).pipe(Pn(s),Fe(a=>r(a,s))))),S1=l(2,(e,t)=>WJ(e,t,D));var Tf=Dr;var fg=\"~effect/DateTime\",lg=\"~effect/DateTime/TimeZone\",E1={[fg]:fg,pipe(){return te(this,arguments)},[Je](){return this.toString()},toJSON(){return yd(this).toJSON()}},I1={...E1,_tag:\"Utc\",[re](){return Lt(this.epochMilliseconds)},[ne](e){return kf(e)&&e._tag===\"Utc\"&&this.epochMilliseconds===e.epochMilliseconds},toString(){return`DateTime.Utc(${yd(this).toJSON()})`}},w1={...E1,_tag:\"Zoned\",[re](){return Ee(Lt(this.epochMilliseconds))(V(this.zone))},[ne](e){return kf(e)&&e._tag===\"Zoned\"&&this.epochMilliseconds===e.epochMilliseconds&&Z(this.zone,e.zone)},toString(){return`DateTime.Zoned(${A0(this)})`}},A1={[lg]:lg,[Je](){return this.toString()}},JJ={...A1,_tag:\"Named\",[re](){return Pe(`Named:${this.id}`)},[ne](e){return Nc(e)&&e._tag===\"Named\"&&this.id===e.id},toString(){return`TimeZone.Named(${this.id})`},toJSON(){return{_id:\"TimeZone\",_tag:\"Named\",id:this.id}}},GJ={...A1,_tag:\"Offset\",[re](){return Pe(`Offset:${this.offset}`)},[ne](e){return Nc(e)&&e._tag===\"Offset\"&&this.offset===e.offset},toString(){return`TimeZone.Offset(${E0(this.offset)})`},toJSON(){return{_id:\"TimeZone\",_tag:\"Offset\",offset:this.offset}}},VJ={value:void 0,enumerable:!1,writable:!0},l0=new WeakMap,ug=(e,t)=>({get(){return Object.isExtensible(this)?void 0:l0.get(this)?.[e]},set(r){if(Object.isExtensible(this)){for(let n of t)Object.defineProperty(this,n,VJ);this[e]=r}else{let n=l0.get(this);n===void 0&&(n={},l0.set(this,n)),n[e]=r}}}),p0=[\"partsUtc\",\"adjustedEpochMilliseconds\",\"partsAdjusted\"];Object.defineProperty(I1,\"partsUtc\",ug(\"partsUtc\",[\"partsUtc\"]));Object.defineProperties(w1,{partsUtc:ug(\"partsUtc\",p0),adjustedEpochMilliseconds:ug(\"adjustedEpochMilliseconds\",p0),partsAdjusted:ug(\"partsAdjusted\",p0)});var Es=(e,t,r)=>{let n=Object.create(w1);return n.epochMilliseconds=e,n.zone=t,r!==void 0&&(n.partsUtc=r),n},kf=e=>A(e,fg);var Nc=e=>A(e,lg),C1=e=>Nc(e)&&e._tag===\"Offset\",T1=e=>Nc(e)&&e._tag===\"Named\",v1=e=>e._tag===\"Utc\",h0=e=>e._tag===\"Zoned\",k1=Kt((e,t)=>e.epochMilliseconds===t.epochMilliseconds);var O1=e=>{let t=Object.create(I1);return t.epochMilliseconds=e,t},vf=e=>{let t=e.getTime();if(Number.isNaN(t))throw new ud(\"Invalid date\");return O1(t)},dg=e=>{if(kf(e))return e;if(e instanceof Date)return vf(e);if(typeof e==\"object\"){if(\"epochMilliseconds\"in e)return vf(new Date(e.epochMilliseconds));let t=new Date(0);return n5(t,e),vf(t)}else if(typeof e==\"string\"&&!ZJ(e))return vf(new Date(e+\"Z\"));return vf(new Date(e))},ZJ=e=>/Z|GMT|[+-]\\d{2}$|[+-]\\d{2}:?\\d{2}$|\\]$/.test(e)||/z$|gmt$/i.test(e),YJ=-864e13+720*60*1e3,QJ=864e13-840*60*1e3,x0=(e,t)=>{let r=t?.timeZone;if(r===void 0&&kf(e)&&h0(e))return e;let n=dg(e);if(n.epochMillisecondsQJ)throw new RangeError(`Epoch millis out of range: ${n.epochMilliseconds}`);r===void 0&&typeof e==\"object\"&&\"timeZoneId\"in e&&(r=e.timeZoneId);let o;if(r===void 0){let s=new Date(n.epochMilliseconds).getTimezoneOffset()*-60*1e3;o=gd(s)}else if(Nc(r))o=r;else if(typeof r==\"number\")o=gd(r);else{let s=S0(r);if(ge(s))throw new ud(`Invalid time zone: ${r}`);o=s.value}return t?.adjustForTimeZone!==!0?Es(n.epochMilliseconds,o,n.partsUtc):o5(n.epochMilliseconds,o,t?.disambiguation??\"compatible\")},d0=Oo(x0),_1=Oo(dg),XJ=/^(.{17,35})\\[(.+)\\]$/,R1=e=>{let t=XJ.exec(e);if(t===null){let o=w0(e);return o!==null?d0(e,{timeZone:o}):v()}let[,r,n]=t;return d0(r,{timeZone:n})};var P1=e=>O1(e.epochMilliseconds);var pg=new Map,e5={day:\"numeric\",month:\"numeric\",year:\"numeric\",era:\"short\",hour:\"numeric\",minute:\"numeric\",second:\"numeric\",timeZoneName:\"longOffset\",fractionalSecondDigits:3,hourCycle:\"h23\"},t5=e=>{let t=e.resolvedOptions().timeZone,r=pg.get(t);if(r!==void 0)return r;let n=Object.create(JJ);return n.id=t,n.format=e,pg.set(t,n),n},g0=e=>{let t=pg.get(e);if(t!==void 0)return t;try{let r=t5(new Intl.DateTimeFormat(\"en-US\",{...e5,timeZone:e}));return pg.set(e,r),r}catch{throw new ud(`Invalid time zone: ${e}`)}},gd=e=>{let t=Object.create(GJ);return t.offset=e,t},y0=Oo(g0);var r5=/^(?:GMT)?[+-]/,S0=e=>{if(r5.test(e)){let t=w0(e);return t===null?v():_(gd(t))}return y0(e)},M1=e=>e._tag===\"Offset\"?E0(e.offset):e.id;var yd=e=>new Date(e.epochMilliseconds),mg=e=>{if(e._tag===\"Utc\")return new Date(e.epochMilliseconds);if(e.zone._tag===\"Offset\")return new Date(e.epochMilliseconds+e.zone.offset);if(e.adjustedEpochMilliseconds!==void 0)return new Date(e.adjustedEpochMilliseconds);let t=!1,r=e.zone.format.formatToParts(e.epochMilliseconds).filter(s=>s.type===\"era\"?(t=s.value===\"BC\",!1):s.type!==\"literal\"),n=Number(r[2].value),o=new Date(0);return o.setUTCFullYear(t?1-n:n,Number(r[0].value)-1,Number(r[1].value)),o.setUTCHours(Number(r[3].value),Number(r[4].value),Number(r[5].value),r[6]?.type===\"fractionalSecond\"?Number(r[6].value):(e.epochMilliseconds%1e3+1e3)%1e3),e.adjustedEpochMilliseconds=o.getTime(),o},b0=e=>mg(e).getTime()-I0(e),E0=e=>{let t=Math.abs(e),r=Math.floor(t/(3600*1e3)),n=Math.round(t%(3600*1e3)/(60*1e3));return n===60&&(r+=1,n=0),`${e<0?\"-\":\"+\"}${String(r).padStart(2,\"0\")}:${String(n).padStart(2,\"0\")}`},F1=e=>E0(b0(e)),I0=e=>e.epochMilliseconds;var n5=(e,t)=>{if((t.year!==void 0||t.month!==void 0||t.day!==void 0)&&e.setUTCFullYear(t.year??e.getUTCFullYear(),t.month!==void 0?t.month-1:e.getUTCMonth(),t.day??e.getUTCDate()),t.weekDay!==void 0){let r=t.weekDay-e.getUTCDay();e.setUTCDate(e.getUTCDate()+r)}t.hour!==void 0&&e.setUTCHours(t.hour),t.minute!==void 0&&e.setUTCMinutes(t.minute),t.second!==void 0&&e.setUTCSeconds(t.second),t.millisecond!==void 0&&e.setUTCMilliseconds(t.millisecond)};var b1=1440*60*1e3,o5=(e,t,r)=>{if(t._tag===\"Offset\")return Es(e-t.offset,t);let n=xd(e-b1,e,t),o=xd(e+b1,e,t);if(n===o)return Es(e-n,t);let s=n{let t=s5.exec(e);if(t===null)return null;let[,r,n,o]=t;return(r===\"+\"?1:-1)*(Number(n)*60+Number(o))*60*1e3},xd=(e,t,r)=>{let n=r.format.formatToParts(e).find(s=>s.type===\"timeZoneName\")?.value??\"\";if(n===\"GMT\")return 0;let o=w0(n);return o===null?b0(Es(t,r)):o};var N1=e=>yd(e).toISOString();var m0=e=>{let t=mg(e);return e._tag===\"Utc\"?t.toISOString():`${t.toISOString().slice(0,-1)}${F1(e)}`},A0=e=>e.zone._tag===\"Offset\"?m0(e):`${m0(e)}[${e.zone.id}]`;var Cpe=globalThis.Number;var D1=l(2,(e,t)=>{if(!globalThis.Number.isFinite(e)||!globalThis.Number.isFinite(t)||t===0)return NaN;if(globalThis.Number.isInteger(e)&&globalThis.Number.isInteger(t))return e%t;let[r,n]=U1(e),[o,s]=U1(t),a=Math.min(n,s),i=r*BigInt(10)**BigInt(n-a),c=o*BigInt(10)**BigInt(s-a),u=i%c;if(u===BigInt(0))return e<0||Object.is(e,-0)?-0:0;let f=globalThis.Number(`${u}e${a}`);return f===0?Math.sign(e)*globalThis.Number.MIN_VALUE:f});function U1(e){if(globalThis.Number.isInteger(e))return[BigInt(e),0];let t=Math.abs(e).toExponential(),r=t.indexOf(\"e\"),n=t.slice(0,r).replace(\".\",\"\");return[BigInt(n)*(e<0?-BigInt(1):BigInt(1)),globalThis.Number(t.slice(r+1))-n.length+1]}var L1=e=>{let t=Math.pow(2,Math.ceil(Math.log2(e)));return Math.max(te.toUpperCase();var K1=e=>e.trim();var c5=(e,t,r,n,o)=>{let s=e;for(let c of t)s=s.replace(c,\"$1\\0$2\");for(let c of r)s=s.replace(c,\"\\0\");let a=0,i=s.length;for(;s.charAt(a)===\"\\0\";)a++;for(;s.charAt(i-1)===\"\\0\";)i--;return a>=i?\"\":s.slice(a,i).split(\"\\0\").map(o).join(n)};var u5=[/([a-z0-9])([A-Z])/g,/([A-Z])([A-Z][a-z])/g],f5=/[^A-Z0-9]+/gi;var B1=e=>c5(e,u5,[f5],\"_\",$1);var At=l(2,(e,t)=>ca(e,l5,r=>t(r))),Is=e=>e.reasons.some(C0),C0=e=>e._tag===\"Fail\"&&Pc(e.error),Sd=e=>{let t,r=!1;for(let n of e.reasons)C0(n)?t??=n.error:n._tag!==\"Interrupt\"&&(r=!0);return t===void 0?q(e):r?q(gs(e.reasons.filter(n=>!C0(n)))):j(t)};var l5=e=>{let t=Sd(e);return ae(t)?t:j(t.success.value)},bd=e=>{let t=Sd(e);return ae(t)?Fn(t.failure):Gr(t.success.value)},Uc=l(2,(e,t)=>_o(e,{onSuccess:t.onSuccess,onFailure:r=>{let n=Sd(r);return ae(n)?t.onFailure(n.failure):t.onDone(n.success.value)}}));var j1=\"~effect/Schedule\";var gr=Te(\"effect/Schedule/CurrentMetadata\",{defaultValue:gt({input:void 0,output:void 0,duration:ta,attempt:0,start:0,now:0,elapsed:0,elapsedSincePrevious:0})}),p5={[j1]:{_Out:D,_In:D,_Env:D},pipe(){return te(this,arguments)}},T0=e=>A(e,j1),Ed=e=>{let t=Object.create(p5);return t.step=e,t},v0=()=>{let e=0,t,r;return(n,o)=>{r===void 0&&(r=n);let s=n-r,a=t===void 0?0:n-t;return t=n,{input:o,attempt:++e,start:r,now:n,elapsed:s,elapsedSincePrevious:a}}},d5=e=>Ed(Fe(e,t=>{let r=v0();return(n,o)=>t(r(n,o))})),Lc=e=>un(e.step,t=>z(()=>Le(t))),Fo=e=>Mo(t=>Fe(Lc(e),r=>{let n=v0();return o=>be(()=>{let s=t.currentTimeMillisUnsafe();return oe(r(s,o),([a,i])=>{let c=n(s,o);return c.output=a,c.duration=i,Rn(wf(i),c)})})})),Id=e=>Fe(Fo(e),t=>r=>Fe(t(r),n=>n.output));var k0=e=>Ed(Fe(Lc(e),t=>(r,n)=>Uc(t(r,n),{onSuccess:o=>z([n,o[1]]),onFailure:Le,onDone:()=>ue(n)}))),H1=e=>wd(Ad,({attempt:t})=>z(t<=e)),O0=e=>{let t=ct(e);return d5(z(r=>z([r.attempt-1,t])))};var wd=l(2,(e,t)=>Ed(Fe(Lc(e),r=>{let n=v0();return(o,s)=>oe(r(o,s),a=>{let[i,c]=a,u=t({...n(o,s),output:i,duration:c});return oe(de(u)?u:z(u),f=>f?z(a):ue(i))})})));var Ad=O0(ta);var z1=\"~effect/ExecutionPlan\";var m5={[z1]:z1,get captureRequirements(){let e=this;return ei(t=>z(h5(e.steps.map(r=>({...r,while:r.while?n=>Pn(r.while(n),t):void 0,schedule:r.schedule?Ed(Pn(Fe(Lc(r.schedule),n=>(o,s)=>Pn(n(o,s),t)),t)):void 0,provide:m1(r.provide)?S1(r.provide,ig(t)):r.provide})))))},pipe(){return te(this,arguments)}},h5=e=>{let t=Object.create(m5);return t.steps=e,t};var gg=Te(\"effect/ExecutionPlan/CurrentMetadata\",{defaultValue:gt({attempt:0,stepIndex:0})});var x5=(e,t,r)=>Vx(n=>oe(r?.local?hd(t,md(),n):cg(t,n),o=>Pn(e,o))),yg=l(e=>de(e[0]),(e,t,r)=>kp(t)?Pn(e,t):x5(e,Array.isArray(t)?y1(...t):t,r));var R0=l(3,(e,t,r)=>oe(Fo(t),n=>{let o=gr.defaultValue(),s=a=>Uc(n(a),{onSuccess(i){return o=i,oe(Lr(e,gr,o),s)},onFailure:Le,onDone:z});return ca(oe(Lr(e,gr,o),s),cn,a=>r(a,o.attempt===0?v():_(o)))})),P0=l(3,(e,t,r)=>oe(Fo(t),n=>{let o=gr.defaultValue(),s,a=ca(be(()=>Lr(e,gr,o)),cn,i=>(s=i,oe(n(i),c=>(o=c,a))));return At(a,i=>za(()=>r(s,i)))})),q1=l(2,(e,t)=>{let r=typeof t==\"function\"?t(D):T0(t)?t:Td(t);return R0(e,r,dt)}),Cd=l(2,(e,t)=>{let r=typeof t==\"function\"?t(D):T0(t)?t:Td(t);return P0(e,r,dt)}),J1=l(3,(e,t,r)=>oe(Fo(r),n=>{let o=s=>Uc(n(s),{onSuccess:a=>oe(Lr(e,gr,a),o),onFailure:Le,onDone:z});return o(t)})),g5=k0(Ad),Td=e=>{let t=e.schedule?k0(e.schedule):g5;return e.while&&(t=wd(t,({input:r})=>{let n=e.while(r);return de(n)?n:z(n)})),e.until&&(t=wd(t,({input:r})=>{let n=e.until(r);return de(n)?Fe(n,o=>!o):z(!n)})),e.times!==void 0&&(t=wd(t,({attempt:r})=>z(r<=e.times))),t};var M0=(e,t)=>{let r=-1,n=0,o=s=>zx(e(s));return{begin:Mo(s=>be(()=>{let a=t();a.stepIndex!==r&&(r=a.stepIndex,n=0),n++;let i={attempt:a.attempt,stepAttempt:n,stepIndex:a.stepIndex,startNanos:s.monotonicTimeNanosUnsafe()};return Rn(o({_tag:\"AttemptStart\",attempt:i.attempt,stepAttempt:i.stepAttempt,stepIndex:i.stepIndex}),i)})),end:(s,a)=>Mo(i=>{let c=On(i.monotonicTimeNanosUnsafe()-s.startNanos);return o(a._tag===\"Success\"?{_tag:\"AttemptSuccess\",attempt:s.attempt,stepAttempt:s.stepAttempt,stepIndex:s.stepIndex,duration:c}:{_tag:\"AttemptFailure\",attempt:s.attempt,stepAttempt:s.stepAttempt,stepIndex:s.stepIndex,duration:c,cause:a.cause})})}},V1=l(e=>de(e[0]),(e,t,r)=>be(()=>{let n=0,o={attempt:0,stepIndex:0},s=Bx(gg,X(()=>(o={attempt:o.attempt+1,stepIndex:n},o))),a=r?.onEvent===void 0?void 0:M0(r.onEvent,()=>o),i=a===void 0?D:u=>ro(f=>oe(a.begin,p=>Mn(f(u),d=>a.end(p,d)))),c;return oe(si({while:()=>np?d:(p=!0,gf(c))),f=Cd(f,vd(u,!1))}else{let p=vd(u,!0);f=p?Cd(f,p):f}return Za(f)},step(u){c=u,n++}}),()=>gf(c))})),vd=(e,t)=>{if(t){if(e.attempts===1||!(e.schedule||e.attempts))return}else return Td({schedule:e.schedule?e.schedule:e.attempts?void 0:y5,times:e.attempts,while:e.while});return Td({schedule:e.schedule,while:e.while,times:e.attempts?e.attempts-1:void 0})},y5=H1(1);var Y1=\"~effect/MutableHashMap\";var S5={[Y1]:Y1,[Symbol.iterator](){return this.backing[Symbol.iterator]()},toString(){return`MutableHashMap(${K(Array.from(this))})`},toJSON(){return{_id:\"MutableHashMap\",values:qt(Array.from(this))}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},$c=()=>{let e=Object.create(S5);return e.backing=new Map,e.buckets=new Map,e};var Nn=l(2,(e,t)=>{if(e.backing.has(t))return _(e.backing.get(t));if(F0(t))return v();let r=V(t),n=e.buckets.get(r);return n===void 0?v():b5(e,n,t)}),F0=e=>typeof e!=\"object\"&&typeof e!=\"function\";var b5=(e,t,r)=>{for(let n=0,o=t.length;nCe(Nn(e,t))),Kc=l(3,(e,t,r)=>{if(e.backing.has(t)||F0(t))return e.backing.set(t,r),e;let n=V(t),o=e.buckets.get(n);if(o===void 0)return e.buckets.set(n,[t]),e.backing.set(t,r),e;let s=E5(o,t);return s===void 0&&(o.push(t),s=t),e.backing.set(s,r),e}),E5=(e,t)=>{for(let r=0,n=e.length;r{if(F0(t))return e.backing.delete(t),e;let r=V(t),n=e.buckets.get(r);if(n===void 0)return e;for(let o=0,s=n.length;o(e.backing.clear(),e.buckets.clear(),e),Q1=e=>e.backing.size;var I5=\"~effect/Request\",w5=Rh({_E:e=>e,_A:e=>e,_R:e=>e}),Vpe={...UO,[I5]:w5};var X1=e=>e;var eF=l(2,(e,t)=>{let r=n=>Dt(o=>{let s=rF(n,e,o,sa());return k5(n,s)});return de(t)?oe(t,r):r(t)}),tF=(e,t)=>{let r=rF(t.resolver,e,t.onExit,{context:t.context,cache:{scheduler:Me(t.context,uf)}});return()=>nF(t.resolver,r)},C5=new WeakSet,T5=e=>{if(!C5.has(e.batchKey))return new Map;let t=$c();return{get:r=>ps(Nn(t,r)),has:r=>N0(t,r),set:(r,n)=>Kc(t,r,n),delete:r=>ci(t,r)}},U0=new WeakMap,v5=(e,t,r,n)=>{let o={key:e,context:t,resolver:r,map:n,entrySet:new Set,entries:new Set,delayEffect:oe(se(s=>(o.fiber=s,o.resolver.delay)),s=>oF(o)),run:Mn(be(()=>o.resolver.runAll(Array.from(o.entries),o.key)),s=>{for(let a of o.entrySet)a.completeUnsafe(s._tag===\"Success\"?Jr(new Error(\"Effect.request: RequestResolver did not complete request\",{cause:a.request})):s);return o.entries.clear(),Se})};return o},rF=(e,t,r,n)=>{let o=U0.get(e);o||(o=T5(e),U0.set(e,o));let s,a=!1,i=X1({request:t,context:n.context,uninterruptible:!1,completeUnsafe(f){a||(a=!0,!(s&&!s.entrySet.delete(i))&&r(f))}});if(e.preCheck!==void 0&&!e.preCheck(i))return i;let c=e.batchKey(i);s=o.get(c);let u=s===void 0;if(s||(s=v5(c,n.context,e,o),o.set(c,s)),s.entrySet.add(i),s.entries.add(i),u){let f=ua(n.context)(s.delayEffect,{scheduler:n.cache.scheduler});if(a||o.get(c)!==s)return i;s.fiber=f}return s.resolver.collectWhile(s.entries)||(s.fiber.interruptUnsafe(n.id),ua(s.context)(oF(s),{scheduler:Me(s.context,uf)})),i},nF=(e,t)=>{if(t.uninterruptible)return;let r=U0.get(e);if(!r)return;let n=e.batchKey(t),o=r.get(n);if(!o||!o.entries.delete(t))return;o.entrySet.delete(t);let s;o.entries.size===0&&(r.delete(n),s=o.fiber),t.completeUnsafe(bf()),s?.interruptUnsafe()},k5=(e,t)=>X(()=>nF(e,t));function oF(e){return e.map.has(e.key)?(e.map.delete(e.key),e.run):Se}var _5=\"effect/Metric/CurrentMetricAttributes\",R5=Te(_5,{defaultValue:()=>({})}),P5=\"effect/Metric/MetricRegistry\",D0=Te(P5,{defaultValue:()=>new Map}),sF=\"~effect/Metric\",aF=class{[sF]=sF;#e;#t;#r=\"\";id;description;attributes;constructor(t,r,n){this.id=t,this.description=r,this.attributes=n}valueUnsafe(t){return this.hook(t).get(t)}modifyUnsafe(t,r){return this.hook(r).modify(t,r)}updateUnsafe(t,r){return this.hook(r).update(t,r)}hook(t){let r=this.key(t),n=Me(t,D0),o=n.get(r);return EO(o)&&(o=this.metadata(this.createHooks()),n.set(r,o)),o.hooks}removeUnsafe(t){Me(t,D0).delete(this.key(t))}registerUnsafe(t,r){let n=this.key(t),o=Me(t,D0),s=this.metadata({get:r.get,update:zr,modify:zr});return o.set(n,s),{remove(){o.get(n)===s&&o.delete(n)}}}key(t){let r=Me(t,R5);if(r!==this.#e){this.#e=r;let n=F5(this.attributes,r);this.#t=Object.keys(r).length>0?n:this.attributes,this.#r=M5(this,n)}return this.#r}metadata(t){return{id:this.id,type:this.type,description:this.description,attributes:this.#t,hooks:t}}pipe(){return te(this,arguments)}};var _f=l(2,(e,t)=>ei(r=>X(()=>e.updateUnsafe(t,r))));function M5(e,t){let r=Object.entries(t).sort((n,o)=>n[0]o[0]?1:0);return JSON.stringify([e.type,e.id,e.description,r])}function F5(e,t){return{...iF(e),...iF(t)}}function iF(e){return cs(e)&&Array.isArray(e)?e.reduce((t,[r,n])=>(B(t,r,n),t),{}):e}var N5=fs,ws=de,Eg=sd,U5=UI,D5=sM,L5=aM,$5=iM,K5=uM,ui=_n,B5=lM,No=si,Pf=XE,fi=FR,g=z,li=Tc,$0=YE,L=be,Y=X,ie=Se;var j5=GI;var Mf=Dt,Bc=Lx,H5=gM,z5=yM,W5=bM;var q5=SM,kt=DR,F=dt,Ig=QE,$e=Le,da=PR,yr=Qa,Ff=MR;var kd=yf,J5=ZE,Un=se,G5=$O,jc=gf,V5=VE,Z5=RR,Y5=_R,C=oe,K0=JR,Zr=xs,Yr=Vp,Q5=Za,X5=MP,so=rd,W=Fe,jt=Rn,wg=Sf,pi=Zp,e8=jR,B0=mP,t8=xI,Uo=ti;var r8=bI,n8=TP,o8=vP,s8=kP,a8=OP,nt=un,i8=EP,c8=Qp,u8=Hx,f8=bP,l8=yI,p8=ca,Do=EI,d8=II,m8=wI,Ag=SI,h8=AP,fF=IP,x8=wP,g8=jx,lF=CP,y8=AI,S8=Cd,b8=P0,E8=HR,I8=PP,di=zx,w8=V1,A8=s1,C8=_P,T8=RP,v8=KP,k8=vI,O8=TI,j0=$P,mi=wf,_8=BP,H0=sI,R8=aI,P8=zR,Nf=iI,z0=mM,M8=hM,W0=xM,F8=DI,N8=LI,U8=hP,D8=dM,Cg=xP,q0=Wx,L8=td,$8=CI,K8=UP,B8=WR,As=_o,j8=ed,H8=DP,z8=LP,Hc=hI,Od=ei,W8=yg,ao=Pn,q8=dP,J0=fP,G0=lP,J8=Ef,G8=ia,V8=pP,Cs=Lr,Z8=Bx,zc=vc,Tg=OI,vg=Vx,Wc=kc,Y8=ZP,pF=nd,Q8=_I,hi=JP,Lo=MI,X8=GP,eG=FI,_d=Po,Dn=Mn,tG=RI,rG=PI,nG=XP,oG=QP,sG=NI,io=eM,aG=Zx,V0=VP,ma=Oc,$o=ro,iG=nM,cG=oM,ir=yP,uG=q1,fG=R0,lG=gI,pG=gP,dG=l(2,(e,t)=>dF(e,void 0,t)),dF=J1,mG=FM,hG=NM,xG=UM,gG=DM,yG=WM,SG=qM,bG=JM,EG=GM,IG=BM,wG=jM,AG=HM,Z0=$M,CG=$p,TG=Kp,vG=zM,kG=KM,OG=pf,_G=eF,RG=tF,Uf=EM,rr=$I,Df=CM,PG=IM,MG=wM,FG=NR,NG=UR,Rd=vM,co=ua,UG=KI,DG=kM,Y0=_M,Q0=BI,kg=OM,LG=Xx,$G=PM,KG=jI,Ts=RM,BG=eg,_e=rI,jG=LR,qc=Mo,HG=Ro,zG=Ro(),WG=Ro(\"Fatal\"),qG=Ro(\"Warn\"),X0=Ro(\"Error\"),JG=Ro(\"Info\"),GG=Ro(\"Debug\"),VG=Ro(\"Trace\"),ZG=l(2,(e,t)=>ia(e,JI,r=>new Set([...r,t]))),YG=l(e=>ws(e[0]),(e,...t)=>ia(e,i1,r=>{let n=t.length===1?{...r,...t[0]}:{...r};return t.length===1||B(n,t[0],t[1]),n})),QG=n1,XG=l(2,(e,t)=>oe(WI,r=>ia(e,c1,n=>[[t,r],...n]))),eV=l(e=>ws(e[0]),(e,t,r)=>Dn(e,n=>{let o=r===void 0?n:r(n);return _f(t,o)})),tV=l(e=>ws(e[0]),(e,t,r)=>Yr(e,n=>{let o=r===void 0?n:r(n);return _f(t,o)})),rV=l(e=>ws(e[0]),(e,t,r)=>Ag(e,n=>{let o=r===void 0?n:r(n);return _f(t,o)})),nV=l(e=>ws(e[0]),(e,t,r)=>lF(e,n=>{let o=r===void 0?n:r(n);return _f(t,o)})),oV=l(e=>ws(e[0]),(e,t,r)=>qc(n=>{let o=n.monotonicTimeNanosUnsafe();return Dn(e,()=>{let s=n.monotonicTimeNanosUnsafe(),a=W_(ct(s),ct(o)),i=r===void 0?a:r(a);return _f(t,i)})})),Rf=class extends Et()(\"effect/Effect/Transaction\"){},sV=e=>Un(t=>{let r=ex(t.context,Rf);if(r&&!uF.has(r))return e;let n=t.getRef(Dr),o=n.currentTimeMillisUnsafe(),s={journal:new Map,retry:!1,attempt:1,retryReason:void 0,start:o,now:o,elapsed:0,elapsedSincePrevious:0},a;return $o(i=>{let c=i(e).pipe(Cs(Rf,s),fF(u=>s.retry?Px(u)?i(iV(s)):Y(()=>L0(s)):ie),so);return C(No({while:()=>!a,body:()=>(s.attempt>1&&aV(s,n.currentTimeMillisUnsafe()),c),step(u){if(s.retry||!mF(s))return s.attempt++,s.retryReason=s.retry?\"retry\":\"conflict\",L0(s);ut(u)&&cV(t,s),L0(s),uF.add(s),a=u}}),()=>a)})}),uF=new WeakSet,aV=(e,t)=>{e.elapsedSincePrevious=t-e.now,e.now=t,e.elapsed=t-e.start},mF=e=>{for(let[t,{version:r}]of e.journal)if(t.version!==r)return!1;return!0},iV=e=>Mf(t=>{if(!mF(e))return t(ie);let r={},n=Array.from(e.journal.keys()),o=()=>{for(let a of n)a.pending.delete(r)},s=()=>{o(),t(ie)};for(let a of n)a.pending.set(r,s);return Y(o)});function cV(e,t){for(let[r,{value:n,written:o}]of t.journal)if(o){Object.is(n,r.value)||(r.version=r.version+1,r.value=n);for(let s of r.pending.values())e.currentDispatcher.scheduleTask(s,0);r.pending.clear()}}function L0(e){e.retry=!1,e.journal.clear()}var uV=C(Rf,e=>{let t=e;return t.retry=!0,io}),fV=(e,t,r)=>(...n)=>Mf(o=>{let s=!0,a;try{e(...n,(i,c)=>{let u=i?t?L(()=>F(t(i,n))):F(i):g(c);s?a??=u:o(u)})}catch(i){a=r?F(r(i,n)):yr(i)}s=!1,a&&o(a)}),lV=()=>e=>e,pV=()=>e=>e,dV=()=>e=>e,fn=GR,Lf=VR,Sr=ZR,Ct=qR,$f=YR,ew=$R;var hF=GE;var xi=Ix,xF=kR,Ko=Dx;var Kf=sa,gi=TM;var br=Symbol.for(\"effect/MutableList/Empty\"),xa=()=>({head:void 0,tail:void 0,length:0}),tw=e=>{let t=e.head;t.offset>=1024&&t===e.tail&&t.mutable&&(t.array.length-t.offset)*8<=t.offset&&(e.head=e.tail={array:t.array.slice(t.offset),mutable:!0,offset:0,next:void 0})},gF=()=>({array:[],mutable:!0,offset:0,next:void 0}),Bo=(e,t)=>{e.tail?e.tail.mutable||(e.tail.next=gF(),e.tail=e.tail.next):e.head=e.tail=gF(),e.tail.array.push(t),e.length++},rw=(e,t)=>{e.head={array:[t],mutable:!0,offset:0,next:e.head},e.tail||(e.tail=e.head),e.length++};var yF=(e,t)=>Md(e,Array.from(t),!0),Md=(e,t,r=!1)=>{if(t.length===0)return 0;let n={array:t,mutable:r,offset:0,next:void 0};return e.head?e.tail=e.tail.next=n:e.head=e.tail=n,e.length+=t.length,t.length},ha=e=>{e.head=e.tail=void 0,e.length=0},Jc=(e,t)=>{if(t=It(t),t<=0||!e.head)return[];if(t=Math.min(t,e.length),t===e.length&&e.head?.offset===0&&!e.head.next){let s=e.head.array;return ha(e),s}let r=new Array(t),n=0,o=e.head;for(;o;){for(;o.offset{if(t=It(t),t<=0||!e.head)return;if(t=Math.min(t,e.length),t===e.length&&e.head?.offset===0&&!e.head.next){ha(e);return}let r=0,n=e.head;for(;n;){let o=n.array.length-n.offset;if(r+o>t){n.offset+=t-r,e.head=n,e.length-=t,tw(e);return}r+=o,n=n.next}ha(e)},yi=e=>Jc(e,e.length),Gc=e=>{if(!e.head)return br;let t=e.head.array[e.head.offset];return e.head.mutable&&(e.head.array[e.head.offset]=void 0),e.head.offset++,e.length--,e.head.offset===e.head.array.length?e.head.next?e.head=e.head.next:ha(e):tw(e),t},SF=(e,t)=>{if(t=It(t),t<=0)return[];let r=Math.min(t,e.length),n=new Array(r),o=0,s=e.head;for(;s;){for(let a=s.offset;a{let r=[],n=e.head,o=0;for(;n;){for(let s=n.offset;snw(e,r=>r!==t);var mV=\"~effect/Queue\",hV=\"~effect/Queue/Enqueue\",xV=\"~effect/Queue/Dequeue\";var ow={_A:D,_E:D},gV={[mV]:ow,[hV]:ow,[xV]:ow,...kr,toJSON(){return{_id:\"effect/Queue\",state:this.state._tag,size:bV(this)}}},uo=e=>se(t=>{let r=Object.create(gV);return r.dispatcher=t.currentDispatcher,r.capacity=e?.capacity??Number.POSITIVE_INFINITY,r.strategy=e?.strategy??\"suspend\",r.messages=xa(),r.scheduleRunning=!1,r.state={_tag:\"Open\",takers:new Set,offers:new Set,awaiters:new Set},z(r)}),Fd=e=>uo({capacity:e});var EF=()=>uo(),Ln=l(2,(e,t)=>be(()=>Pg(e,t)?Fg:e.state._tag===\"Open\"&&e.strategy===\"suspend\"?AV(e,t):wF)),Pg=(e,t)=>e.state._tag!==\"Open\"?!1:e.messages.length>=e.capacity?e.strategy===\"sliding\"?(Gc(e.messages),Bo(e.messages,t),!0):e.capacity<=0&&e.state.takers.size>0?(Bo(e.messages,t),AF(e),!0):!1:(Bo(e.messages,t),Rg(e),!0),Vc=l(2,(e,t)=>Dt(r=>{let n=Mg(e,t);return n.length===0||e.strategy===\"dropping\"?r(We(n)):vF(e,{_tag:\"Array\",remaining:n,offset:0,resume:r})})),Mg=(e,t)=>{if(e.state._tag!==\"Open\")return wt(t);if(e.capacity===Number.POSITIVE_INFINITY||e.strategy===\"sliding\")return yF(e.messages,t),e.strategy===\"sliding\"&&Jc(e.messages,e.messages.length-e.capacity),Rg(e),[];let r=e.capacity<=0?e.state.takers.size:e.capacity-e.messages.length;if(r===0)return wt(t);let n=[],o=0;for(let s of t)oX(()=>Si(e,t))),Si=(e,t)=>{if(e.state._tag!==\"Open\")return!1;let r=Nt(t),n=oP(r,EV);return e.state.offers.size===0&&e.messages.length===0?(Ng(e,n),!0):(e.state={...e.state,_tag:\"Closing\",exit:n},Rg(e),!0)},aw=e=>cr(e,Ju(pc())),Nd=e=>Si(e,Ju(pc()));var fo=e=>X(()=>yV(e)),yV=e=>{if(e.state._tag===\"Done\")return!1;ha(e.messages);let t=e.state.offers;Ng(e,e.state._tag===\"Open\"?IV:e.state.exit);for(let r of t)kF(r);return!0};var Zc=e=>IF(e,1,Number.POSITIVE_INFINITY);var IF=l(3,(e,t,r)=>(t=It(t),r=It(r),CF(()=>wV(e,t,r)??xs(TF(e,()=>iw(e,t)),IF(e,t,r))))),ga=e=>CF(()=>SV(e)??xs(TF(e,()=>iw(e,1)),ga(e)));var SV=e=>{if(e.state._tag===\"Done\")return e.state.exit;if(e.messages.length>0){let t=Gc(e.messages);return sw(e),We(t)}else if(e.capacity<=0&&e.state.offers.size>0){let t=OF(e.state.offers);return sw(e),We(t)}};var bV=e=>e.state._tag===\"Done\"?0:e.messages.length;var wF=We(!1),Fg=We(!0),EV=ko(pc()),IV=bf(),AF=e=>{if(!(e.state._tag===\"Done\"||e.state.takers.size===0)){for(let t of e.state.takers)if(t.ready()&&(e.state.takers.delete(t),t.resume(Ur),e.messages.length===0))break}},Rg=e=>{e.scheduleRunning||e.state._tag===\"Done\"||e.state.takers.size===0||(e.scheduleRunning=!0,e.dispatcher.scheduleTask(()=>{e.scheduleRunning=!1,AF(e)},0))},wV=(e,t,r)=>{if(e.state._tag===\"Done\")return e.state.exit;if(r<=0||t<=0)return We([]);if(!iw(e,t))return;let n=e.messages.length>0?Jc(e.messages,r):[OF(e.state.offers)];return sw(e),We(n)},CF=Zn({op:\"QueueTake\",[lt](e){let t=this[xe]();return Sp(t)?t[lt](e):t}}),iw=(e,t)=>e.messages.length>=(e.state._tag===\"Closing\"?1:Math.min(t,e.capacity||1))||e.capacity<=0&&e.state._tag!==\"Done\"&&e.state.offers.size>0,TF=(e,t)=>Dt(r=>{if(e.state._tag===\"Done\")return r(e.state.exit);if(t())return r(Ur);let n={ready:t,resume:r};return e.state.takers.add(n),X(()=>{e.state._tag!==\"Done\"&&e.state.takers.delete(n)})}),AV=(e,t)=>Dt(r=>Pg(e,t)?r(Fg):vF(e,{_tag:\"Single\",message:t,resume:r})),vF=(e,t)=>{if(e.state._tag!==\"Open\")return kF(t);let r=e.state.offers;return r.add(t),X(()=>{e.state._tag!==\"Done\"&&(r.delete(t),e.state._tag===\"Closing\"&&r.size===0&&e.messages.length===0&&Ng(e,e.state.exit))})},kF=e=>e._tag===\"Single\"?e.resume(wF):e.resume(We(e.remaining.slice(e.offset))),OF=e=>{let t=e.values().next().value;if(t._tag===\"Single\")return e.delete(t),t.resume(Fg),t.message;let r=t.remaining[t.offset++];return t.offset===t.remaining.length&&(e.delete(t),t.resume(We([]))),r},sw=e=>{if(e.state._tag===\"Done\")return Is(e.state.exit.cause);if(e.state.offers.size===0)return e.state._tag===\"Closing\"&&e.messages.length===0?(Ng(e,e.state.exit),Is(e.state.exit.cause)):!1;for(let t of e.state.offers){let r=e.capacity-e.messages.length;if(r<=0)break;if(t._tag===\"Single\")Bo(e.messages,t.message),e.state.offers.delete(t),t.resume(Fg);else{for(;t.offset{if(e.state._tag===\"Done\")return;let r=e.state;e.state={_tag:\"Done\",exit:t};for(let n of r.takers)n.resume(t);r.takers.clear();for(let n of r.awaiters)n(t);r.awaiters.clear()};var bi=Te(\"effect/crypto/WebCrypto\",{defaultValue:()=>globalThis.crypto});var Ei=class extends Et()(\"effect/crypto/SecureRandom\"){};var Ug=e=>new dw(e),lw=e=>{for(let t of e.waiters)if(t.permits<=e.free)return t},pw=(e,t,r,n=D)=>se(o=>{if(e.free>=t&&lw(e)===void 0)return e.taken+=t,r();let s={permits:t,resume:void 0},a=()=>{e.waiters.delete(s)&&e.releaseUnsafe(o,0)};e.waiters.add(s),oi(o,a);let i=n(Dt(u=>{lw(e)===s?u(Se):s.resume=u})),c=oe(i,()=>lw(e)!==s?c:(e.taken+=t,a(),r()));return c}),dw=class{waiters=new Set;taken=0;permits;constructor(t){this.permits=t}get free(){return this.permits-this.taken}take(t){return pw(this,t,()=>z(t))}takeScoped(t){return ro(r=>oe(vc,n=>pw(this,t,()=>Jx(n,this.release(t)),r)))}takeIfAvailable(t){return be(()=>this.free0&&t.currentDispatcher.scheduleTask(()=>{let n=this.free;for(let o of Array.from(this.waiters)){if(!this.waiters.has(o)||o.permits>n)continue;n-=o.permits;let s=o.resume;o.resume=void 0,s?.(Se)}},0),this.free}resize(t){return se(r=>(this.permits=t,this.free<0?Se:(this.releaseUnsafe(r,0),Se)))}release(t){return se(r=>z(this.releaseUnsafe(r,t)))}get releaseAll(){return se(t=>z(this.releaseUnsafe(t,this.taken)))}withPermits(t){return r=>ro(n=>pw(this,t,()=>Po(n(r),()=>{this.releaseUnsafe(sa(),t)},!0),n))}withPermit=this.withPermits(1);withPermitsIfAvailable(t){return r=>ro(n=>this.free{this.releaseUnsafe(sa(),t)},!0)))}};var hw=1e4,hde=2*hw,RF=/^[+-]?\\d+$/,xw=\"~effect/BigDecimal\",CV={[xw]:xw,[re](){let e=yw(this);return Ee(Pe(String(e.value)),Lt(e.scale))},[ne](e){return gw(e)&&LF(this,e)===0},toString(){return`BigDecimal(${ya(this)})`},toJSON(){return{_id:\"BigDecimal\",value:String(this.value),scale:this.scale}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},gw=e=>A(e,xw),FF=(e,t)=>{if(!Number.isSafeInteger(t))throw new RangeError(`Scale must be a safe integer, got ${t}`);let r=Object.create(CV);return r.value=e,r.scale=t,r},NF=(e,t)=>{let r=FF(e,t);return r.normalized=r,r};var lo=BigInt(0),TV=BigInt(1);var vV=BigInt(10),UF=NF(lo,0);var yw=e=>{if(e.normalized===void 0)if(e.value===lo)e.normalized=UF;else{let t=`${e.value}`,r=DF(t);e.normalized=NF(BigInt(t.slice(0,t.length-r)),e.scale-r)}return e.normalized},DF=e=>{let t=e.length;for(;e[t-1]===\"0\";)t--;return e.length-t};var kV=100,OV=[TV],mw=(e,t)=>e===t?0:e{let r=`${e.value{if(e.scale===t.scale)return mw(e.value,t.value);let r=MF(e),n=MF(t);if(r!==n)return rkV)return r===-1?PF(t,e):PF(e,t);let a=OV[s]??=vV**BigInt(s);return o>0?mw(e.value,t.value*a):mw(e.value*a,t.value)},Bf=qa(LF);var MF=e=>e.value===lo?0:e.value{if(e===\"\")return _(UF);let t,r,n=e.search(/[eE]/);if(n!==-1){let f=e.slice(n+1);if(t=e.slice(0,n),r=Number(f),t===\"\"||!Number.isSafeInteger(r)||!RF.test(f))return v()}else t=e,r=0;let o,s,a=t.search(/\\./);if(a!==-1){let f=t.slice(0,a),p=t.slice(a+1);if(!/^\\d*$/.test(p))return v();o=`${f}${p}`,s=p.length}else o=t,s=0;if(!RF.test(o))return v();let i=s-r,c=BigInt(o),u=c===lo?i:i-DF(o);return i>hw||u<-hw?v():_(FF(c,i))};var ya=e=>{let t=yw(e);if(Math.abs(t.scale)>=16)return _V(t);let r=t.value0?n.padStart(t.scale+1,\"0\"):n.padEnd(n.length-t.scale,\"0\"),s=o.length-t.scale,a=t.scale>0?`${o.slice(0,s)}.${o.slice(s)}`:o;return r?`-${a}`:a},_V=e=>{if(RV(e))return\"0e+0\";let t=yw(e),r=`${t.value}`,n=t.value=0?\"+\":\"\"}${a}`};var RV=e=>e.value===lo;var Ie={};An(Ie,{AeadKey:()=>Mv,AeadKeyFromBytes:()=>$ne,AeadKeyFromFormat:()=>Kne,Any:()=>Iee,Array:()=>Be,ArrayEnsure:()=>Mee,BigDecimal:()=>zB,BigDecimalFromString:()=>xre,BigInt:()=>Nl,BigIntFromString:()=>tre,Boolean:()=>Gm,BooleanFromBit:()=>cre,BooleanLiterals:()=>Sv,ByteSize:()=>$l,ByteSizeFromBigInt:()=>yre,ByteSizeFromNumber:()=>Sre,ByteSizeFromString:()=>gre,Cause:()=>dv,CauseReason:()=>pv,Char:()=>Kte,Chunk:()=>bre,CipherKey:()=>Fv,CipherKeyFromBytes:()=>Bne,CipherKeyFromFormat:()=>jne,Class:()=>Vj,Cookie:()=>Dj,Cookies:()=>Lj,Date:()=>Dl,DateFromMillis:()=>Gte,DateFromString:()=>Jte,DateTimeUtc:()=>Kl,DateTimeUtcFromDate:()=>Tre,DateTimeUtcFromHttpDate:()=>Ore,DateTimeUtcFromMillis:()=>_re,DateTimeUtcFromString:()=>vre,DateTimeZoned:()=>ij,DateTimeZonedFromString:()=>Fre,Defect:()=>jte,DnsARecord:()=>Ij,DnsAaaaRecord:()=>wj,DnsCaaRecord:()=>Aj,DnsCnameRecord:()=>Cj,DnsMxRecord:()=>Tj,DnsNaptrRecord:()=>vj,DnsNsRecord:()=>kj,DnsPtrRecord:()=>Oj,DnsRecord:()=>Rne,DnsRecordType:()=>_ne,DnsSoaRecord:()=>_j,DnsSrvRecord:()=>Rj,DnsTlsaRecord:()=>Pj,DnsTxtRecord:()=>Mj,DomainName:()=>Ua,DomainNameFromString:()=>gj,Duration:()=>vu,DurationFromIsoString:()=>One,DurationFromMillis:()=>kne,DurationFromNanos:()=>vne,DurationFromString:()=>Rv,Enum:()=>Eee,Error:()=>Zj,ErrorInstance:()=>Bte,Exit:()=>toe,FalseLiterals:()=>SB,File:()=>UB,Finite:()=>Ul,FiniteFromString:()=>ere,FormData:()=>DB,Graph:()=>soe,HashMap:()=>aoe,HashSet:()=>ioe,Headers:()=>poe,Host:()=>yne,HostFromString:()=>Sne,HostPort:()=>Sj,HostPortFromString:()=>bne,InetAddress:()=>hj,InetAddressFromString:()=>hne,InetAddressV4:()=>dne,InetAddressV6:()=>mne,Int:()=>en,IpAddress:()=>Wi,IpAddressFromString:()=>Tu,IpInterface:()=>lj,IpInterfaceFromString:()=>une,IpLinkLocalAddress:()=>Vre,IpLinkLocalAddressFromString:()=>Zre,IpLoopbackAddress:()=>Jre,IpLoopbackAddressFromString:()=>Gre,IpMulticastAddress:()=>Nre,IpMulticastAddressFromString:()=>Ure,IpNetwork:()=>mj,IpNetworkFromString:()=>pne,IpUnicastAddress:()=>$re,IpUnicastAddressFromString:()=>Kre,IpUnspecifiedAddress:()=>Yre,IpUnspecifiedAddressFromString:()=>Qre,Ipv4Address:()=>rh,Ipv4AddressFromString:()=>Ov,Ipv4BroadcastAddress:()=>Hre,Ipv4BroadcastAddressFromString:()=>zre,Ipv4Interface:()=>uj,Ipv4InterfaceFromString:()=>ine,Ipv4Network:()=>pj,Ipv4NetworkFromString:()=>fne,Ipv4PrivateAddress:()=>Xre,Ipv4PrivateAddressFromString:()=>ene,Ipv6Address:()=>$S,Ipv6AddressFromString:()=>cj,Ipv6Interface:()=>fj,Ipv6InterfaceFromString:()=>cne,Ipv6Network:()=>dj,Ipv6NetworkFromString:()=>lne,Ipv6UniqueLocalAddress:()=>tne,Ipv6UniqueLocalAddressFromString:()=>rne,Json:()=>BS,JsonFromUrlParamsField:()=>hoe,JsonObject:()=>qoe,KeyAgreementPrivateKey:()=>Lv,KeyAgreementPrivateKeyFromBytes:()=>Vne,KeyAgreementPrivateKeyFromFormat:()=>Zne,KeyAgreementPublicKey:()=>Dv,KeyAgreementPublicKeyFromBytes:()=>Jne,KeyAgreementPublicKeyFromFormat:()=>Gne,KeyWrapKey:()=>$v,KeyWrapKeyFromBytes:()=>Yne,KeyWrapKeyFromFormat:()=>Qne,KeyWrapPrivateKey:()=>Uj,KeyWrapPrivateKeyFromFormat:()=>eoe,KeyWrapPublicKey:()=>Nj,KeyWrapPublicKeyFromFormat:()=>Xne,Literal:()=>zt,Literals:()=>Jn,MacAddress:()=>Cu,MacAddressFromString:()=>Bl,MacBroadcastAddress:()=>Wre,MacBroadcastAddressFromString:()=>qre,MacKey:()=>Pv,MacKeyFromBytes:()=>Dne,MacKeyFromFormat:()=>Lne,MacLocallyAdministeredAddress:()=>nne,MacLocallyAdministeredAddressFromString:()=>one,MacMulticastAddress:()=>Dre,MacMulticastAddressFromString:()=>Lre,MacUnicastAddress:()=>Bre,MacUnicastAddressFromString:()=>jre,MacUniversallyAdministeredAddress:()=>sne,MacUniversallyAdministeredAddressFromString:()=>ane,MutableJson:()=>Goe,Natural:()=>ts,Never:()=>iB,NonEmptyArray:()=>FS,NonEmptyString:()=>th,Null:()=>PS,NullOr:()=>yv,NullishOr:()=>lB,Number:()=>wu,NumberFromString:()=>Xte,ObjectKeyword:()=>Cee,Opaque:()=>qee,Option:()=>ku,OptionFromNullOr:()=>coe,OptionFromNullishOr:()=>foe,OptionFromOptional:()=>yoe,OptionFromOptionalKey:()=>goe,OptionFromOptionalNullOr:()=>Soe,OptionFromUndefinedOr:()=>uoe,Port:()=>Ene,PropertyKey:()=>lv,ReadonlyMap:()=>Hte,ReadonlySet:()=>zte,Record:()=>Na,RecordFromCookies:()=>loe,RecordFromUrlParams:()=>xoe,Redacted:()=>KS,RedactedFromValue:()=>boe,RegExp:()=>Wte,Result:()=>Eoe,RetryAfter:()=>$j,RetryAfterFromString:()=>moe,SchemaError:()=>Ma,ScopedIpv6Literal:()=>_v,ScopedIpv6LiteralFromString:()=>yj,SemVer:()=>zj,SemVerFromString:()=>Ioe,SemVerRange:()=>Jj,SemVerRangeFromString:()=>woe,SignaturePrivateKey:()=>Uv,SignaturePrivateKeyFromBytes:()=>Wne,SignaturePrivateKeyFromFormat:()=>qne,SignaturePublicKey:()=>Nv,SignaturePublicKeyFromBytes:()=>Hne,SignaturePublicKeyFromFormat:()=>zne,SocketAddress:()=>gne,StandardSchemaV1FailureResult:()=>ire,String:()=>H,StringForLiteralAutocomplete:()=>wee,StringFromBase64:()=>nre,StringFromBase64Url:()=>ore,StringFromHex:()=>sre,StringFromUriComponent:()=>are,Struct:()=>ve,StructWithRest:()=>Ree,Symbol:()=>cB,TaggedClass:()=>voe,TaggedError:()=>koe,TaggedStruct:()=>Vm,TaggedUnion:()=>Wee,TemplateLiteral:()=>See,TemplateLiteralParser:()=>bee,TimeZone:()=>sj,TimeZoneFromString:()=>Mre,TimeZoneNamed:()=>nj,TimeZoneNamedFromString:()=>Pre,TimeZoneOffset:()=>Rre,Tree:()=>Woe,Trim:()=>rre,Trimmed:()=>$B,TrueLiterals:()=>yB,Tuple:()=>Ds,TupleWithRest:()=>Pee,URL:()=>LS,URLFromString:()=>qte,URLSearchParams:()=>LB,Uint8Array:()=>Ll,Uint8ArrayFromBase64:()=>ure,Uint8ArrayFromBase64Url:()=>fre,Uint8ArrayFromHex:()=>BB,Undefined:()=>xv,UndefinedOr:()=>NS,Union:()=>st,UniqueArray:()=>Fee,UniqueSymbol:()=>Tee,UnixPathAddress:()=>xj,UnixPathAddressFromString:()=>xne,Unknown:()=>Fl,UnknownFromJsonString:()=>Zte,UrlParams:()=>Kv,Void:()=>Aee,annotate:()=>qX,annotateEncoded:()=>JX,annotateKey:()=>GX,asserts:()=>XX,brand:()=>US,catchDecoding:()=>Lee,catchDecodingWithContext:()=>xB,catchEncoding:()=>$ee,catchEncodingWithContext:()=>gB,check:()=>Uee,declare:()=>je,declareConstructor:()=>yn,decode:()=>Kee,decodeEffect:()=>eee,decodeExit:()=>tee,decodeOption:()=>nee,decodePromise:()=>see,decodeResult:()=>oee,decodeSync:()=>aee,decodeTo:()=>J,decodeUnknownEffect:()=>OS,decodeUnknownExit:()=>QK,decodeUnknownOption:()=>ree,decodeUnknownPromise:()=>eB,decodeUnknownResult:()=>XK,decodeUnknownSync:()=>tB,encode:()=>Bee,encodeEffect:()=>iee,encodeExit:()=>cee,encodeKeys:()=>Oee,encodeOption:()=>fee,encodePromise:()=>pee,encodeResult:()=>lee,encodeSync:()=>dee,encodeTo:()=>bv,encodeUnknownEffect:()=>_S,encodeUnknownExit:()=>rB,encodeUnknownOption:()=>uee,encodeUnknownPromise:()=>oB,encodeUnknownResult:()=>nB,encodeUnknownSync:()=>sB,extendTo:()=>_ee,fieldsAssign:()=>vee,flip:()=>fv,fromBrand:()=>Dee,fromFormData:()=>Yte,fromJsonString:()=>vv,fromURLSearchParams:()=>Qte,instanceOf:()=>Au,is:()=>QX,isAscii:()=>ote,isBase64:()=>CB,isBase64Url:()=>ste,isBetween:()=>Ls,isBetweenBigDecimal:()=>hre,isBetweenBigInt:()=>Ote,isBetweenCodePoints:()=>Pte,isBetweenDate:()=>Cte,isBetweenLength:()=>Av,isBetweenProperties:()=>Lte,isBetweenSize:()=>Nte,isCapitalized:()=>lte,isEndingWith:()=>ite,isFinite:()=>dte,isGUID:()=>ete,isGreaterThan:()=>hte,isGreaterThanBigDecimal:()=>lre,isGreaterThanBigInt:()=>Tte,isGreaterThanDate:()=>Ete,isGreaterThanOrEqualTo:()=>TB,isGreaterThanOrEqualToBigDecimal:()=>pre,isGreaterThanOrEqualToBigInt:()=>vB,isGreaterThanOrEqualToDate:()=>Ite,isIncluding:()=>cte,isInt:()=>DS,isInt32:()=>Ste,isLessThan:()=>xte,isLessThanBigDecimal:()=>dre,isLessThanBigInt:()=>vte,isLessThanDate:()=>wte,isLessThanOrEqualTo:()=>gte,isLessThanOrEqualToBigDecimal:()=>mre,isLessThanOrEqualToBigInt:()=>kte,isLessThanOrEqualToDate:()=>Ate,isLowercased:()=>fte,isMaxCodePoints:()=>Rte,isMaxLength:()=>_B,isMaxProperties:()=>Dte,isMaxSize:()=>Fte,isMinCodePoints:()=>_te,isMinLength:()=>wv,isMinProperties:()=>Ute,isMinSize:()=>Mte,isMultipleOf:()=>yte,isNonEmpty:()=>OB,isPattern:()=>zi,isPropertyNames:()=>$te,isSchema:()=>RS,isSchemaError:()=>JK,isStartingWith:()=>ate,isStringBigInt:()=>Vee,isStringFinite:()=>Gee,isStringSymbol:()=>Zee,isTrimmed:()=>AB,isULID:()=>rte,isUUID:()=>Qee,isUint32:()=>bte,isUncapitalized:()=>pte,isUnique:()=>Tv,isUniqueKey:()=>RB,isUppercased:()=>ute,link:()=>ke,linkDecoding:()=>Hi,make:()=>Q,makeClassTrusted:()=>jv,makeFilter:()=>Ne,makeFilterGroup:()=>Jee,makeIsBetween:()=>eh,makeIsGreaterThan:()=>Zm,makeIsGreaterThanOrEqualTo:()=>Ym,makeIsLessThan:()=>Qm,makeIsLessThanOrEqualTo:()=>Xm,makeIsMultipleOf:()=>mte,middlewareDecoding:()=>mB,middlewareEncoding:()=>hB,mutable:()=>Nee,mutableKey:()=>xee,optional:()=>Pl,optionalKey:()=>rs,overrideToCodecIso:()=>Hoe,overrideToEquivalence:()=>Roe,overrideToFormatter:()=>Ooe,readonlyKey:()=>gee,refine:()=>dB,required:()=>hee,requiredKey:()=>mee,resolveAnnotations:()=>Voe,resolveAnnotationsKey:()=>Zoe,revealBottom:()=>WX,revealCodec:()=>VX,suspend:()=>pB,tag:()=>Fa,tagDefaultOmit:()=>zee,toCodecArrayFromSingle:()=>Doe,toCodecGoJson:()=>Loe,toCodecIso:()=>Uoe,toCodecJson:()=>Noe,toCodecStringTree:()=>oh,toDifferJsonPatch:()=>zoe,toEncoded:()=>Ml,toEncoderXml:()=>$oe,toEquivalence:()=>Poe,toFormatter:()=>_oe,toIso:()=>Koe,toIsoFocus:()=>joe,toIsoSource:()=>Boe,toJsonSchemaDocument:()=>Foe,toRepresentation:()=>Moe,toStandardJSONSchemaV1:()=>YX,toStandardSchemaV1:()=>ZX,toTaggedUnion:()=>wB,toType:()=>Sn,withArrayLengthConstraints:()=>MS,withConstructorDefault:()=>bB,withDecodingDefault:()=>IB,withDecodingDefaultKey:()=>Ev,withDecodingDefaultType:()=>Hee,withDecodingDefaultTypeKey:()=>jee});var BF=globalThis.BigInt;var jF=e=>e>BF(Number.MAX_SAFE_INTEGER)||ee.names.map(t=>[t,e])));var bw=e=>e;var jf=e=>{throw new Error(`Invalid ByteSize: ${e}`)},WF=e=>!Number.isSafeInteger(e)||e<0?jf(`expected a non-negative safe integer, received ${e}`):bw(BigInt(e)),_de=BigInt(Number.MAX_SAFE_INTEGER),UV=(e,t)=>{let r=/^(\\d+)(?:\\.(\\d+))?(?:e([+-]\\d+))?$/.exec(e);if(r===null)return;let n=r[2]??\"\",o=BigInt(r[1]+n)*t,s=Number(r[3]??0)-n.length;if(s>=0)return o*BigInt(10)**BigInt(s);let a=BigInt(10)**BigInt(-s);return o%a===Sw?o/a:void 0};var qF=e=>{let t=/^\\s*(\\d+(?:\\.\\d+)?)\\s*([A-Za-z]+)\\s*$/.exec(e);if(t===null)return jf(`unsupported syntax ${JSON.stringify(e)}`);let r=NV.get(t[2]);if(r===void 0)return jf(`unsupported unit ${JSON.stringify(t[2])}`);let n=UV(t[1],r.factor);return n===void 0?jf(`${JSON.stringify(e)} does not represent an integral number of bytes`):bw(n)},JF=Oo(qF),Dg=e=>{switch(typeof e){case\"bigint\":return etypeof e==\"bigint\"?Dg(e):WF(e);var VF=e=>typeof e==\"bigint\"&&e>=Sw;var Lg=e=>e,ZF=jF;var QF=\"~effect/Chunk\";function YF(e,t,r,n,o){for(let s=t;sKt((t,r)=>{if(t.length!==r.length)return!1;let n=Yc(t),o=Yc(r);for(let s=0;se},toString(){return`Chunk(${K(Yc(this))})`},toJSON(){return{_id:\"Chunk\",values:qt(Yc(this))}},[Je](){return this.toJSON()},[ne](e){return Kg(e)&&$V(this,e)},[re](){return wo(Yc(this))},[Symbol.iterator](){switch(this.backing._tag){case\"IArray\":return this.backing.array[Symbol.iterator]();case\"IEmpty\":return XF[Symbol.iterator]();default:return Yc(this)[Symbol.iterator]()}},pipe(){return te(this,arguments)}},Aw=e=>{let t=Object.create(KV);switch(t.backing=e,e._tag){case\"IEmpty\":{t.length=0,t.depth=0,t.left=t,t.right=t;break}case\"IConcat\":{t.length=e.left.length+e.right.length,t.depth=1+Math.max(e.left.depth,e.right.depth),t.left=e.left,t.right=e.right;break}case\"IArray\":{t.length=e.array.length,t.depth=0,t.left=Sa,t.right=Sa;break}case\"ISingleton\":{t.length=1,t.depth=0,t.left=Sa,t.right=Sa;break}case\"ISlice\":{t.length=e.length,t.depth=0,t.left=Sa,t.right=Sa;break}}return t},Kg=e=>A(e,QF),Sa=Aw({_tag:\"IEmpty\"}),BV=()=>Sa;var jV=e=>Aw({_tag:\"ISingleton\",a:e}),Cw=e=>Kg(e)?e:zV(wt(e)),Iw=(e,t,r)=>{switch(e.backing._tag){case\"IArray\":{YF(e.backing.array,0,t,r,e.length);break}case\"IConcat\":{Iw(e.left,t,r),Iw(e.right,t,r+e.left.length);break}case\"ISingleton\":{t[r]=e.backing.a;break}case\"ISlice\":{YF(Yc(e.backing.chunk),e.backing.offset,t,r,e.length);break}}};var HV=e=>{switch(e.backing._tag){case\"IEmpty\":return XF;case\"IArray\":return e.backing.array;default:{let t=new Array(e.length);return Iw(e,t,0),e.backing={_tag:\"IArray\",array:t},e.left=Sa,e.right=Sa,e.depth=0,t}}},Yc=HV;var zV=e=>e.length===0?BV():e.length===1?jV(e[0]):Aw({_tag:\"IArray\",array:e});var eN=e=>e.length;var qg={};An(qg,{Aead:()=>jd,aes128Gcm:()=>dZ,aes256Gcm:()=>mZ,chacha20Poly1305:()=>hZ,fromCryptoKey:()=>IZ,isKey:()=>Nw,key:()=>Uw,layerWebCrypto:()=>EZ,layerWebCryptoWith:()=>SN,toBytes:()=>Dw,xchacha20Poly1305:()=>xZ});var tN=\"~effect/crypto/CryptoError\",ks=\"~effect/crypto/CryptoError/Reason\",Qc=class extends Ut(\"InvalidArgument\"){[ks]=ks;get message(){return this.description}},ba=class extends Ut(\"InvalidKey\"){[ks]=ks;get message(){return this.description}},wi=class extends Ut(\"DecryptionFailed\"){[ks]=ks;get message(){return\"Could not decrypt the data\"}},Ai=class extends Ut(\"Unsupported\"){[ks]=ks;get message(){return this.description}},Bg=class extends Ut(\"NotExtractable\"){[ks]=ks;get message(){return this.description}},Hf=class extends Ut(\"CryptoError\"){[tN]=tN;cause=\"cause\"in this.reason?this.reason.cause:void 0;get message(){return`${this.module}.${this.method}: ${this.reason.message}`}};function rN(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===\"Uint8Array\"&&\"BYTES_PER_ELEMENT\"in e&&e.BYTES_PER_ELEMENT===1}var jg=e=>e?`\"${e}\" `:\"\";function vw(e,t=\"\"){if(typeof e!=\"boolean\")throw new TypeError(jg(t)+\"expected boolean, got type=\"+typeof e);return e}function zf(e,t=\"\"){if(typeof e!=\"number\")throw new TypeError(jg(t)+\"expected number, got \"+typeof e);if(!Number.isSafeInteger(e)||e<0)throw new RangeError(jg(t)+\"expected integer >= 0, got \"+e);return e}function po(e,t,r=\"\"){if(rN(e)&&(t===void 0||e.length===t))return e;t!==void 0&&zf(t,\"length\");let n=rN(e),o=t!==void 0?` of length ${t}`:\"\",s=n?`length=${e.length}`:`type=${typeof e}`,a=jg(r)+\"expected Uint8Array\"+o+\", got \"+s;throw n?new RangeError(a):new TypeError(a)}var nN=(e,t)=>{if(e===null||typeof e!=\"object\"||Array.isArray(e))throw new TypeError(t===\"object\"?\"expected valid options object\":`\"${t}\" expected object, got type=${typeof e}`)};function WV(e,t){return nN(e,\"defaults\"),nN(t,\"opts\"),Object.assign(e,t)}function oN(e,t=!0){if(e.destroyed)throw new Error(\"hash was destroyed\");if(t&&e.finished)throw new Error(\"digest() was already called\")}function qV(e,t){po(e,void 0,\"output\");let r=t.outputLen;if(!(e.length>=r))throw new RangeError('\"output\" expected length >= '+r)}function Ea(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function _s(...e){for(let t=0;t>>8&65280|e>>>24&255}function VV(e){for(let t=0;te:VV;function ZV(e,t){return!e.byteLength||!t.byteLength?!1:e.buffer===t.buffer&&e.byteOffsetUint8Array.from(e.split(\"\"),t=>t.charCodeAt(0)),eZ=jo(Ea(cN(\"expand 16-byte k\"))),tZ=jo(Ea(cN(\"expand 32-byte k\")));function Ye(e,t){return e<>>32-t}var Dd=64,rZ=16,Ow=2**32-1,sN=Uint32Array.of();function nZ(e,t,r,n,o,s,a,i){let c=o.length,u=new Uint8Array(Dd),f=Ea(u),p=Os&&Hg(o)&&Hg(s),d=p?Ea(o):sN,m=p?Ea(s):sN;if(!Os){for(let h=0;h=Ow)throw new Error(\"arx: counter overflow\");let y=Math.min(Dd,c-h);for(let S=0,b;S=Ow)throw new Error(\"arx: counter overflow\");let y=Math.min(Dd,c-h);if(p&&y===Dd){let S=h/4;if(h%4!==0)throw new Error(\"arx: invalid block position\");for(let b=0,x;b{po(i,void 0,\"key\"),po(c,void 0,\"nonce\"),po(u,void 0,\"data\");let d=u.length,m=f!==void 0;if(f=kw(d,f,!1),m&&YV(u,f),zf(p),p<0||p>=Ow)throw new Error(\"arx: counter overflow\");let h=[],y=i.length,S,b;if(y===32)h.push(S=zg(i)),b=tZ;else if(y===16&&r)S=new Uint8Array(32),S.set(i),S.set(i,16),b=eZ,h.push(S);else throw po(i,32,\"arx key\"),new Error(\"invalid key size\");(!Os||!Hg(c))&&h.push(c=zg(c));let x=Ea(S);if(n){if(c.length!==24)throw new Error(\"arx: extended nonce must be 24 bytes\");let T=c.subarray(0,16);if(Os)n(b,x,Ea(T),x);else{let P=jo(Uint32Array.from(b));n(P,x,Ea(T),x),_s(P),jo(x)}c=c.subarray(16)}else Os||jo(x);let w=16-o;if(w!==c.length)throw new Error(`arx: nonce must be ${w} or 16 bytes`);if(w!==12){let T=new Uint8Array(12);T.set(c,s?0:12-c.length),c=T,h.push(c)}let I=jo(Ea(c));try{return nZ(e,b,x,I,u,f,p,a),f}finally{_s(...h)}}}function _r(e,t){return e[t++]&255|(e[t++]&255)<<8}var _w=class{blockLen=16;outputLen=16;buffer=new Uint8Array(16);r=new Uint16Array(10);h=new Uint16Array(10);pad=new Uint16Array(8);pos=0;finished=!1;destroyed=!1;constructor(t){t=zg(po(t,32,\"key\"));let r=_r(t,0),n=_r(t,2),o=_r(t,4),s=_r(t,6),a=_r(t,8),i=_r(t,10),c=_r(t,12),u=_r(t,14);this.r[0]=r&8191,this.r[1]=(r>>>13|n<<3)&8191,this.r[2]=(n>>>10|o<<6)&7939,this.r[3]=(o>>>7|s<<9)&8191,this.r[4]=(s>>>4|a<<12)&255,this.r[5]=a>>>1&8190,this.r[6]=(a>>>14|i<<2)&8191,this.r[7]=(i>>>11|c<<5)&8065,this.r[8]=(c>>>8|u<<8)&8191,this.r[9]=u>>>5&127;for(let f=0;f<8;f++)this.pad[f]=_r(t,16+2*f)}process(t,r,n=!1){let o=n?0:2048,{h:s,r:a}=this,i=a[0],c=a[1],u=a[2],f=a[3],p=a[4],d=a[5],m=a[6],h=a[7],y=a[8],S=a[9],b=_r(t,r+0),x=_r(t,r+2),w=_r(t,r+4),I=_r(t,r+6),T=_r(t,r+8),P=_r(t,r+10),G=_r(t,r+12),he=_r(t,r+14),me=s[0]+(b&8191),E=s[1]+((b>>>13|x<<3)&8191),R=s[2]+((x>>>10|w<<6)&8191),N=s[3]+((w>>>7|I<<9)&8191),O=s[4]+((I>>>4|T<<12)&8191),M=s[5]+(T>>>1&8191),U=s[6]+((T>>>14|P<<2)&8191),pe=s[7]+((P>>>11|G<<5)&8191),He=s[8]+((G>>>8|he<<8)&8191),ze=s[9]+(he>>>5|o),ee=0,Qe=ee+me*i+E*(5*S)+R*(5*y)+N*(5*h)+O*(5*m);ee=Qe>>>13,Qe&=8191,Qe+=M*(5*d)+U*(5*p)+pe*(5*f)+He*(5*u)+ze*(5*c),ee+=Qe>>>13,Qe&=8191;let qe=ee+me*c+E*i+R*(5*S)+N*(5*y)+O*(5*h);ee=qe>>>13,qe&=8191,qe+=M*(5*m)+U*(5*d)+pe*(5*p)+He*(5*f)+ze*(5*u),ee+=qe>>>13,qe&=8191;let et=ee+me*u+E*c+R*i+N*(5*S)+O*(5*y);ee=et>>>13,et&=8191,et+=M*(5*h)+U*(5*m)+pe*(5*d)+He*(5*p)+ze*(5*f),ee+=et>>>13,et&=8191;let De=ee+me*f+E*u+R*c+N*i+O*(5*S);ee=De>>>13,De&=8191,De+=M*(5*y)+U*(5*h)+pe*(5*m)+He*(5*d)+ze*(5*p),ee+=De>>>13,De&=8191;let xt=ee+me*p+E*f+R*u+N*c+O*i;ee=xt>>>13,xt&=8191,xt+=M*(5*S)+U*(5*y)+pe*(5*h)+He*(5*m)+ze*(5*d),ee+=xt>>>13,xt&=8191;let vt=ee+me*d+E*p+R*f+N*u+O*c;ee=vt>>>13,vt&=8191,vt+=M*i+U*(5*S)+pe*(5*y)+He*(5*h)+ze*(5*m),ee+=vt>>>13,vt&=8191;let vr=ee+me*m+E*d+R*p+N*f+O*u;ee=vr>>>13,vr&=8191,vr+=M*c+U*i+pe*(5*S)+He*(5*y)+ze*(5*h),ee+=vr>>>13,vr&=8191;let is=ee+me*h+E*m+R*d+N*p+O*f;ee=is>>>13,is&=8191,is+=M*u+U*c+pe*i+He*(5*S)+ze*(5*y),ee+=is>>>13,is&=8191;let Ws=ee+me*y+E*h+R*m+N*d+O*p;ee=Ws>>>13,Ws&=8191,Ws+=M*f+U*u+pe*c+He*i+ze*(5*S),ee+=Ws>>>13,Ws&=8191;let ju=ee+me*S+E*y+R*h+N*m+O*d;ee=ju>>>13,ju&=8191,ju+=M*p+U*f+pe*u+He*c+ze*i,ee+=ju>>>13,ju&=8191,ee=(ee<<2)+ee|0,ee=ee+Qe|0,Qe=ee&8191,ee=ee>>>13,qe+=ee,s[0]=Qe,s[1]=qe,s[2]=et,s[3]=De,s[4]=xt,s[5]=vt,s[6]=vr,s[7]=is,s[8]=Ws,s[9]=ju}finalize(){let{h:t,pad:r}=this,n=new Uint16Array(10),o=t[1]>>>13;t[1]&=8191;for(let i=2;i<10;i++)t[i]+=o,o=t[i]>>>13,t[i]&=8191;t[0]+=o*5,o=t[0]>>>13,t[0]&=8191,t[1]+=o,o=t[1]>>>13,t[1]&=8191,t[2]+=o,n[0]=t[0]+5,o=n[0]>>>13,n[0]&=8191;for(let i=1;i<10;i++)n[i]=t[i]+o,o=n[i]>>>13,n[i]&=8191;n[9]-=8192;let s=(o^1)-1;for(let i=0;i<10;i++)n[i]&=s;s=~s;for(let i=0;i<10;i++)t[i]=t[i]&s|n[i];t[0]=(t[0]|t[1]<<13)&65535,t[1]=(t[1]>>>3|t[2]<<10)&65535,t[2]=(t[2]>>>6|t[3]<<7)&65535,t[3]=(t[3]>>>9|t[4]<<4)&65535,t[4]=(t[4]>>>12|t[5]<<1|t[6]<<14)&65535,t[5]=(t[6]>>>2|t[7]<<11)&65535,t[6]=(t[7]>>>5|t[8]<<8)&65535,t[7]=(t[8]>>>8|t[9]<<5)&65535;let a=t[0]+r[0];t[0]=a&65535;for(let i=1;i<8;i++)a=(t[i]+r[i]|0)+(a>>>16)|0,t[i]=a&65535;_s(n)}update(t){oN(this),po(t),t=zg(t);let{buffer:r,blockLen:n}=this,o=t.length;for(let s=0;s>>0,t[s++]=n[a]>>>8}digest(){let{buffer:t,outputLen:r}=this;this.digestInto(t);let n=t.slice(0,r);return this.destroy(),n}};function Rw(e,t,r,n,o,s=20){let a=e[0],i=e[1],c=e[2],u=e[3],f=t[0],p=t[1],d=t[2],m=t[3],h=t[4],y=t[5],S=t[6],b=t[7],x=o,w=r[0],I=r[1],T=r[2],P=a,G=i,he=c,me=u,E=f,R=p,N=d,O=m,M=h,U=y,pe=S,He=b,ze=x,ee=w,Qe=I,qe=T;for(let De=0;De{e.update(t);let r=t.length%16;r&&e.update(iZ.subarray(r))},cZ=new Uint8Array(32);function iN(e,t,r,n,o){o!==void 0&&po(o,void 0,\"AAD\");let s=e(t,r,cZ),a=XV(n.length,o?o.length:0,!0),i=new _w(s);o&&aN(i,o),aN(i,n),i.update(a);let c=i.digest();return _s(s,a),c}var fN=e=>(t,r,n)=>({encrypt(s,a){let i=s.length;a=kw(i+16,a,!1),a.set(s);let c=a.subarray(0,-16);e(t,r,c,c,1);let u=iN(e,t,r,c,n);return a.set(u,i),_s(u),a},decrypt(s,a){a=kw(s.length-16,a,!1);let i=s.subarray(0,-16),c=s.subarray(-16),u=iN(e,t,r,i,n);if(!QV(c,u)){_s(u);return}return a.set(s.subarray(0,-16)),e(t,r,a,a,1),_s(u),a}}),lN=fN(sZ),pN=fN(aZ);var fZ=()=>new Error(\"crypto.subtle is unavailable; browsers expose it only in secure contexts\"),Ia=(e,t,r)=>F(new Hf({module:e,method:t,reason:r})),Ci=(e,t,r)=>Ia(e,t,new ba({description:r})),$d=(e,t)=>Ia(e,t,new Bg({description:\"The CryptoKey is not extractable\"})),Pw=(e,t)=>r=>Ia(e,t,r.reason),Ld=class{reason;constructor(t){this.reason=t}};var Wf=(e,t,r,n,o)=>dN(e,t,`${e}.layerWebCrypto`,r,n,o),dN=(e,t,r,n,o,s)=>{let a=lZ(t,r,n,o,s);if(a===void 0)throw o;return new Hf({module:e,method:t,reason:a})},lZ=(e,t,r,n,o)=>{if(n instanceof Ld)return n.reason;switch(A(n,\"name\")?n.name:void 0){case\"DataError\":return new ba({description:\"Invalid key data\",cause:n});case\"InvalidAccessError\":return new ba({description:`The key cannot be used for ${e}`,cause:n});case\"NotSupportedError\":return new Ai({description:`${t} does not provide ${r}`,cause:n});case\"OperationError\":return o?.();default:return}},wa=(e,t,r,n,o,s=a=>Wf(e,t,r,a))=>L(()=>{let a=n?.subtle;return a===void 0?yr(fZ()):fi({try:()=>o(a),catch:s})}),Kd=(e,t,r,n)=>bi.use(o=>wa(e,t,r,o,n,s=>dN(e,t,\"crypto.subtle\",r,s)));var mN=Symbol(\"~effect/crypto/Key/material\"),Jf=e=>new Uint8Array(e),Ho=e=>e[mN],$r=(e,t)=>({[e]:e,toJSON(){return{_id:t,algorithm:this.algorithm.name}},toString(){return K(this.toJSON())},[Je](){return this.toJSON()}}),hN=(e,t,r)=>Rh(Object.create(e,{algorithm:{value:t,enumerable:!0},[mN]:{value:r}})),zo=(e,t,r)=>hN(e,t,{_tag:\"Bytes\",bytes:r}),Gf=e=>t=>t.length===e.keyLength?void 0:`Expected a ${e.keyLength}-byte key for ${e.name}, not ${t.length} bytes`,ln=(e,t,r,n,o,s)=>L(()=>{if(!(o instanceof Uint8Array))return Ci(e,t,\"Expected the key as a Uint8Array\");let a=s(o);return a===void 0?g(zo(r,n,Jf(o))):Ci(e,t,a)}),Bd=(e,t)=>r=>{let n=r.length;return n===t*8?void 0:`Expected a ${t*8}-bit ${e} key, not ${n} bits`},pZ=(e,t)=>{if(!A(e,\"type\")||!A(e,\"algorithm\")||!A(e,\"usages\")||!Array.isArray(e.usages))return\"Expected a CryptoKey\";if(e.algorithm.name!==t.name)return`Expected a ${t.name} key, not ${e.algorithm.name}`;if(e.type!==t.type)return`Expected a ${t.type} key, not ${e.type}`;let r=t.check?.(e.algorithm);if(r!==void 0)return r;let n=e.usages;if(t.usagePolicy===\"all\"){if(!t.usages.every(o=>n.includes(o)))return`Expected a key with the usages ${t.usages.join(\" and \")}, not ${n.join(\", \")||\"none\"}`}else if(!t.usages.some(o=>n.includes(o)))return`Expected a key with one of the usages ${t.usages.join(\", \")}`},Mw=(e,t)=>{let r=t.algorithm.modulusLength;return A(e,\"modulusLength\")&&r!==void 0&&e.modulusLength!==r?{...e,modulusLength:r}:e},Ti=(e,t,r,n,o,s)=>L(()=>{let a=pZ(o,s);return a===void 0?g(hN(r,Mw(n,o),{_tag:\"CryptoKey\",cryptoKey:o})):Ci(e,t,a)}),vi=async(e,t)=>new Uint8Array(await e.exportKey(\"raw\",t)),Rs=(e,t,r)=>L(()=>{let n=Ho(t);return n._tag===\"Bytes\"?g(Jf(n.bytes)):n.cryptoKey.extractable?Kd(e,\"toBytes\",t.algorithm.name,o=>r(o,n.cryptoKey)):$d(e,\"toBytes\")}),ki=e=>{let t=new WeakMap;return async(r,n)=>{let o=Ho(n);if(o._tag===\"CryptoKey\")return o.cryptoKey;let s=t.get(n);return s===void 0&&(s=await e(r,o.bytes,n.algorithm),t.set(n,s)),s}};var xN=\"~effect/crypto/Aead/Key\",dZ={name:\"aes128Gcm\",keyLength:16,nonceLength:12,implementation:void 0},mZ={name:\"aes256Gcm\",keyLength:32,nonceLength:12,implementation:void 0},gN=e=>({encrypt:(t,r,n,o)=>e(t,r,o).encrypt(n),decrypt:(t,r,n,o)=>e(t,r,o).decrypt(n)}),hZ={name:\"chacha20Poly1305\",keyLength:32,nonceLength:12,implementation:gN(lN)},xZ={name:\"xchacha20Poly1305\",keyLength:32,nonceLength:24,implementation:gN(pN)},Fw=$r(xN,\"Aead.Key\"),Nw=e=>A(e,xN),jd=class extends Et()(\"effect/crypto/Aead\"){},Wg=(e,t)=>Ia(\"Aead\",e,t),yN=()=>Wg(\"decrypt\",new wi),gZ=2**36-32,yZ=16,SZ=(e,t,r,n)=>{let o=t.algorithm;if(n.nonce.length!==o.nonceLength)return Wg(e,new Qc({description:`${o.name} nonces must contain exactly ${o.nonceLength} bytes`}));if(e===\"encrypt\"){if(o.implementation===void 0&&r.length>gZ)return Wg(e,new Qc({description:\"AES-GCM plaintext cannot exceed 2^36 - 32 bytes\"}))}else if(r.length{let s=Ho(r);if(s._tag!==\"Bytes\")return Wg(e,new ba({description:`${r.algorithm.name} keys must hold bytes`}));let a=o.aad??new Uint8Array(0);return e===\"encrypt\"?Y(()=>t.encrypt(s.bytes,o.nonce,n,a)):L(()=>{let i=t.decrypt(s.bytes,o.nonce,n,a);return i===void 0?yN():g(i)})},SN=e=>pa(jd,kt(function*(){let t=yield*Ei,r=yield*bi,n=ki((c,u)=>c.importKey(\"raw\",u,\"AES-GCM\",!1,[\"encrypt\",\"decrypt\"])),o=e.implementations,s=c=>{let u=o?.[c.algorithm.name];return u!==void 0&&Ho(c)._tag===\"Bytes\"?u:c.algorithm.implementation},a=(c,u,f,p)=>{let d={name:\"AES-GCM\",iv:p.nonce,tagLength:128,...p.aad===void 0?{}:{additionalData:p.aad}};return wa(\"Aead\",c,u.algorithm.name,r,async m=>new Uint8Array(await m[c](d,await n(m,u),f)),m=>Wf(\"Aead\",c,u.algorithm.name,m,c===\"decrypt\"?()=>new wi:void 0))},i=c=>(u,f,p)=>L(()=>{let d=SZ(c,u,f,p);if(d!==void 0)return d;let m=s(u);return m===void 0?a(c,u,f,p):bZ(c,m,u,f,p)});return jd.of({generateKey:c=>W(t.randomBytes(c.keyLength),u=>zo(Fw,c,u)),encrypt:i(\"encrypt\"),decrypt:i(\"decrypt\")})})),EZ=SN({}),Uw=(e,t)=>ln(\"Aead\",\"key\",Fw,e,t,Gf(e)),IZ=(e,t)=>e.implementation!==void 0?Ci(\"Aead\",\"fromCryptoKey\",`${e.name} keys cannot be CryptoKeys`):Ti(\"Aead\",\"fromCryptoKey\",Fw,e,t,{type:\"secret\",name:\"AES-GCM\",usages:[\"encrypt\",\"decrypt\"],usagePolicy:\"all\",check:Bd(\"AES-GCM\",e.keyLength)}),Dw=e=>Rs(\"Aead\",e,vi);var Jg={};An(Jg,{Cipher:()=>Hd,aes128Cbc:()=>CZ,aes128Ctr:()=>wZ,aes256Cbc:()=>TZ,aes256Ctr:()=>AZ,fromCryptoKey:()=>OZ,isKey:()=>$w,key:()=>Kw,layerWebCrypto:()=>kZ,toBytes:()=>Bw});var IN=\"~effect/crypto/Cipher/Key\",wZ={name:\"aes128Ctr\",mode:\"AES-CTR\",keyLength:16},AZ={name:\"aes256Ctr\",mode:\"AES-CTR\",keyLength:32},CZ={name:\"aes128Cbc\",mode:\"AES-CBC\",keyLength:16},TZ={name:\"aes256Cbc\",mode:\"AES-CBC\",keyLength:32},Lw=$r(IN,\"Cipher.Key\"),$w=e=>A(e,IN),Hd=class extends Et()(\"effect/crypto/Cipher\"){},bN=(e,t)=>Ia(\"Cipher\",e,t),EN=16,vZ=(e,t)=>e.mode===\"AES-CTR\"?{name:\"AES-CTR\",counter:t,length:128}:{name:\"AES-CBC\",iv:t},kZ=pa(Hd,kt(function*(){let e=yield*Ei,t=yield*bi,r=ki((o,s,a)=>o.importKey(\"raw\",s,a.mode,!1,[\"encrypt\",\"decrypt\"])),n=o=>(s,a,i)=>L(()=>{if(i.iv.length!==EN)return bN(o,new Qc({description:\"IVs must contain exactly 16 bytes\"}));let c=s.algorithm.mode===\"AES-CBC\";return o===\"decrypt\"&&c&&(a.length===0||a.length%EN!==0)?bN(o,new wi):wa(\"Cipher\",o,s.algorithm.name,t,async u=>new Uint8Array(await u[o](vZ(s.algorithm,i.iv),await r(u,s),a)),u=>Wf(\"Cipher\",o,s.algorithm.name,u,o===\"decrypt\"&&c?()=>new wi:void 0))});return Hd.of({generateKey:o=>W(e.randomBytes(o.keyLength),s=>zo(Lw,o,s)),encrypt:n(\"encrypt\"),decrypt:n(\"decrypt\")})})),Kw=(e,t)=>ln(\"Cipher\",\"key\",Lw,e,t,Gf(e)),OZ=(e,t)=>Ti(\"Cipher\",\"fromCryptoKey\",Lw,e,t,{type:\"secret\",name:e.mode,usages:[\"encrypt\",\"decrypt\"],usagePolicy:\"all\",check:Bd(e.mode,e.keyLength)}),Bw=e=>Rs(\"Cipher\",e,vi);var wN=e=>Uint8Array.of(48,46,2,1,0,48,5,6,3,43,101,e,4,34,4,32),AN=wN(112),CN=wN(110),jw=32,Hw={\"P-256\":32,\"P-384\":48,\"P-521\":66},Vf=(e,t)=>r=>{if(r.length!==jw)return t===\"private\"&&r.length===64?`Expected the 32-byte ${e} seed, not the 64-byte seed\\u2016public key form: pass its first 32 bytes`:`Expected a ${jw}-byte ${e} ${t} key, not ${r.length} bytes`},Gg=e=>t=>{let r=1+2*Hw[e];return t.length!==r?`Expected a ${r}-byte uncompressed ${e} point, not ${t.length} bytes`:t[0]===4?void 0:`Expected an uncompressed ${e} point, starting with 0x04`},Vg=e=>t=>{let r=t.namedCurve;return r===e?void 0:`Expected a ${e} key, not ${r}`},Zg=e=>t=>{let r=t.hash?.name;return r===e?void 0:`Expected a key for ${e}, not ${r}`};var _Z=(e,t)=>{let r=new Uint8Array(e.length+t.length);return r.set(e),r.set(t,e.length),r},TN=(e,t,r,n)=>e.importKey(\"pkcs8\",r.seedPrefix===void 0?t:_Z(r.seedPrefix,t),r.importParams,n,r.privateUsages),vN=(e,t,r)=>e.importKey(r.publicFormat,t,r.importParams,!0,r.publicUsages),RZ=async(e,t,r)=>{let n=new Uint8Array(await e.exportKey(\"pkcs8\",t)),o=r.seedPrefix;if(o===void 0)return n;if(n.length!==o.length+jw||!o.every((s,a)=>n[a]===s))throw new Ld(new Ai({description:`${r.name} private key was exported in an unexpected PKCS#8 form`}));return n.slice(o.length)},PZ=async(e,t,r)=>new Uint8Array(await e.exportKey(r.publicFormat,t)),zw=(e,t,r,n)=>n===\"private\"?RZ(e,t,r):PZ(e,t,r),Zf=(e,t)=>Rs(e.module,t,(r,n)=>zw(r,n,e.specOf(t.algorithm),e.isPrivateKey(t)?\"private\":\"public\"));var _N=\"~effect/crypto/KeyAgreement/PrivateKey\",RN=\"~effect/crypto/KeyAgreement/PublicKey\";var PN=$r(_N,\"KeyAgreement.PrivateKey\"),MN=$r(RN,\"KeyAgreement.PublicKey\"),Ww=e=>A(e,_N),FN=e=>A(e,RN),UZ=e=>e._tag===\"X25519\"?{name:\"X25519\",importParams:{name:\"X25519\"},privateUsages:[\"deriveBits\"],publicUsages:[],seedPrefix:CN,publicFormat:\"raw\"}:{name:\"ECDH\",importParams:{name:\"ECDH\",namedCurve:e.namedCurve},privateUsages:[\"deriveBits\"],publicUsages:[],seedPrefix:void 0,publicFormat:\"raw\",check:Vg(e.namedCurve)},qw={module:\"KeyAgreement\",specOf:UZ,privateKeyProto:PN,publicKeyProto:MN,isPrivateKey:Ww};var NN=(e,t)=>ln(\"KeyAgreement\",\"privateKey\",PN,e,t,Vf(\"X25519\",\"private\")),UN=(e,t)=>ln(\"KeyAgreement\",\"publicKey\",MN,e,t,e._tag===\"Ecdh\"?Gg(e.namedCurve):Vf(\"X25519\",\"public\"));var Jw=e=>Zf(qw,e);var Ca=e=>DZ(typeof e==\"string\"?$N.encode(e):e),Xc=e=>{let t=KZ(e),r=t.length;if(r%4!==0)return q(new to({kind:\"Decode\",module:\"Base64\",input:t,message:`Length must be a multiple of 4, but is ${r}`}));let n=t.indexOf(\"=\");if(n!==-1&&(nms($9(e,t,r));function K9(e){let t=e2(e.name,e.valueEncoded,e.options);if(t!==void 0)throw t;let r=e.name+\"=\"+e.valueEncoded;if(e.options===void 0)return r;let n=e.options;if(n.maxAge!==void 0){let o=hs(ct(n.maxAge));r+=\"; Max-Age=\"+Math.trunc(o)}if(n.domain!==void 0&&!n.hostOnly&&(r+=\"; Domain=\"+n.domain),n.path!==void 0&&(r+=\"; Path=\"+n.path),n.priority!==void 0)switch(n.priority){case\"low\":r+=\"; Priority=Low\";break;case\"medium\":r+=\"; Priority=Medium\";break;case\"high\":r+=\"; Priority=High\";break}if(n.expires!==void 0&&(r+=\"; Expires=\"+n.expires.toUTCString()),n.httpOnly&&(r+=\"; HttpOnly\"),n.secure&&(r+=\"; Secure\"),n.partitioned&&(r+=\"; Partitioned\"),n.sameSite!==void 0)switch(n.sameSite){case\"lax\":r+=\"; SameSite=Lax\";break;case\"strict\":r+=\"; SameSite=Strict\";break;case\"none\":r+=\"; SameSite=None\";break}return r}var r2=e=>{let t={},r=Object.values(e.cookies);for(let n=0;nObject.values(e.cookies).map(K9);var B9=e=>{try{return decodeURIComponent(e)}catch{return e}};var su=new WeakMap,o2=e=>{if(su.has(e))return su.get(e);throw new Error(\"Unable to get redacted value\"+(e.label?` with label: \"${e.label}\"`:\"\"))};var s2=\"~effect/Redacted\",Qf=e=>A(e,s2),Ta=(e,t)=>{let r=Object.create(z9);return t?.label&&(r.label=t.label),su.set(r,e),r},z9={[s2]:{_A:e=>e},label:void 0,...kr,toJSON(){return this.toString()},toString(){return``},[re](){return V(su.get(this))},[ne](e){return Qf(e)&&Z(su.get(this),su.get(e))}},Mi=o2;var a2=e=>Kt((t,r)=>e(Mi(t),Mi(r)));var $A=Symbol.for(\"~effect/http/Headers\"),c2=e=>A(e,$A),KA=Object.defineProperties(Object.create(null),{[$A]:{value:$A},[Gs]:{value(e){return q9(this,Me(e,J9))}},toJSON:{value(){return Ao(this)}},[ne]:{value(e){return HA(this,e)}},[re]:{value(){return mp(this)}},toString:{value:$t.toString},[Je]:{value:$t[Je]}});var HA=T_(Wa()),W9=Object.create(KA),u2=e=>{if(e===void 0)return W9;if(Symbol.iterator in e){let r=Object.create(KA);for(let[n,o]of e)r[n.toLowerCase()]=o;return r}let t=Object.create(KA);for(let[r,n]of Object.entries(e))Array.isArray(n)?t[r.toLowerCase()]=n.join(\", \"):n!==void 0&&(t[r.toLowerCase()]=n);return t};var q9=l(2,(e,t)=>{let r={...e},n=o=>{if(typeof o==\"string\"){let s=o.toLowerCase();s in e&&(r[s]=Ta(e[s]))}else for(let s in e)s.search(o)!==-1&&(r[s]=Ta(e[s]))};if(Array.isArray(t))for(let o=0;o{let r=e.toLowerCase();for(let n=0;n[\"authorization\",\"cookie\",\"set-cookie\",\"x-api-key\"]}),i2=\"~effect/http/Headers/HeaderParseError\",BA=class extends Np{},hy=class e extends Ut(\"HeaderParseError\"){static fromReason(t,r){return new e({reason:new BA({_tag:t,input:r})})}[i2]=i2;get message(){return`${this.reason._tag}: ${JSON.stringify(this.reason.input)}`}};var G9=[\"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\",\"dec\"],V9=[/^(?:mon|tue|wed|thu|fri|sat|sun), (?\\d{2}) (?[a-z]{3}) (?\\d{4}) (?\\d{2}):(?\\d{2}):(?\\d{2}) gmt$/i,/^(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday), (?\\d{2})-(?[a-z]{3})-(?\\d{2}) (?\\d{2}):(?\\d{2}):(?\\d{2}) gmt$/i,/^(?:mon|tue|wed|thu|fri|sat|sun) (?[a-z]{3}) (? \\d|\\d{2}) (?\\d{2}):(?\\d{2}):(?\\d{2}) (?\\d{4})$/i],l2=e=>{for(let t of V9){let r=t.exec(e)?.groups;if(r===void 0)continue;let n=G9.indexOf(r.month.toLowerCase()),o=Number(r.hour),s=Number(r.minute),a=Number(r.second);if(n===-1||o>23||s>59||a>60)return;let i=Number(r.year);r.year.length===2&&(i+=i<70?2e3:1900);let c=Number(r.day),u=new Date(0);return u.setUTCFullYear(i,n,c),u.getUTCFullYear()!==i||u.getUTCMonth()!==n||u.getUTCDate()!==c?void 0:u.getTime()+((o*60+s)*60+a)*1e3}},p2=e=>{let t=l2(e.trim());return t===void 0?q(hy.fromReason(\"InvalidHttpDate\",e)):j(Vd(t))},zA=e=>cy(e).toUTCString();var Z9=e=>({_tag:\"DateTime\",dateTime:e}),Y9=/^\\d+$/,jA=BigInt(1e9),d2=e=>{let t=e.trim();if(Y9.test(t)){let n=Number(t),o=Number.isSafeInteger(n*1e3)?cf(n):On(BigInt(t)*jA);return j({_tag:\"Duration\",duration:o})}let r=l2(t);return r===void 0?q(hy.fromReason(\"InvalidRetryAfter\",e)):j(Z9(Vd(r)))},m2=e=>e._tag===\"Duration\"?String((yc(e.duration)+jA-BigInt(1))/jA):zA(e.dateTime);var nm=e=>typeof e==\"string\"?e:Mi(e);var WA=\"~effect/http/UrlParams\",qA=e=>A(e,WA),Q9={...kr,[WA]:WA,[Symbol.iterator](){return this.params[Symbol.iterator]()},[Gs](e){return{_id:\"UrlParams\",params:Object.fromEntries(t7(this,Me(e,n7)))}},toJSON(){return Ao(this)},[ne](e){return JA(this,e)},[re](){return wo(this.params.flat())}},xy=e=>{let t=Object.create(Q9);return t.params=e,t},y2=e=>{if(qA(e))return e;let t=S2(e),r=[];for(let n=0;n{let t=typeof e[Symbol.iterator]==\"function\"?wt(e):Object.entries(e),r=[];for(let[n,o]of t)if(Array.isArray(o))for(let s=0;sQf(e)?e:String(e),JA=Kt((e,t)=>X9(e.params,t.params)),X9=__(S_([Wa(),xp()]));var b2=l(2,(e,t)=>hE(e.params,([r])=>r===t).pipe(Vt(([,r])=>nm(r))));var e7=e=>{let t={};for(let[r,n]of e.params){let o=nm(n);if(!Object.hasOwn(t,r))B(t,r,o);else{let s=t[r];typeof s==\"string\"?B(t,r,[s,o]):s.push(o)}}return t},E2=e7,t7=l(2,(e,t)=>{let r=Array.isArray(t)?t:[t];return e.params.map(([n,o])=>[n,typeof o==\"string\"&&r7(n,r)?Ta(o):o])}),r7=f2;var n7=Te(\"effect/http/UrlParams/CurrentRedactedNames\",{defaultValue:()=>[\"X-Amz-Signature\",\"X-Amz-Credential\",\"X-Amz-Security-Token\",\"AWSAccessKeyId\",\"Signature\",\"sig\",\"X-Goog-Signature\"]});var GA=\"~effect/Graph\",VA=e=>A(e,GA),I2=e=>e;var s7=(e,t,r)=>(e===\"directed\"?t.source===r.source&&t.target===r.target:t.source===r.source&&t.target===r.target||t.source===r.target&&t.target===r.source)&&Z(t.data,r.data),a7=(e,t)=>e===\"directed\"?V(t):lr(Ee(V(t.data),i7(t.source,t.target))),i7=(e,t)=>Ee(0,V(e))+Ee(0,V(t)),c7=Pe(\"Graph\"),u7={[GA]:{_N:e=>e,_E:e=>e},[Symbol.iterator](){return this.nodes[Symbol.iterator]()},[Je](){return this.toJSON()},[ne](e){if(A(e,GA)){let t=I2(e);if(this.nodes.size!==t.nodes.size||this.edges.size!==t.edges.size||this.type!==t.type)return!1;for(let[r,n]of this.nodes)if(!t.nodes.has(r)||!Z(n,t.nodes.get(r)))return!1;for(let[r,n]of this.edges){let o=t.edges.get(r);if(o===void 0||!s7(this.type,n,o))return!1}return!0}return!1},[re](){let e=c7;e=e^Pe(this.type),e=e^Lt(this.nodes.size),e=e^Lt(this.edges.size);for(let[t,r]of this.nodes)e^=Ee(V(t),V(r));for(let[t,r]of this.edges)e^=Ee(V(t),a7(this.type,r));return lr(e)},toJSON(){return{_id:\"Graph\",nodeCount:this.nodes.size,edgeCount:this.edges.size,type:this.type}},toString(){return`Graph(${this.type}, ${this.nodes.size}, ${this.edges.size})`},pipe(){return te(this,arguments)}},f7=(e,t)=>{let r=Object.create(u7);return r.type=e,r.mutable=t,r.transforming=!1,r.nodes=new Map,r.edges=new Map,r.adjacency=new Map,r.reverseAdjacency=new Map,r.nextNodeIndex=0,r.nextEdgeIndex=0,r.acyclic=_(!0),r};var om=e=>{let t=I2(e);return{type:e.type,nodes:Array.from(t.nodes,([r,n])=>({index:r,data:n})).sort((r,n)=>r.index-n.index),edges:Array.from(t.edges,([r,n])=>({index:r,source:n.source,target:n.target,data:n.data})).sort((r,n)=>r.index-n.index)}},gy=e=>{let t=f7(e.type,!1);for(let r of e.nodes)t.nodes.set(r.index,r.data),t.adjacency.set(r.index,[]),t.reverseAdjacency.set(r.index,[]);for(let r of e.edges)t.edges.set(r.index,{source:r.source,target:r.target,data:r.data}),t.adjacency.get(r.source).push(r.index),t.reverseAdjacency.get(r.target).push(r.index),e.type===\"undirected\"&&(t.adjacency.get(r.target).push(r.index),t.reverseAdjacency.get(r.source).push(r.index));return t.nextNodeIndex=e.nodes.length===0?0:e.nodes[e.nodes.length-1].index+1,t.nextEdgeIndex=e.edges.length===0?0:e.edges[e.edges.length-1].index+1,t.acyclic=v(),t};function va(e){return e.checks?e.checks[e.checks.length-1].annotations:e.annotations}function yy(e){return t=>va(t)?.[e]}var pn=\"~structural\",au=\"~identifier\",sm=\"~sentinels\",Sy=\"~constructor\",w2=[\"title\",\"description\",\"default\",\"examples\",\"readOnly\",\"writeOnly\",\"format\",\"contentEncoding\",\"contentMediaType\",\"contentSchema\"],Xf=yy(\"identifier\"),ZA=yy(au),YA=yy(\"title\");var am=on(e=>{let t=va(e)?.identifier;return typeof t==\"string\"?t:e.getExpected(am)}),A2=new Set([sm,pn,\"representation\",\"arbitraryConstraint\",\"toJsonSchema\",\"toCode\",\"toEquivalence\",\"toFormatter\",\"toCodec\",\"toCodecJson\",\"toCodecStringTree\",\"toCodecIso\",\"toCodecArbitrary\"]);var Ae=Symbol();var Er=Gr,dn=Er(Ae),ot=Er(Ae),im=e=>e===Ae?v():_(e),QA=e=>e._tag===\"None\"?dn:Er(e.value);var lm=\"~effect/SchemaIssue/Issue\";function eC(e){return A(e,lm)&&e[lm]===lm}function p7(e){return Object.hasOwn(e,\"input\")}var $n=class{[lm]=lm;constructor(t,r){r?.reportInput===!0&&t!==Ae&&(this.input=t)}},C2=class extends $n{_tag=\"Filter\";filter;issue;constructor(e,t,r,n){super(r,n),this.filter=e,this.issue=t}},T2=class extends $n{_tag=\"Encoding\";ast;issue;constructor(e,t,r,n){super(r,n),this.ast=e,this.issue=t}},Ot=class extends $n{_tag=\"Pointer\";path;issue;constructor(e,t){super(),this.path=e,this.issue=t}},Ni=class extends $n{_tag=\"MissingKey\";annotations;constructor(e){super(),this.annotations=e}},tC=class extends $n{_tag=\"UnexpectedKey\";ast;constructor(e,t,r){super(t,r),this.ast=e}},Ht=class extends $n{_tag=\"Composite\";ast;issues;constructor(e,t,r,n){super(r,n),this.ast=e,this.issues=t}},_t=class extends $n{_tag=\"InvalidType\";ast;constructor(e,t,r){super(t,r),this.ast=e}},fe=class extends $n{_tag=\"InvalidValue\";annotations;constructor(e,t,r){super(t,r),this.annotations=e}};function mn(e,t,r,n,o){return new Ht(e,[new Ot([t],r)],n,o)}var iu=class extends $n{_tag=\"Forbidden\";annotations;constructor(e,t,r){super(t,r),this.annotations=e}},pm=class extends $n{_tag=\"AnyOf\";ast;issues;constructor(e,t,r,n){super(r,n),this.ast=e,this.issues=t}},v2=class extends $n{_tag=\"OneOf\";ast;successes;constructor(e,t,r,n){super(r,n),this.ast=e,this.successes=t}};function XA(e,t,r){if(eC(e))return e;if(typeof e==\"string\")return new fe({message:e},t,r);let n=typeof e.issue==\"string\"?new fe({message:e.issue},t,r):e.issue;return new Ot(e.path,n)}function k2(e,t,r){if(e!==void 0)return typeof e==\"boolean\"?e?void 0:new fe(void 0,t,r):XA(e,t,r)}function O2(e,t,r,n){return Array.isArray(t)?yt(t)?t.length===1?XA(t[0],r,n):new Ht(e,kn(t,o=>XA(o,r,n)),r,n):void 0:k2(t,r,n)}var _2=e=>{let t=tl(e);if(t!==void 0)return t;switch(e._tag){case\"InvalidType\":return el(am(e.ast),e);case\"InvalidValue\":{let r=M2(e);if(r!==void 0)return el(r,e);let n=by(e);return n===void 0?\"Expected a valid value\":`Invalid data ${n}`}case\"MissingKey\":return\"Missing key\";case\"UnexpectedKey\":{let r=by(e);return r===void 0?\"Expected no excess property\":`Unexpected key with value ${r}`}case\"Forbidden\":return\"Forbidden operation\";case\"OneOf\":{let r=by(e);return r===void 0?\"Expected exactly one member to match\":`Expected exactly one member to match the input ${r}`}}},R2=e=>tl(e)??tl(e.issue);function P2(e){return t=>({issues:um(t,[],e?.leafHook??_2,e?.checkHook??R2)})}function by(e){return p7(e)?K(e.input):void 0}function M2(e){let t=e.annotations?.expected;return typeof t==\"string\"?t:void 0}function el(e,t){let r=by(t);return r===void 0?`Expected ${e}`:`Expected ${e}, got ${r}`}function F2(e,t){let r=t(e);if(r!==void 0||e.issue._tag!==\"InvalidValue\")return r;let n=M2(e.issue);return n===void 0?el(N2(e.filter),e):el(n,e.issue)}function um(e,t,r,n,o){switch(e._tag){case\"Filter\":return um(e.issue,t,r,n,o??F2(e,n));case\"Encoding\":return um(e.issue,t,r,n,o);case\"Pointer\":return um(e.issue,[...t,...e.path],r,n,o);case\"Composite\":case\"AnyOf\":return e._tag===\"Composite\"||e.issues.length>0?e.issues.flatMap(s=>um(s,t,r,n,o)):[{path:t,message:o??tl(e)??el(am(e.ast),e)}];default:return[{path:t,message:o??r(e)}]}}function N2(e){let t=e.annotations?.expected;if(typeof t==\"string\")return t;switch(e._tag){case\"Filter\":return\"\";case\"FilterGroup\":return e.checks.map(r=>N2(r)).join(\" & \")}}function d7(){return e=>fm(e,\"\")}var U2=d7();function fm(e,t,r){let n;switch(e._tag){case\"Filter\":return fm(e.issue,t,r??F2(e,R2));case\"Encoding\":return fm(e.issue,t,r);case\"Pointer\":return fm(e.issue,t+Ph(e.path),r);case\"Composite\":case\"AnyOf\":{if(e._tag===\"Composite\"||e.issues.length>0)return e.issues.map(o=>fm(o,t,r)).join(`\n`);n=r??tl(e)??el(am(e.ast),e);break}default:n=r??_2(e);break}return t?`${n}\n at ${t}`:n}function tl(e){if(e._tag===\"Pointer\"||e._tag===\"Composite\")return;if(e._tag===\"Encoding\")return tl(e.issue);let r=(e._tag===\"Filter\"?e.filter.annotations:\"annotations\"in e?e.annotations:e.ast.annotations)?.[e._tag===\"MissingKey\"?\"messageMissingKey\":e._tag===\"UnexpectedKey\"?\"messageUnexpectedKey\":\"message\"];if(typeof r==\"string\")return r}function dm(e){let t;for(let r of e.reasons){if(!ai(r)||!eC(r.error))return;t??=r.error}return t}function ho(e,t){let r=dm(e);if(r===void 0)throw new Error(t,{cause:e});return r}var L2=(e,t,r)=>{switch(e._tag){case\"Passthrough\":return g(t);case\"Transform\":return g(Vt(t,e.transform));case\"TransformOptional\":return g(e.transform(t));case\"TransformEffect\":return ge(t)?li:fn(e.transform(t.value,r),_);case\"TransformOptionalEffect\":return e.transform(t,r)}};var mm=e=>Object.assign(Object.create(Pb),e),Ey=(e,t)=>rC((r,n)=>Ct(L2(e,r,n),o=>L2(t,o,n))),Iy=l(2,(e,t)=>{if(e._tag===\"Passthrough\")return t;if(t._tag===\"Passthrough\")return e;switch(e._tag){case\"Transform\":switch(t._tag){case\"Transform\":return le(r=>t.transform(e.transform(r)));case\"TransformOptional\":return ka(r=>t.transform(Vt(r,e.transform)));case\"TransformEffect\":return Rt((r,n)=>t.transform(e.transform(r),n));case\"TransformOptionalEffect\":return Ey(e,t)}case\"TransformOptional\":switch(t._tag){case\"Transform\":return ka(r=>Vt(e.transform(r),t.transform));case\"TransformOptional\":return ka(r=>t.transform(e.transform(r)));case\"TransformEffect\":case\"TransformOptionalEffect\":return Ey(e,t)}case\"TransformEffect\":switch(t._tag){case\"Transform\":return Rt((r,n)=>fn(e.transform(r,n),t.transform));case\"TransformOptional\":case\"TransformOptionalEffect\":return Ey(e,t);case\"TransformEffect\":return Rt((r,n)=>Ct(e.transform(r,n),o=>t.transform(o,n)))}case\"TransformOptionalEffect\":return Ey(e,t)}});function m7(e){return rC((t,r)=>F(e(t,r)))}function cu(e){return m7((t,r)=>{let n={message:e(t)};return Ce(t)?new iu(n,t.value,r):new iu(n)})}var $2=cu(()=>\"Encoding is not supported\"),h7=mm({_tag:\"Passthrough\"});function hn(){return h7}function le(e){return mm({_tag:\"Transform\",transform:e})}function Rt(e){return mm({_tag:\"TransformEffect\",transform:e})}function ka(e){return mm({_tag:\"TransformOptional\",transform:e})}function rC(e){return mm({_tag:\"TransformOptionalEffect\",transform:e})}function nC(){return ka(()=>v())}function oC(e){return rC(t=>{let r=hc(t,cs);return Ce(r)?g(r):fn(e,_)})}function uu(){return le(globalThis.String)}function wy(){return le(globalThis.Number)}function K2(){return Rt((e,t)=>{try{return g(globalThis.BigInt(e))}catch{return F(new fe({expected:\"a value that can be converted to a bigint\"},e,t))}})}function sC(){return le(e=>new globalThis.Date(e))}function B2(){return le(K1)}function j2(e){return Rt((t,r)=>Ff({try:()=>JSON.parse(t,e?.reviver),catch:()=>new fe({expected:\"a valid JSON string\"},t,r)}))}function H2(e){return Rt((t,r)=>Ff({try:()=>{let n=JSON.stringify(t,e?.replacer,e?.space);if(n===void 0)throw new TypeError(\"Value cannot be represented as JSON\");return n},catch:()=>new fe({expected:\"a JSON-serializable value\"},t,r)}))}function z2(e){let t=e?.separator??\",\",r=e?.keyValueSeparator??\"=\",n=e?.trim??!1,o=e?.keepEmptyValues??!1;return le(s=>s.split(t).reduce((a,i)=>{let c,u;if(r===\"\")c=i.slice(0,1),u=i.slice(1,2);else{let f=i.indexOf(r);if(f===-1)return a;c=i.slice(0,f),u=i.slice(f+r.length)}return n&&(c=c.trim(),u=u.trim()),c===\"\"||u===\"\"&&!o||B(a,c,u),a},{}))}function W2(e){let t=e?.separator??\",\",r=e?.keyValueSeparator??\"=\";return le(n=>Object.entries(n).map(([o,s])=>`${o}${r}${s}`).join(t))}function q2(e){let t=e?.separator??\",\";return le(r=>r===\"\"?[]:r.split(t))}function aC(){return le(Ca)}function Ay(e){return le(e?.padding?jN:ey)}function Cy(){return le(gx)}function J2(){return Rt((e,t)=>Lf(jc(Xc(e)),()=>new fe({expected:\"a valid Base64 string\"},e,t)))}function G2(){return Rt((e,t)=>mr(LN(e),{onFailure:()=>F(new fe({expected:\"a valid Base64 string\"},e,t)),onSuccess:g}))}function V2(){return Rt((e,t)=>mr(Wd(e),{onFailure:()=>F(new fe({expected:\"a valid Base64Url string\"},e,t)),onSuccess:g}))}function Z2(){return Rt((e,t)=>mr(HN(e),{onFailure:()=>F(new fe({expected:\"a valid Base64Url string\"},e,t)),onSuccess:g}))}function Y2(){return Rt((e,t)=>mr(CE(e),{onFailure:()=>F(new fe({expected:\"a valid hexadecimal string\"},e,t)),onSuccess:g}))}function Q2(){return Rt((e,t)=>mr(nR(e),{onFailure:()=>F(new fe({expected:\"a valid hexadecimal string\"},e,t)),onSuccess:g}))}function X2(){return le(encodeURIComponent)}function eD(){return Rt((e,t)=>{try{return g(globalThis.decodeURIComponent(e))}catch{return F(new fe({expected:\"a valid URI component\"},e,t))}})}function tD(){return le(e=>sD(Array.from(e.entries())))}var x7=aD(e=>typeof e==\"string\"||typeof Blob<\"u\"&&e instanceof Blob);function rD(){return le(e=>{let t=new FormData;return typeof e==\"object\"&&e!==null&&x7(e).forEach(([n,o])=>{t.append(n,o)}),t})}function nD(){return le(e=>sD(Array.from(e.entries())))}var g7=aD(Wr);function oD(){return le(e=>typeof e==\"object\"&&e!==null?new URLSearchParams(g7(e)):new URLSearchParams)}function y7(e){if(e===\"\")return[\"\"];let t=e.replace(/\\[([^\\]\\r\\n\\u2028\\u2029]*)(\\])?/g,(o,s,a)=>a?`.${s}`:o),r=t.split(\".\"),n=t.startsWith(\".\")?1:0;return r.slice(n).map(o=>nf(o)?globalThis.Number(o):o)}var S7=20;function sD(e){let t={},r=new WeakSet,n=new WeakSet,o=new Map;e.forEach(([s,a])=>{let i=y7(s),c=t;for(let u=0;u{let r=[];function n(o,s){if(e(s))r.push([o,s]);else if(Array.isArray(s))s.every(e)?s.forEach(i=>{r.push([o,i])}):s.forEach((i,c)=>{n(`${o}[${c}]`,i)});else if(typeof s==\"object\"&&s!==null)for(let[a,i]of Object.entries(s))n(`${o}[${a}]`,i)}for(let[o,s]of Object.entries(t))n(o,s);return r}}var iD=Symbol.for(\"~effect/Schema/content\");function cD(e,t){return Object.defineProperty(e,iD,{value:t}),e}function uD(e){return e[iD]}var Ty=class extends ja{_tag=\"Middleware\";decode;encode;constructor(e,t){super(),this.decode=e,this.encode=t}flip(){return new Ty(this.encode,this.decode)}},hm=\"~effect/SchemaTransformation/Transformation\",Ke=class extends ja{[hm]=hm;_tag=\"Transformation\";decode;encode;constructor(e,t){super(),this.decode=e,this.encode=t}flip(){return new Ke(this.encode,this.decode)}};function b7(e){return A(e,hm)&&e[hm]===hm}var vy=e=>b7(e)?e:new Ke(e.decode,e.encode);function mt(e){return new Ke(Rt(e.decode),Rt(e.encode))}function Ge(e){return new Ke(le(e.decode),le(e.encode))}function ky(e){return new Ke(ka(e.decode),ka(e.encode))}function lD(){return new Ke(B2(),hn())}function pD(e){return new Ke(z2(e),W2(e))}var E7=new Ke(hn(),hn());function nl(){return E7}var ol=new Ke(wy(),uu()),Oy=new Ke(K2(),uu()),iC=new Ke(sC(),le(qb)),dD=new Ke(sC(),le(e=>e.getTime()));var cC=mt({decode:(e,t)=>Zt(JF(e),{onNone:()=>F(new fe({expected:\"a valid ByteSize string\"},e,t)),onSome:g}),encode:e=>g(`${e} ${e===BigInt(1)?\"byte\":\"bytes\"}`)}),mD=mt({decode:(e,t)=>Zt(Ew(e),{onNone:()=>F(new fe({expected:\"a non-negative bigint byte count\"},e,t)),onSome:g}),encode:e=>g(Lg(e))}),hD=mt({decode:(e,t)=>Zt(Ew(e),{onNone:()=>F(new fe({expected:\"a non-negative safe-integer byte count\"},e,t)),onSome:g}),encode:(e,t)=>Zt(ZF(e),{onNone:()=>F(new fe({expected:\"a ByteSize representable as a safe integer\"},e,t)),onSome:g})}),I7=e=>fr(e)&&typeof e.message==\"string\",xD=e=>{let r=Object.hasOwn(e,\"cause\")?new Error(e.message,{cause:yD(e.cause)}):new Error(e.message);return typeof e.name==\"string\"&&e.name!==\"Error\"&&(r.name=e.name),typeof e.stack==\"string\"&&(r.stack=e.stack),r},w7=e=>{try{let t=nc(e);return t===void 0?K(e):JSON.parse(t)}catch{return K(e)}},A7=(e,t,r)=>{let n={name:e.name,message:typeof e.message==\"string\"?e.message:\"\"};return t?.includeStack&&typeof e.stack==\"string\"&&(n.stack=e.stack),!t?.excludeCause&&e.cause!==void 0&&(n.cause=r(e.cause)),n},gD=e=>{let t=new WeakSet,r=n=>{if(wO(n)){if(t.has(n))return\"[Circular]\";t.add(n);let o=A7(n,e,r);return t.delete(n),o}return w7(n)};return r},yD=e=>I7(e)?xD(e):e,SD=e=>Ge({decode:xD,encode:t=>gD(e)(t)}),bD=e=>Ge({decode:yD,encode:gD(e)});function ED(){return Ge({decode:oE,encode:Zh})}function ID(){return Ge({decode:nE,encode:ps})}function wD(e){return Ge({decode:vp,encode:e?.onNoneEncoding===null?Zh:ps})}function AD(){return ky({decode:_,encode:mc})}function CD(){return ky({decode:e=>e.pipe(hc(cs),_),encode:mc})}var uC=mt({decode:(e,t)=>URL.canParse(e)?g(new URL(e)):F(new fe({expected:\"a valid URL string\"},e,t)),encode:e=>g(e.href)});var fC=new Ke(J2(),aC()),TD=new Ke(G2(),aC()),vD=new Ke(Z2(),Ay()),kD=new Ke(Q2(),Cy()),OD=new Ke(eD(),X2());function _D(e){return new Ke(j2(e??{}),cD(H2(e),{mediaType:\"application/json\",preserveSchema:e?.reviver===void 0&&e?.replacer===void 0}))}var RD=new Ke(tD(),rD()),PD=new Ke(nD(),oD());function Ui(e){return t=>t._tag===e}var ul=Ui(\"Declaration\");var C7=Ui(\"Never\");var al=Ui(\"Literal\"),pC=Ui(\"UniqueSymbol\");var My=Ui(\"Arrays\"),bC=Ui(\"Objects\"),Fy=Ui(\"Union\"),gm=Ui(\"Suspend\"),Tt=class{to;transformation;constructor(e,t){this.to=e,this.transformation=t}},Ns={},Fs=class{isOptional;isMutable;constructorDefault;annotations;constructor(e,t,r=void 0,n=void 0){this.isOptional=e,this.isMutable=t,this.constructorDefault=r,this.annotations=n}},MD=\"~effect/Schema\",Pt=class{[MD]=MD;annotations;checks;encoding;context;constructor(t=void 0,r=void 0,n=void 0,o=void 0){this.annotations=t,this.checks=r,this.encoding=n,this.context=o}toString(){return`<${this._tag}>`}},fl=class extends Pt{_tag=\"Declaration\";typeParameters;run;encodingChecks;encodingRun;constructor(e,t,r,n,o,s,a,i){super(r,n,o,s),this.typeParameters=e,this.run=t,this.encodingChecks=a,this.encodingRun=i}getParser(){let e;return(t,r)=>{if(t===Ae)return dn;e??=this.run(this.typeParameters);try{return e(t,this,r)}catch(n){return yr(n)}}}_rebuild(e,t,r,n,o){let s=lu(this.typeParameters,e);return s===this.typeParameters&&t===this.checks&&r===this.encodingChecks&&n===this.run&&o===this.encodingRun?this:new fl(s,n,this.annotations,t,void 0,this.context,r,o)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks,this.run,this.encodingRun)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks,this.encodingRun??this.run,this.run)}getExpected(){let e=this.annotations?.expected;return typeof e==\"string\"?e:\"\"}},T7=class extends Pt{_tag=\"Null\";getParser(){return Ky(this,null)}getExpected(){return\"null\"}},ym=new T7;var v7=class extends Pt{_tag=\"Undefined\";getParser(){return Ky(this,void 0)}toCodecJson(){return ft(this,[BD])}getExpected(){return\"undefined\"}},BD=new Tt(ym,new Ke(le(()=>{}),le(()=>null))),EC=new v7;var k7=class extends Pt{_tag=\"Void\";getParser(){let e=Er(void 0);return t=>t===Ae?dn:e}toCodecJson(){return ft(this,[BD])}getExpected(){return\"void\"}},jD=new k7;var O7=class extends Pt{_tag=\"Never\";getParser(){return Vo(this,IO)}getExpected(){return\"never\"}},ll=new O7,_7=class extends Pt{_tag=\"Any\";getParser(){return Vo(this,Ub)}getExpected(){return\"any\"}},HD=new _7,R7=class extends Pt{_tag=\"Unknown\";getParser(){return Vo(this,Ub)}getExpected(){return\"unknown\"}},Jo=new R7,P7=class extends Pt{_tag=\"ObjectKeyword\";getParser(){return Vo(this,pp)}getExpected(){return\"object | array | function\"}},zD=new P7,WD=class extends Pt{_tag=\"Enum\";enums;constructor(e,t,r,n,o){super(t,r,n,o);for(let[,s]of e)if(typeof s==\"number\"&&!globalThis.Number.isFinite(s))throw new Error(`A numeric enum value must be finite, got ${K(s)}`);this.enums=e}getParser(){let e=new Set(this.enums.map(([,t])=>t));return Vo(this,t=>e.has(t))}toCodecStringTree(){if(this.enums.some(([e,t])=>typeof t==\"number\")){let e=Object.fromEntries(this.enums.map(([t,r])=>[globalThis.String(r),r]));return ft(this,[new Tt(new Qr(Object.keys(e).map(t=>new Kn(t))),new Ke(le(t=>e[t]),uu()))])}return this}getExpected(){return this.enums.map(([e,t])=>JSON.stringify(t)).join(\" | \")}};function lC(e){return typeof e==\"number\"?`parts[${e}]`:e}function dC(e,t,r){if(r.has(e))return!0;if(e.encoding)throw new Error(`TemplateLiteral parts cannot have an encoding at ${lC(t)}`);let n;switch(e._tag){case\"String\":case\"Number\":case\"BigInt\":n=!0;break;case\"Literal\":n=!e.checks;break;case\"TemplateLiteral\":{let o=lC(t);n=!e.checks&&e.parts.every((s,a)=>dC(s,`${o}.parts[${a}]`,r));break}case\"Union\":{let o=lC(t);n=!e.checks&&e.types.every((s,a)=>dC(s,`${o}.types[${a}]`,r));break}default:return!1}return n&&r.add(e),n}var IC=class extends Pt{_tag=\"TemplateLiteral\";parts;encodedParts;literals;suffixLengths;constructor(e,t,r,n,o){super(t,r,n,o);let s=[],a=[],i=new Set;for(let u=0;u=0;u--)c[u]=c[u+1]+(a[u]?.length??0);this.parts=e,this.encodedParts=s,this.literals=a,this.suffixLengths=c}getParser(e){let t=new jn(!1,this.parts.map(LC),[]),r=e(Oa(xn,t,JD(this)));return(n,o)=>{if(n===Ae)return dn;let s=r(n,o);return s._tag===\"Success\"?ot:Sr(s,{onSuccess:()=>n,onFailure:a=>new Ht(this,[a],n,o)})}}getExpected(){return\"string\"}matchPart(e,t){return hL(this,e,t)===void 0?void 0:e}};function qD(e){let t=on(o=>{if(o._tag!==\"Union\")return o;let s=lu(o.types,t);return(o.options?.mode??\"anyOf\")===\"anyOf\"&&s===o.types?o:new Qr(s,o.options===void 0?void 0:{...o.options,mode:\"anyOf\"},o.annotations,o.checks,void 0,o.context)}),r=new IC(e.map(o=>t(gn(o)))),n=new jn(!1,e.map(LC),[]);return Oa(r,n,JD(r))}function JD(e){return new Ke(Rt((t,r)=>{let n=hL(e,t,r);return n?g(n):F(new fe({expected:\"a string matching template literal parts\"},t,r))}),le(t=>t.join(\"\")))}var GD=class extends Pt{_tag=\"UniqueSymbol\";symbol;constructor(e,t,r,n,o){super(t,r,n,o),this.symbol=e}getParser(){return Ky(this,this.symbol)}toCodecStringTree(){let e=globalThis.Symbol.keyFor(this.symbol);return ft(this,[new Tt(e===void 0?ll:new Kn(globalThis.String(this.symbol)),yL.transformation)])}getExpected(){return globalThis.String(this.symbol)}},Kn=class extends Pt{_tag=\"Literal\";literal;constructor(e,t,r,n,o){if(super(t,r,n,o),typeof e==\"number\"&&!globalThis.Number.isFinite(e))throw new Error(`A numeric literal must be finite, got ${K(e)}`);this.literal=e}getParser(){return Ky(this,this.literal)}matchPart(e,t){return e===globalThis.String(this.literal)?this.literal:void 0}toCodecJson(){return typeof this.literal==\"bigint\"?FD(this):this}toCodecStringTree(){return typeof this.literal==\"string\"?this:FD(this)}getExpected(){return typeof this.literal==\"string\"?JSON.stringify(this.literal):globalThis.String(this.literal)}};function FD(e){let t=globalThis.String(e.literal);return ft(e,[new Tt(new Kn(t),new Ke(le(()=>e.literal),le(()=>t)))])}var M7=class extends Pt{_tag=\"String\";getParser(){return Vo(this,Wr)}matchPart(e,t){let r=this.checks;return r&&!t.disableChecks&&Zo(r,e,void 0,this,t)?void 0:e}getExpected(){return\"string\"}},xn=new M7,F7=class extends Pt{_tag=\"Number\";getParser(){return Vo(this,lp)}matchKey(e,t){return this._match(Q7,e,t)}matchPart(e,t){return this._match(gC,e,t)}_match(e,t,r){if(!e.test(t))return;let n=globalThis.Number(t);return r.disableChecks||!this.checks?n:Zo(this.checks,n,void 0,this,r)?void 0:n}toCodecJson(){return this.checks&&(mC(this.checks,\"effect/schema/isFinite\")||mC(this.checks,\"effect/schema/isInt\"))?this:ft(this,[W7])}toCodecStringTree(){return this.toCodecJson()===this?ft(this,[X7]):ft(this,[eY])}getExpected(){return\"number\"}};function mC(e,t){return e.some(r=>r.annotations?.representation?.id===t||r._tag===\"FilterGroup\"&&mC(r.checks,t))}var wC=new F7,N7=class extends Pt{_tag=\"Boolean\";getParser(){return Vo(this,Th)}getExpected(){return\"boolean\"}},VD=new N7,U7=class extends Pt{_tag=\"Symbol\";getParser(){return Vo(this,Nb)}matchKey(e,t){return t.disableChecks||!this.checks?e:Zo(this.checks,e,void 0,this,t)?void 0:e}toCodecStringTree(){return ft(this,[yL])}getExpected(){return\"symbol\"}},ZD=new U7,D7=class extends Pt{_tag=\"BigInt\";getParser(){return Vo(this,bO)}matchPart(e,t){if(!yC.test(e))return;let r=globalThis.BigInt(e);return t.disableChecks||!this.checks?r:Zo(this.checks,r,void 0,this,t)?void 0:r}toCodecStringTree(){return ft(this,[rY])}getExpected(){return\"bigint\"}},YD=new D7,jn=class extends Pt{_tag=\"Arrays\";isMutable;elements;rest;encodingChecks;constructor(e,t,r,n,o,s,a,i){super(n,o,s,a),this.isMutable=e,this.elements=t,this.rest=r,this.encodingChecks=i;let c=!1;for(let u=0;u1)throw new Error(\"A required element cannot follow an optional element. ts(1257)\");for(let u=1;u=f?o[p-f+1]:o[0]}let c=f=>{let{input:p,len:d,options:m}=f;if(r.rest.length===0&&d>s)for(let h=s;h{let d=f.length,m={ast:r,getParser:i,input:f,len:d,tailThreshold:Math.max(s,d-a),output:[],issues:void 0,options:p},h=r.rest.length===0?s:Math.max(d,s+a),y=p.concurrency===void 0?1:ad(p.concurrency),S=y===1?$7(m,f,0,h):K7(m,f,{concurrency:y,end:h});if(!S)return c(m);if(Ve(S))return Ct(S,()=>c(m));let b=!0;return L(()=>b?(b=!1,C(S,()=>c(m))):u(f,p))};return(f,p)=>{if(f===Ae)return dn;try{return Array.isArray(f)?(n||(n=r.elements.map(d=>({ast:d,parser:t(d)})),o=r.rest.map(d=>({ast:d,parser:t(d)}))),u(f,p)):F(new _t(r,f,p))}catch(d){return yr(d)}}}_rebuild(e,t,r){let n=lu(this.elements,e),o=lu(this.rest,e);return n===this.elements&&o===this.rest&&t===this.checks&&r===this.encodingChecks?this:new jn(this.isMutable,n,o,this.annotations,t,void 0,this.context,r)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks)}getExpected(){return\"array\"}};function L7(e,t,r,n){if(r._tag===\"Failure\")return Ry(e,e.ast,n,r);let o=r===ot?t:r[xe];if(o!==Ae)e.output[n]=o;else{let s=e.getParser(e.tailThreshold,n);if(nr(s.ast))return;let a=new Ot([n],new Ni(s.ast.context?.annotations));if(e.options.errors===\"all\")e.issues?e.issues.push(a):e.issues=[a];else return la(new Ht(e.ast,[a],e.input,e.options))}}var QD={onItem(e,t,r){let n=r{if(n.cause.reasons.length===0)return n;let o=dm(n.cause);if(o===void 0)return Fn(fa(n.cause,a=>new Ht(t,[new Ot([r],a)],e.input,e.options)));let s=new Ot([r],o);if(e.options.errors===\"all\")e.issues?e.issues.push(s):e.issues=[s];else return la(new Ht(t,[s],e.input,e.options))},Sm=\"[+-]?(?:\\\\d+(?:\\\\.\\\\d+)?|\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?\";function Ms(e,t,r=Ns){let n,o;function s(a){switch(a._tag){case\"String\":case\"TemplateLiteral\":return(n??=Object.keys(e)).filter(i=>a.matchPart(i,r)!==void 0);case\"Number\":return(n??=Object.keys(e)).filter(i=>a.matchKey(i,r)!==void 0);case\"Symbol\":return(o??=Object.getOwnPropertySymbols(e)).filter(i=>Object.prototype.propertyIsEnumerable.call(e,i)&&a.matchKey(i,r)!==void 0);case\"Union\":return[...new Set(a.types.flatMap(s))];default:return[]}}return s(DC(gn(t)))}var AC=class{name;type;constructor(e,t){this.name=e,this.type=t}};function XD(e){switch(e._tag){case\"String\":case\"Number\":case\"Symbol\":case\"TemplateLiteral\":return!0;case\"Union\":return e.types.every(XD);default:return!1}}function eL(e){let t=pu(e);switch(t._tag){case\"String\":case\"Number\":case\"Symbol\":case\"TemplateLiteral\":return!0;case\"Union\":return t.types.every(eL);default:return!1}}function B7(e){return XD(e)&&eL(e)}var CC=class{parameter;type;constructor(e,t){if(!B7(e))throw new Error(`Invalid index signature parameter ${e._tag}`);if(this.parameter=e,this.type=t,nr(t)||t.encoding!==void 0&&nr(gn(t)))throw new Error(\"Cannot use `Schema.optionalKey` or `Schema.optional` with index signatures. Index signatures already allow keys to be absent; use `Schema.UndefinedOr` to allow `undefined` values.\")}},bm=class extends Pt{_tag=\"Objects\";propertySignatures;indexSignatures;encodingChecks;constructor(e,t,r,n,o,s,a){super(r,n,o,s),this.propertySignatures=e,this.indexSignatures=t,this.encodingChecks=a}getParser(e,t=e){let r=this,n=r.propertySignatures.length,o=r.indexSignatures.length;if(!n&&!o)return Vo(r,kh);let s,a,i=()=>(s||(s=r.propertySignatures.map(p=>({parser:t(p.type),name:p.name,type:p.type})),a=o?r.indexSignatures.map(p=>({is:p,parserKey:e(DC(p.parameter)),parserValue:t(p.type)})):void 0),s),c=()=>{let p=new Set(r.propertySignatures.map(S=>typeof S.name==\"number\"?globalThis.String(S.name):S.name)),d=(S,b,x,w,I)=>{if(I._tag===\"Failure\")return Ry(S,r,b,I)??Bt;let T=I===ot?w:I[xe];if(x!==Ae&&T!==Ae){if(n&&(p.has(b)||p.has(typeof x==\"number\"?globalThis.String(x):x)))return Bt;B(S.out,x,T)}return Bt},m=(S,b,x,w)=>{if(!w){let G=x.parserKey(b,S.options);if(!Ve(G))return C(so(G),he=>m(S,b,x,he));w=G}if(w._tag===\"Failure\")return Ry(S,r,b,w)??Bt;let I=w===ot?b:w[xe],T=S.input[b],P=x.parserValue(T,S.options);return Ve(P)?d(S,b,I,T,P):C(so(P),G=>d(S,b,I,T,G))},h=(S,b,x)=>{let w=S.input[b],I=x.parserValue(w,S.options);return Ve(I)?d(S,b,b,w,I):C(so(I),T=>d(S,b,b,w,T))},y=o?Qx()({onItem:(S,[b,x])=>x.is.parameter===xn?h(S,b,x):m(S,b,x),step:(S,b,x)=>x._tag===\"Failure\"?x:void 0}):void 0;return ew(function*(S,b){if(S===Ae)return Ae;if(!(typeof S==\"object\"&&S!==null&&!Array.isArray(S)))return yield*F(new _t(r,S,b));i();let x=S,w={},I={ast:r,input:x,out:w,issues:void 0,options:b},T=b.errors===\"all\",P=b.onExcessProperty===\"error\",G=b.concurrency===void 0?1:ad(b.concurrency),he=o&&P?r.indexSignatures.map(me=>Ms(x,me.parameter,b)):void 0;if(P){let me=he?new Set(p):p;if(he)for(let R of he)for(let N of R)me.add(N);let E=Reflect.ownKeys(x);for(let R=0;R{let h=s[d];return C(so(m),y=>{let S={...p,out:{...p.out}},b=hC(S,h,y);if(b)return b;let x=()=>Er(S.out),w=ND(S,s.slice(d+1));return w?Ct(w,x):x()})};return(p,d)=>{if(p===Ae)return dn;if(d.errors===\"all\"||d.onExcessProperty!==void 0||d.concurrency!==void 0&&ad(d.concurrency)!==1)return(u??=c())(p,d);if(!(typeof p==\"object\"&&p!==null&&!Array.isArray(p)))return F(new _t(r,p,d));let m=i(),h=p,y={},S={ast:r,input:h,out:y,issues:void 0,options:d};try{for(let b=0;b{let i=e(a.type);return i===a.type?a:new AC(a.name,i)}),s=lu(this.indexSignatures,a=>{let i=t(a.parameter),c=e(a.type);return i===a.parameter&&c===a.type?a:new CC(i,c)});return o===this.propertySignatures&&s===this.indexSignatures&&r===this.checks&&n===this.encodingChecks?this:new bm(o,s,this.annotations,r,void 0,this.context,n)}flip(e){return this._rebuild(e,e,this.encodingChecks,this.checks)}recur(e,t=e){return this._rebuild(e,t,this.checks,this.encodingChecks)}getExpected(){return this.propertySignatures.length===0&&this.indexSignatures.length===0?\"object | array\":\"object\"}};function hC(e,t,r){if(r._tag===\"Failure\")return Ry(e,e.ast,t.name,r);if(r===ot)return;let n=r[xe];if(n!==Ae){B(e.out,t.name,n);return}if(delete e.out[t.name],!nr(t.type)){let o=new Ot([t.name],new Ni(t.type.context?.annotations));if(e.options.errors===\"all\"){e.issues?e.issues.push(o):e.issues=[o];return}else return la(new Ht(e.ast,[o],e.input,e.options))}}var tL={onItem(e,t){if(!sl(e.input,t.name))return t.parser(Ae,e.options);let r=e.input[t.name];return B(e.out,t.name,r),t.parser(r,e.options)},step:hC},ND=Yx()(tL),j7=Qx()(tL);function TC(e,t){return e?t?[...e,...t]:e:t}function Ny(e,t,r){return new bm(Reflect.ownKeys(e).map(n=>new AC(n,e[n].ast)),[],r,t)}function Em(e){return e.ast}function vC(e,t=void 0){return new jn(!1,e.map(r=>r.ast),[],void 0,t)}function Uy(e,t,r){return new Qr(e.map(Em),t,void 0,r)}function rL(e,t){if(e.encoding||t.some(s=>s.encoding))throw new Error(\"StructWithRest does not support encodings\");let r=e.propertySignatures,n=e.indexSignatures,o=e.checks;for(let s of t){for(let a of s.propertySignatures)if(r.some(i=>i.name===a.name))throw new Error(`Duplicate identifier: ${JSON.stringify(a.name)}. ts(2300)`);r=r.concat(s.propertySignatures),n=n.concat(s.indexSignatures),o=TC(o,s.checks)}return new bm(r,n,void 0,o)}function nL(e,t){if(e.encoding)throw new Error(\"TupleWithRest does not support encodings\");return new jn(e.isMutable,e.elements,t,void 0,e.checks)}function oL(e){if(e.encoding)throw new Error(\"mutable does not support encodings\");return new jn(!0,e.elements,e.rest,e.annotations,e.checks,void 0,e.context,e.encodingChecks)}var kC=qs(e=>{for(;;){if(gm(e))return Jo;let t=e.encoding;if(!t)return e.recur?.(kC,D)??e;if(t.some(r=>r.transformation._tag===\"Middleware\"&&r.transformation.decode!==D))return Jo;e=t[t.length-1].to}});function sL(e){switch(e._tag){case\"Null\":return[\"null\"];case\"Undefined\":return[\"undefined\"];case\"String\":case\"TemplateLiteral\":return[\"string\"];case\"Number\":return[\"number\"];case\"Boolean\":return[\"boolean\"];case\"Symbol\":case\"UniqueSymbol\":return[\"symbol\"];case\"BigInt\":return[\"bigint\"];case\"Arrays\":return[\"array\"];case\"ObjectKeyword\":return[\"object\",\"array\",\"function\"];case\"Objects\":return e.propertySignatures.length||e.indexSignatures.length?[\"object\"]:[\"string\",\"number\",\"boolean\",\"symbol\",\"bigint\",\"object\",\"array\",\"function\"];case\"Enum\":return Array.from(new Set(e.enums.map(([,t])=>typeof t)));case\"Literal\":return[typeof e.literal];case\"Union\":return Array.from(new Set(e.types.flatMap(sL)));default:return[\"null\",\"undefined\",\"string\",\"number\",\"boolean\",\"symbol\",\"bigint\",\"object\",\"array\",\"function\"]}}function il(e){switch(e._tag){default:return[];case\"Declaration\":{let t=e.annotations?.[sm];return Array.isArray(t)?t:[]}case\"Objects\":return e.propertySignatures.flatMap(t=>{let r=t.type;if(!nr(r)){if(al(r))return[{key:t.name,literal:r.literal}];if(pC(r))return[{key:t.name,literal:r.symbol}]}return[]});case\"Arrays\":return e.elements.flatMap((t,r)=>{if(!nr(t)){if(al(t))return[{key:r,literal:t.literal}];if(pC(t))return[{key:r,literal:t.symbol}]}return[]});case\"Union\":{if(e.types.length===0)return[];let t=e.types.map(r=>il(kC(r)));return t[0].filter(r=>t.every(n=>n.some(o=>o.key===r.key&&o.literal===r.literal)))}case\"Suspend\":return il(e.thunk())}}var UD=new WeakMap,_y=Object.freeze([]),DD=e=>e===null?\"null\":Array.isArray(e)?\"array\":typeof e,sl=(e,t)=>t===\"__proto__\"?Object.hasOwn(e,t):t in e;function Im(e){let t=UD.get(e);if(t)return t;let r,n=0,o,s,a=!0,i=[];for(let f=0;fc[f]??=Object.freeze(o?.[f]??_y);if(a&&s)s.forEach(Object.freeze),t=f=>s.get(f)??_y;else if(r?.size===1&&!o){let[f,[p]]=r.entries().next().value,d=new Map;for(let[h,y]of p)d.set(h,Object.freeze(Array.from(y)));let m=Object.freeze(e.map((h,y)=>y));t=(h,y)=>{if(pp(h)){let S=sl(h,f)?h[f]:void 0;if(S!==void 0)return d.get(S)??_y;if(y)return m}return _y}}else if(r){let f;for(let p of r)(!f||p[1][0].size>f[1][0].size)&&p[1][1].size===n&&(f=p);t=(p,d)=>{let m=DD(p);if(!pp(p))return u(m);let h=new Set(o?.[m]),y;if(f){let[S,[b]]=f,x=sl(p,S),w=x?p[S]:void 0;if(x&&(!d||w!==void 0)){let I=b.get(w);if(!I)return u(m);for(let T of I)h.add(T);y=S}}if(y===void 0)for(let[S,[b,x]]of r){let w=sl(p,S),I=w?p[S]:void 0;if(w&&(!d||I!==void 0)){let T=b.get(I);if(T)for(let P of T)h.add(P)}else if(d)for(let T of x)h.add(T)}for(let[S,[b,x]]of r){if(S===y)continue;let w=sl(p,S),I=w?p[S]:void 0;if(w&&(!d||I!==void 0)){let T=b.get(I);for(let P of h)x.has(P)&&!T?.has(P)&&h.delete(P)}}return Array.from(h).sort((S,b)=>S-b)}}else t=f=>{let p=u(DD(f));return s?p.filter(d=>i[d]===void 0||i[d]===f):p};return UD.set(e,t),t}var Qr=class extends Pt{_tag=\"Union\";types;options;encodingChecks;constructor(e,t,r,n,o,s,a){super(r,n,o,s),this.types=e,this.options=t,this.encodingChecks=a}getParser(e,t){let r=this,n=t!==void 0,o=[],s=i=>o[i]??=e(r.types[i]),a;return(i,c)=>{if(i===Ae)return dn;let u=(a??=Im(r.types))(i,n);if(u.length===0)return F(new pm(r,[],i,c));if(u.length===1){let f=s(u[0])(i,c);return f._tag===\"Success\"?f:Ve(f)?aL(r,f.cause,i,c):H7(r,f,i,c)}return iL(r,s,u,i,c)}}_rebuild(e,t,r){let n=lu(this.types,e);return n===this.types&&t===this.checks&&r===this.encodingChecks?this:new Qr(n,this.options,this.annotations,t,void 0,this.context,r)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks)}matchPart(e,t){for(let r of this.types){let n=r.matchPart(e,t);if(n!==void 0)return n}}getExpected(e){let t=this.annotations?.expected;if(typeof t==\"string\")return t;if(this.types.length===0)return\"never\";let r=this.types.map(n=>{let o=gn(n);switch(o._tag){case\"Arrays\":{let s=o.elements.filter(al);if(s.length>0)return`${$D(o.isMutable)}[ ${s.map(a=>e(a)+KD(a.context?.isOptional)).join(\", \")}, ... ]`;break}case\"Objects\":{let s=o.propertySignatures.filter(a=>al(a.type));if(s.length>0)return`{ ${s.map(a=>`${$D(a.type.context?.isMutable)}${us(a.name)}${KD(a.type.context?.isOptional)}: ${e(a.type)}`).join(\", \")}, ... }`;break}}return e(o)});return Array.from(new Set(r)).join(\" | \")}};function aL(e,t,r,n){let o=dm(t);return o?la(new pm(e,[o],r,n)):Fn(t)}function H7(e,t,r,n){return nt(t,o=>aL(e,o,r,n))}function iL(e,t,r,n,o){let s={ast:e,parser:t,input:n,out:void 0,successes:e.options?.mode===\"oneOf\"?[]:void 0,issues:void 0,options:o},a=z7(s,r);if(!a)return s.out?s.out:F(new pm(e,s.issues??[],n,o));if(Ve(a))return LD(a,s);let i=!0;return L(()=>i?(i=!1,LD(a,s)):iL(e,t,r,n,o))}function LD(e,t){return Ct(e,r=>t.out===ot?g(t.input):t.out?t.out:F(new pm(t.ast,t.issues??[],t.input,t.options)))}var z7=Yx()({onItem(e,t){return e.parser(t)(e.input,e.options)},step(e,t,r){if(r._tag===\"Failure\"){let n=dm(r.cause);if(n===void 0)return r;e.issues?e.issues.push(n):e.issues=[n]}else{if(e.out&&e.successes)return e.successes.push(e.ast.types[t]),la(new v2(e.ast,e.successes,e.input,e.options));if(e.out=r,e.successes)e.successes.push(e.ast.types[t]);else return Bt}}}),cL=new Qr([new Kn(\"Infinity\"),new Kn(\"-Infinity\"),new Kn(\"NaN\")]);function $D(e){return e?\"\":\"readonly \"}function KD(e){return e?\"?\":\"\"}var OC=class extends Pt{_tag=\"Suspend\";thunk;constructor(e,t,r,n,o){if(r)throw new Error(\"Cannot add checks to Suspend\");super(t,void 0,n,o);let s;this.thunk=()=>s??=e()}getParser(e){let t;return(r,n)=>(t??=e(this.thunk()))(r,n)}recur(e){return new OC(()=>e(this.thunk()),this.annotations,void 0,void 0,this.context)}getExpected(e){return e(this.thunk())}},Py=class extends ja{_tag=\"Filter\";run;annotations;aborted;constructor(e,t=void 0,r=!1){super(),this.run=e,this.annotations=t,this.aborted=r}annotate(e){return new Py(this.run,{...this.annotations,...e},this.aborted)}abort(){return new Py(this.run,this.annotations,!0)}and(e,t){return new fu([this,e],t)}},fu=class extends ja{_tag=\"FilterGroup\";checks;annotations;constructor(e,t=void 0){super(),this.checks=e,this.annotations=t}annotate(e){return new fu(this.checks,{...this.annotations,...e})}and(e,t){return new fu([this,e],t)}};function Dy(e,t,r=!1){return new Py((n,o,s)=>O2(o,e(n,o,s),n,s),t,r)}function Ly(e,t){return new Py((r,n,o)=>e(r)?void 0:new fe(void 0,r,o),t,!0)}function _C(e){return Dy(t=>globalThis.Number.isFinite(t),{expected:\"a finite number\",representation:{id:\"effect/schema/isFinite\",payload:null},toJsonSchema:()=>({type:\"number\"}),toCode:()=>({runtime:\"Schema.isFinite()\"}),arbitraryConstraint:{number:\"finite\"},...e})}var RC=Us(wC,[_C()]),W7=new Tt(new Qr([RC,cL]),new Ke(wy(),le(e=>globalThis.Number.isFinite(e)?e:globalThis.String(e))));function wm(e,t){let r=new globalThis.RegExp(e),n={source:r.source,flags:r.flags};return Dy(o=>(r.lastIndex=0,r.test(o)),{expected:`a string matching the RegExp ${n.source}`,representation:{id:\"effect/schema/isPattern\",payload:n},toJsonSchema:()=>[{},!0],arbitraryConstraint:{patterns:[n]},...t})}var xC=new WeakMap;function Am(e,t){let r=Object.assign(Object.create(Object.getPrototypeOf(e)),e,t);return Reflect.ownKeys(t).every(n=>n===\"context\"||n===\"encoding\")&&xC.set(r,Di(e)),r}function Di(e){let t=xC.get(e);if(t!==void 0)return t;if(e.encoding===void 0)return e;let r=Object.assign(Object.create(Object.getPrototypeOf(e)),e,{encoding:void 0});return xC.set(e,r),r}function ft(e,t){return e.encoding===t?e:Am(e,{encoding:t})}function Hn(e,t){if(e.context===t)return e;let r=Di(e);return r.context===t&&r.encoding===e.encoding?r:Am(e,{context:t})}function pu(e){return e.encoding?pu(e.encoding[e.encoding.length-1].to):e}function Go(e,t){if(e.checks){let r=e.checks[e.checks.length-1];return Cm(e,sx(e.checks.slice(0,-1),r.annotate(t)))}return Am(e,{annotations:{...e.annotations,...t}})}function Cm(e,t){if(e._tag===\"Suspend\"&&t)throw new Error(\"Cannot add checks to Suspend\");return e.checks===t?e:Am(e,{checks:t})}function Us(e,t){return Cm(e,TC(e.checks,t))}function pl(e,t){let r=t(e.to);return r===e.to?e:new Tt(r,e.transformation)}function PC(e,t){let r=e,n=r[r.length-1],o=pl(n,t);return o===n?e:sx(e.slice(0,e.length-1),o)}function MC(e){return t=>t.encoding?ft(t,PC(t.encoding,e)):t}function FC(e,t){return MC(r=>Hn(r,t))(e)}function dl(e){function t(r){return r.encoding?ft(r,PC(r.encoding,t)):e(r)}return on(t)}function du(e,t){function r(n){if(n.encoding){let o=n.encoding[n.encoding.length-1];return t?.stopAt?.(o)?n:ft(n,PC(n.encoding,r))}return e(n)}return qs(r)}function uL(e,t){return NC(e,t,Mt(e))}function fL(e,t){return NC(gn(e),t,e)}function NC(e,t,r){let n=new Tt(e,t);return ft(r,r.encoding?[...r.encoding,n]:[n])}function lu(e,t){let r;for(let n=0;n{let t=e.context?e.context.isOptional===!1?new Fs(!0,e.context.isMutable,e.context.constructorDefault,e.context.annotations):e.context:new Fs(!0,!1);return q7(Hn(e,t))}),q7=MC(mu),lL=on(e=>mu(new Qr([e,EC]))),UC=qs(e=>{let t=e.context?e.context.isMutable===!1?new Fs(e.context.isOptional,!0,e.context.constructorDefault,e.context.annotations):e.context:new Fs(!1,!0);return J7(Hn(e,t))}),J7=MC(UC);function pL(e,t){let r=e.context?new Fs(e.context.isOptional,e.context.isMutable,t,e.context.annotations):new Fs(!1,!1,t);return Hn(e,r)}function Oa(e,t,r){return NC(e,r,t)}function G7(e){let t=[],r=[];function n(s){t.includes(s)||t.push(s)}function o(s){switch(s._tag){case\"Literal\":vh(s.literal)&&n(s.literal);return;case\"UniqueSymbol\":n(s.symbol);return;case\"Enum\":for(let[,a]of s.enums)n(a);return;case\"Never\":return;case\"Union\":for(let a=0;anew AC(o,t)),n.map(o=>new CC(o,t)))}function nr(e){return e.context?.isOptional??!1}function dL(e){return e.context?.isMutable??!1}function mL(e){return e.annotations?.[pn]===!0||e._tag===\"FilterGroup\"&&e.checks.every(mL)}function V7(e){function t(n){return mL(n)?[n]:n._tag===\"FilterGroup\"?n.checks.flatMap(t):[]}let r=e.flatMap(t);return Mr(r)?r:void 0}function Z7(e){let t=!0;function r(n){return t=t&&!n.encoding&&!gm(n),t&&\"recur\"in n&&n.recur(r),n}return\"recur\"in e&&e.recur(r),t}var Mt=qs(e=>{let t=Di(e);if(t!==e){let n=Mt(t);return n===t&&e.encoding===void 0?e:Hn(n,e.context)}let r=\"recur\"in e?e.recur(Mt):e;if(\"encodingChecks\"in r&&r.encodingChecks){let n=Z7(e)?r.encodingChecks:My(r)||bC(r)||ul(r)&&r.typeParameters.length>0?V7(r.encodingChecks):void 0;return Am(r,{encodingChecks:void 0,checks:TC(r.checks,n)})}return r}),gn=qs(e=>Mt(Bn(e)));function Y7(e,t){let r=t,n=r.length,o=r[n-1],s=[new Tt(Bn(ft(e,void 0)),r[0].transformation.flip())];for(let i=1;i{if(e.encoding)return Y7(e,e.encoding);let t=Di(e);if(t!==e){let r=Bn(t);return r===t?e:Hn(r,e.context)}return\"flip\"in e?e.flip(Bn):\"recur\"in e?e.recur(Bn):e});function Ky(e,t){let r=t===0?ot:Er(t);return(n,o)=>n===Ae?dn:n===t?r:F(new _t(e,n,o))}function Vo(e,t){return(r,n)=>r===Ae?dn:t(r)?ot:F(new _t(e,r,n))}function hL(e,t,r){let n=e.encodedParts,o=e.literals,s=t.length;for(let u=0;us)return;let a=new Array(n.length),i;function c(u,f){if(u===n.length)return f===s;if(i?.has(u*(s+1)+f))return!1;let p=n[u];if(u===n.length-1){let d=t.slice(f);if(p.matchPart(d,r)!==void 0)return a[u]=d,!0}else if(p._tag===\"Literal\"){let d=o[u];if(t.startsWith(d,f)&&c(u+1,f+d.length))return a[u]=d,!0}else{let d=s-e.suffixLengths[u+1],m=o[u+1],h=m===void 0?d:t.lastIndexOf(m,d);for(;h>=f;){let y=t.slice(f,h);if(p.matchPart(y,r)!==void 0&&c(u+1,h))return a[u]=y,!0;if(h===0)break;h=m===void 0?h-1:t.lastIndexOf(m,h-1)}}return i??=new Set,i.add(u*(s+1)+f),!1}return c(0,0)?a:void 0}var DC=du(e=>{switch(e._tag){default:return e;case\"Number\":return e.toCodecStringTree();case\"Union\":return e.recur(DC)}}),By=du(e=>{switch(e._tag){default:return e;case\"Symbol\":case\"UniqueSymbol\":return e.toCodecStringTree();case\"Union\":return e.recur(By)}}),LC=du(e=>{switch(e._tag){default:return e;case\"Number\":case\"Literal\":case\"BigInt\":return e.toCodecStringTree();case\"Union\":return e.recur(LC)}}),xL=\"[\\\\s\\\\S]*?\",gC=new globalThis.RegExp(`^${Sm}$`),Q7=new globalThis.RegExp(`^(?:${Sm}|Infinity|-Infinity|NaN)$`);function $C(e){return wm(gC,{expected:\"a string representing a finite number\",representation:{id:\"effect/schema/isStringFinite\",payload:null},toJsonSchema:()=>({pattern:gC.source}),...e})}var gL=Us(xn,[$C()]),X7=new Tt(gL,ol),eY=new Tt(new Qr([gL,cL]),ol),tY=\"-?\\\\d+\",yC=new globalThis.RegExp(`^${tY}$`);function KC(e){return wm(yC,{expected:\"a string representing a bigint\",representation:{id:\"effect/schema/isStringBigInt\",payload:null},toJsonSchema:()=>({pattern:yC.source}),...e})}var BC=Us(xn,[KC({expected:\"a string representing a bigint\"})]),rY=new Tt(BC,Oy),nY=\"Symbol\\\\(([\\\\s\\\\S]*)\\\\)\",SC=new globalThis.RegExp(`^${nY}$`),oY=Us(xn,[jC()]),yL=new Tt(oY,new Ke(le(e=>globalThis.Symbol.for(SC.exec(e)[1])),Rt((e,t)=>globalThis.Symbol.keyFor(e)!==void 0?g(globalThis.String(e)):F(new iu({message:\"cannot serialize to string, Symbol is not registered\"},e,t)))));function jC(e){return wm(SC,{expected:\"a string representing a symbol\",representation:{id:\"effect/schema/isStringSymbol\",payload:null},toJsonSchema:()=>({pattern:SC.source}),...e})}function Zo(e,t,r,n,o){for(let s=0;s0;){let o=n[n.length-1],s=o.keys;if(typeof s==\"number\"){if(o.index(e,t,r)=>ml(e)?ot:F(new _t(t,e,r)),{representation:{id:\"effect/schema/Json\",payload:null},expected:\"JSON value\",toCodecJson:()=>{},toCodecStringTree:()=>zC}),EL=Go(cl,{representation:{id:\"effect/schema/MutableJson\",payload:null}}),HC=new Tt(cl,nl()),IL=new Tt(new Qr([new jn(!1,[],[cl]),new bm([],[new CC(xn,cl)])]),nl());function iY(e){return bL(e,aY)}var cY=new fl([],()=>(e,t,r)=>iY(e)?ot:F(new _t(t,e,r)),{expected:\"StringTree\",toCodecStringTree:()=>{}}),zC=new Tt(cY,nl());var Hy=(e,t,r)=>e===ot?r(t):Ct(e,r);function AL(e){let t=uY(e);return(r,n,o)=>{try{return t(r,n,o)}catch(s){return yr(s)}}}function uY(e){if(e._tag===\"Middleware\")return(r,n,o)=>{let s=r===ot?e.decode(Er(im(n)),o):e.decode(fn(r,im),o);return wL(s)};let t=e.decode;switch(t._tag){case\"Passthrough\":return(r,n)=>r===ot?Er(n):r;case\"Transform\":{let r=n=>n===Ae?dn:Er(t.transform(n));return(n,o)=>Hy(n,o,r)}case\"TransformOptional\":{let r=n=>QA(t.transform(im(n)));return(n,o)=>Hy(n,o,r)}case\"TransformEffect\":return(r,n,o)=>Hy(r,n,s=>s===Ae?dn:t.transform(s,o));case\"TransformOptionalEffect\":return(r,n,o)=>Hy(r,n,s=>wL(t.transform(im(s),o)))}}var wL=e=>Ct(e,QA),CL=(e,t,r,n)=>nt(n,o=>da(()=>fa(o,s=>new T2(e,s,t,r))));function fY(e,t){let r=AL(e.link.transformation),n;return(o,s)=>{if(o===Ae)return dn;if(e.isConstructed(o))return ot;let a=(n??=t(e.link.to))(o,s);return r(a,o,s)}}function lY(e,t){let r=e.context.constructorDefault;return(n,o)=>{if(n!==Ae&&n!==void 0)return t(n,o);let s=r;if(Ve(s)&&s._tag===\"Success\"){let a=t(s[xe],o);return a===ot?s:a}return Ct(CL(e,n,o,s),a=>{let i=t(a,o);return i===ot?Er(a):i})}}function WC(e,t){let r=t(e);return e.context?.constructorDefault===void 0?r:lY(e,r)}function vm(e,t,r,n,o){if(e._tag===\"Declaration\")for(let h of e.typeParameters)t(h);let s=r?jy(e):void 0,a=s?fY(s,t):n??e.getParser(t,r),i=e.checks,c=e.encoding,u=c?.map(h=>AL(h.transformation)),f=e.encodingChecks;if(!c&&!i&&!f)return a;let p,d=(h,y)=>{let S=a(h,y);try{if(f&&!y.disableChecks)if(Ve(S)){if(S._tag===\"Success\"){let b=S===ot?h:S[xe];if(h!==Ae&&b!==Ae){let x=Zo(f,h,void 0,e,y);x&&(S=F(new Ht(e,x,h,y)))}}}else S=C(S,b=>{if(h!==Ae&&b!==Ae){let x=Zo(f,h,void 0,e,y);if(x)return F(new Ht(e,x,h,y))}return g(b)});if(i&&!y.disableChecks)if(Ve(S)){if(S._tag===\"Success\"){let b=S===ot?h:S[xe];if(b===Ae)return S;let x=Zo(i,b,void 0,e,y);x&&(S=F(new Ht(e,x,b,y)))}}else S=C(S,b=>{if(b!==Ae){let x=Zo(i,b,void 0,e,y);if(x)return F(new Ht(e,x,b,y))}return g(b)});return S}catch(b){return yr(b)}},m=o===void 0?d:o(d);return c?(h,y)=>{let S=p??=c.map(w=>t(w.to)),b=h,x=S[S.length-1](h,y);for(let w=c.length-1;w>=0;w--)if(x=u[w](x,b,y),w!==0){let I=S[w-1];x._tag===\"Success\"?(b=x[xe],x=I(b,y)):x=Ct(x,T=>{let P=I(T,y);return P===ot?Er(T):P})}if(x._tag===\"Success\"){let w=x[xe],I=m(w,y);return I===ot?x:I}return x=CL(e,h,y,x),Ct(x,w=>{let I=m(w,y);return I===ot?Er(w):I})}:m}var qy=Symbol(),TL=new WeakMap,vL,hl=!1;var dY=e=>hl?Wy(Xr,e,\"parser\"):Xr(e).parser,kL=e=>hl?Wy(Xr,e,\"makeEffect\"):Xr(e).makeEffect,mY=e=>WC(e,kL),zy=class{ast;constructor(t){this.ast=t}get decodeEffect(){return this.cachedDecodeEffect??=vm(this.ast,dY)}get parser(){return this.decodeEffect}get makeEffect(){return this.cachedMakeEffect??=vm(this.ast,kL,mY)}},qC=class extends zy{compiled;resolve;constructor(t,r,n){super(t),this.compiled=r,this.resolve=n}save(t,r){return Object.defineProperty(this,t,{value:r}),r}operation(t){let r=this.compiled;return typeof r==\"function\"?r(this.ast,this.resolve,t):r?.[t]}get is(){return this.save(\"is\",this.operation(\"is\"))}get decode(){return this.save(\"decode\",this.operation(\"decode\"))}get make(){return this.save(\"make\",this.operation(\"make\"))}get compiledMakeEffect(){return this.save(\"compiledMakeEffect\",this.operation(\"makeEffect\"))}get decodeEffect(){return this.save(\"decodeEffect\",this.operation(\"decodeEffect\")??vm(this.ast,t=>Wy(this.resolve,t,\"parser\")))}get parser(){let t=this.decode;return t===void 0?this.decodeEffect:this.save(\"parser\",hY(t,()=>this.decodeEffect))}get makeEffect(){let t=this.compiledMakeEffect;if(t!==void 0)return this.save(\"makeEffect\",t);let r=n=>Wy(this.resolve,n,\"makeEffect\");return this.save(\"makeEffect\",vm(this.ast,r,n=>WC(n,r)))}};function hY(e,t){let r;return(n,o)=>{if(n!==Ae)try{let s=e(n,o);if(s!==qy)return s===n?ot:Er(s)}catch(s){return yr(s)}return(r??=t())(n,o)}}function Wy(e,t,r){let n=e(t);if(n.compiled===void 0||Object.hasOwn(n,r))return n[r];let o;return(s,a)=>(o??=n[r])(s,a)}function Xr(e){let t=TL.get(e);if(t!==void 0)return t;let r=vL===void 0?new zy(e):new qC(e,vL(e,Xr),Xr);return TL.set(e,r),r}function VC(e){let t=e.ast,r;return(n,o)=>(r??=tT(AY,Mt(t)))(n,o?.disableChecks?o?.parseOptions?{...o.parseOptions,disableChecks:!0}:{disableChecks:!0}:o?.parseOptions)}function Gy(e){let t=VC(e);return(r,n)=>{let o=Ts(t(r,n));return ut(o)?_(o.value):(ho(o.cause,\"Option adapter can only return none for schema issues\"),v())}}function OL(e){return IY(Mt(e.ast))}function km(e){return Om(e.ast)}function gY(e){if(!hl){let o=xl(Yy(e));return s=>{let a=o(s,Ns);return ut(a)?!0:(ho(a.cause,\"Type guard adapter can only return false for schema issues\"),!1)}}let t=Xr(e),r=t.is;if(r!==void 0)return o=>{try{return r(o,Ns)}catch(s){return ho(Rc(s),\"Type guard adapter can only return false for schema issues\"),!1}};let n=t.parser;return o=>{let s=Ts(eT(n(o,Ns),o));return ut(s)?!0:(ho(s.cause,\"Type guard adapter can only return false for schema issues\"),!1)}}function Om(e){let t=Mt(e),r=n=>(r=gY(t),r(n));return n=>r(n)}function _L(e){let t=Yy(e);return(r,n)=>{let o=Ts(t(r,n));if(!ut(o))return ho(o.cause,\"Issue adapter can only return schema issues\")}}function RL(e,t){let r=Mt(e.ast),n=Xr(r).parser(t,Ns),o=Ts(eT(n,t));if(no(o)){let s=ho(o.cause,\"Assertion adapter can only throw schema issues\");throw new Error(\"Schema validation failed\",{cause:s})}}function St(e,t){let r=Yy(e.ast);return t===void 0?r:(n,o)=>r(n,XC(t,o))}var ZC=St;function PL(e,t){return xl(St(e,t))}function YC(e,t){return $L(St(e,t))}var ML=YC;function FL(e,t){return KL(St(e,t))}function yY(e,t){return hl?BL(e.ast,t):rT(St(e,t))}var Vy=yY;function hu(e,t){let r=Yy(Bn(e.ast));return t===void 0?r:(n,o)=>r(n,XC(t,o))}var NL=hu;function UL(e,t){return xl(hu(e,t))}function QC(e,t){return $L(hu(e,t))}var DL=QC;function LL(e,t){return KL(hu(e,t))}function SY(e,t){return hl?BL(Bn(e.ast),t):rT(hu(e,t))}var Zy=SY,XC=(e,t)=>t?{...e,...t}:e,Jy=e=>e===Ae?F(new fe):g(e);function Yy(e){return tT(wY,e)}function eT(e,t){return e===ot?g(t):Ve(e)?e[xe]===Ae?Jy(Ae):e:Ct(e,Jy)}function tT(e,t){let r;return(n,o)=>{let s=(r??=e(t))(n,o??Ns);return s===ot?g(n):Ve(s)?s[xe]===Ae?Jy(Ae):s:Ct(s,Jy)}}function xl(e){return(t,r)=>Ts(e(t,r))}function $L(e){let t=xl(e);return(r,n)=>{let o=t(r,n);return ut(o)?_(o.value):(ho(o.cause,\"Option adapter can only return none for schema issues\"),v())}}function KL(e){let t=xl(e);return(r,n)=>{let o=t(r,n);return ut(o)?j(o.value):q(ho(o.cause,\"Result adapter can only return schema issues\"))}}function BL(e,t){let r;return(n,o)=>(r??=bY(Xr(e),t))(n,o)}function bY(e,t){let r=e.decode,n,o=r===void 0?(s,a=Ns)=>(n??=JC(e))(s,a):(s,a=Ns)=>{if(s===Ae)return(n??=JC(e))(s,a);let i;try{i=r(s,a)}catch(c){throw ho(Rc(c),\"Sync adapter can only throw schema issues\"),c}return i!==qy?i:(n??=JC(e))(s,a)};return t===void 0?o:(s,a)=>o(s,XC(t,a))}function JC(e){return rT(tT(()=>e.decodeEffect,e.ast))}function rT(e){let t=xl(e);return(r,n)=>{let o=t(r,n);if(ut(o))return o.value;let s=ho(o.cause,\"Sync adapter can only throw schema issues\");throw new Error(\"Schema validation failed\",{cause:s})}}function EY(e,t){let r=Ts(e);if(ut(r))return r.value;let n=ho(r.cause,t);throw new Error(\"Schema validation failed\",{cause:n})}var jL=\"Constructor adapter can only throw schema issues\";function HL(e){throw new Error(jL,{cause:Rc(e)})}function IY(e){let t;return(r,n)=>GC(t??=Xr(e),r,n)}function GC(e,t,r){let n=r?.disableChecks?r.parseOptions?{...r.parseOptions,disableChecks:!0}:{disableChecks:!0}:r?.parseOptions??Ns,o=e.make;if(o!==void 0&&t!==Ae){let s;try{s=o(t,n)}catch(a){HL(a)}if(s!==qy&&s!==Ae)return s}return EY(eT(e.makeEffect(t,n),t),jL)}function zL(e,t,r,n){let o=Xr(e),s=jy(e);if(s===void 0||o.make!==void 0||o.compiledMakeEffect!==void 0)return GC(o,t,r);if(s.isConstructed(t))return t;let a=GC((o.resolve??Xr)(s.link.to),t,r);try{return n(a)}catch(i){HL(i)}}var wY=e=>Xr(e).parser,AY=e=>Xr(e).makeEffect;var Qy=\"~effect/Schema/Schema\",WL=Symbol(),CY={[Qy]:Qy,get make(){let e=OL(this);return Object.defineProperty(this,\"make\",{value:e,enumerable:!0}),e},get makeEffect(){let e=VC(this);return Object.defineProperty(this,\"makeEffect\",{value:e,enumerable:!0}),e},get makeOption(){let e=Gy(this);return Object.defineProperty(this,\"makeOption\",{value:e,enumerable:!0}),e},pipe(){return te(this,arguments)},annotate(e){return this.rebuild(Go(this.ast,e))},annotateKey(e){return this.rebuild(Tm(this.ast,e))},check(...e){return this.rebuild(Us(this.ast,e))},rebuild(e){return Wn(e,this[WL])}};function Wn(e,t){function r(){}let n=Object.setPrototypeOf(r,CY);return t&&(Object.hasOwn(t,\"name\")||Object.hasOwn(t,\"length\")||Object.hasOwn(t,\"__proto__\"))?Object.defineProperties(n,Object.getOwnPropertyDescriptors({...t})):Object.assign(n,t),n[WL]=t,n.ast=e,n}function JL(e){switch(e){case\"$defs\":case\"properties\":case\"patternProperties\":case\"dependentSchemas\":return\"map\";case\"allOf\":case\"anyOf\":case\"oneOf\":case\"prefixItems\":return\"array\";case\"not\":case\"additionalProperties\":case\"propertyNames\":case\"unevaluatedProperties\":case\"items\":case\"contains\":case\"unevaluatedItems\":case\"if\":case\"then\":case\"else\":case\"contentSchema\":return\"schema\"}}function nT(e){return e.replace(/~/g,\"~0\").replace(/\\//g,\"~1\")}function _m(e){return e.replace(/~1/g,\"/\").replace(/~0/g,\"~\")}function oT(e){return encodeURI(nT(e)).replace(/#/g,\"%23\")}function sT(e){if(e.length===0||e===\"#\")return\"\";if(!e.startsWith(\"#\"))return;let t=e.slice(1);try{if(encodeURI(t).replace(/%25/g,\"%\").replace(/#/g,\"%23\")!==t)return;let r=decodeURIComponent(t);return r.startsWith(\"/\")&&!/~(?:[^01]|$)/.test(r)?r:void 0}catch{return}}function GL(e){let t=sT(e);return t===void 0?void 0:t.length===0?[]:t.slice(1).split(\"/\").map(_m)}function VL(e){return e.reduce((t,r)=>`${t}/${oT(r)}`,\"#\")}var iT=\"http://json-schema.org/draft-07/schema#\",Xy=\"https://json-schema.org/draft/2020-12/schema\";function ZL(e,t){return e===t||e===(t.endsWith(\"#\")?t.slice(0,-1):`${t}#`)}function XL(e){return kY(e)}function kY(e,t){return{dialect:\"draft-07\",...MY(e,HY,void 0,t)}}function OY(e,t){return r(e,!1,!0);function r(n,o,s=!1){if(!fr(n))return n;let a=o||!s&&r$(n.$id),i={};for(let c of Object.keys(n)){let u=n[c],f=u;switch(JL(c)){case\"map\":f=cT(u,p=>r(p,a))??u;break;case\"array\":f=Array.isArray(u)?u.map(p=>r(p,a)):u;break;case\"schema\":f=r(u,a)}B(i,c,f)}return t(i,a),i}}function e$(e,t){return OY(e,r=>{_Y(r,t)})}function _Y(e,t){typeof e.$ref==\"string\"&&B(e,\"$ref\",t(e.$ref,\"$ref\")),typeof e.$dynamicRef==\"string\"&&B(e,\"$dynamicRef\",t(e.$dynamicRef,\"$dynamicRef\"))}function cT(e,t){if(!fr(e))return;let r={};for(let n of Object.keys(e))B(r,n,t(e[n],n));return r}function RY(e,t,r){let n=new Map,o=[],s=aT;function a(d,m=[],h=[]){if(m.length===0&&t?.trackIds){let y=fr(d)?f(d):void 0;s=YL(y,aT)??aT}return u(d,m,h,{sourceRoot:[],targetRoot:[],uri:s})}function i(){for(let[d,m,h]of o){let y=m,S=t$(m,h);if(S!==void 0){let b=GL(S.hash);if(S.hash=\"\",b!==void 0){let x=n.get(QL(S.href,b));x!==void 0&&(y=PY(m,x))}}B(d,\"$ref\",y)}}let c=r(a);return i(),c;function u(d,m,h,y){if(typeof d==\"boolean\")return p(m,h,y),t?.booleanAdapter?.(d)??d;if(!fr(d))return d;let S=y,b=f(d);if(m.length>0&&t?.trackIds&&r$(b)){let I=YL(b,y.uri);I!==void 0&&(S={parent:y,sourceRoot:m,targetRoot:h,uri:I})}p(m,h,S);let x=S.uri,w={isDocumentRoot:m.length===0,schema(I,T,P=T){return u(I,[...m,T],[...h,P],S)},schemaAt(I,T,P){return u(I,[...m,...T],[...h,...P],S)},schemaArray(I,T,P=T){return Array.isArray(I)?I.map((G,he)=>u(G,[...m,T,String(he)],[...h,P,String(he)],S)):I},schemaMap(I,T,P=T){return fr(I)?cT(I,(G,he)=>u(G,[...m,T,he],[...h,P,he],S)):I},reference(I,T){typeof T==\"string\"?o.push([I,T,x]):B(I,\"$ref\",T)}};return e(d,w)}function f(d){return t?.ignoreRefSiblings===!0&&typeof d.$ref==\"string\"?void 0:d.$id}function p(d,m,h){h.parent!==void 0&&p(d,m,h.parent),n.set(QL(h.uri,d.slice(h.sourceRoot.length)),m.slice(h.targetRoot.length))}}var aT=\"https://effect.invalid/.json-schema/\";function t$(e,t){return URL.canParse(e,t)?new URL(e,t):void 0}function YL(e,t){if(typeof e!=\"string\")return;let r=t$(e,t);if(r!==void 0)return r.hash=\"\",r.href}function PY(e,t){let r=e.indexOf(\"#\");return r===-1&&t.length===0?e:`${r===-1?e:e.slice(0,r)}${VL(t)}`}function QL(e,t){return`${e}\\0${JSON.stringify(t)}`}function r$(e){return typeof e==\"string\"&&e.length>0&&e[0]!==\"#\"}function MY(e,t,r,n){return RY(t,{...r,trackIds:!0},o=>({schema:o(e.schema),definitions:cT(e.definitions,(s,a)=>o(s,[...n??[\"$defs\"],a],[...n??[\"definitions\"],a]))}))}var FY=new Set([\"properties\",\"patternProperties\"]),NY=new Set([\"allOf\",\"anyOf\",\"oneOf\"]),UY=new Set([\"not\",\"additionalProperties\",\"propertyNames\",\"contains\",\"if\",\"then\",\"else\",\"contentSchema\"]);function DY(e,t,r,n,o,s=FY){let a;if(s.has(t))a=n.schemaMap(r,t);else if(NY.has(t))a=n.schemaArray(r,t);else if(o.has(t))a=n.schema(r,t);else return!1;return B(e,t,a),!0}var n$=[\"$anchor\",\"$defs\",\"$dynamicAnchor\",\"$dynamicRef\",\"$vocabulary\",\"contentSchema\",\"dependentRequired\",\"dependentSchemas\",\"maxContains\",\"minContains\",\"prefixItems\",\"unevaluatedItems\",\"unevaluatedProperties\"],yge=[...n$,\"deprecated\"],Sge=[...n$,\"$comment\",\"$id\",\"$schema\",\"const\",\"contains\",\"contentEncoding\",\"contentMediaType\",\"else\",\"examples\",\"if\",\"patternProperties\",\"propertyNames\",\"then\"],LY=/^[A-Za-z_][-A-Za-z0-9._]*$/,$Y=/^[A-Za-z][-A-Za-z0-9._:]*$/;function xu(e,t,r){throw new Error(`Cannot convert JSON Schema keyword \"${e}\" to ${t}: ${r}`)}function KY(e,t,r,n){for(let o of t)Object.hasOwn(e,o)&&xu(o,r,`it is not active in ${n} but would become active in the target`)}var BY=[\"additionalItems\",\"definitions\",\"dependencies\"];function jY(e,t,r,n,o){r.isDocumentRoot?B(e,\"$schema\",ZL(t,Xy)?n:t):ZL(t,Xy)||xu(\"$schema\",o,\"an embedded resource cannot declare a different dialect\")}function HY(e,t){KY(e,BY,\"Draft-07\",\"Draft 2020-12\");let r={},n,o,s;for(let a of Object.keys(e)){let i=e[a];if(!DY(r,a,i,t,UY))switch(a){case\"$ref\":n=i;break;case\"$schema\":jY(r,i,t,iT,\"Draft-07\");break;case\"$id\":case\"$anchor\":break;case\"$defs\":B(r,\"definitions\",t.schemaMap(i,a,\"definitions\"));break;case\"prefixItems\":o=i;break;case\"items\":s=i;break;case\"dependentRequired\":case\"dependentSchemas\":case\"minContains\":case\"maxContains\":break;case\"$dynamicRef\":case\"$dynamicAnchor\":case\"$vocabulary\":case\"unevaluatedProperties\":case\"unevaluatedItems\":xu(a,\"Draft-07\",\"the target dialect has no equivalent\");case\"required\":case\"enum\":if(Array.isArray(i)&&i.length===0)break;B(r,a,i);break;default:B(r,a,i)}}if(zY(r,o,s,t),Object.hasOwn(e,\"contains\")){let a=e.minContains,i=e.maxContains;(a!==void 0&&a!==1||i!==void 0)&&xu(\"minContains/maxContains\",\"Draft-07\",\"contains cardinality cannot be represented\"),Object.hasOwn(e,\"minContains\")&&B(r,\"minContains\",a)}else Object.hasOwn(e,\"minContains\")&&B(r,\"minContains\",e.minContains),Object.hasOwn(e,\"maxContains\")&&B(r,\"maxContains\",e.maxContains);return qY(e,r,t,\"draft-07\"),JY(e,r,\"$id\",\"Draft-07\"),Array.isArray(e.enum)&&e.enum.length===0&&o$(r,{not:{}}),WY(r,n,t),r}function zY(e,t,r,n){if(t===void 0){r!==void 0&&B(e,\"items\",n.schema(r,\"items\"));return}B(e,\"items\",n.schemaArray(t,\"prefixItems\",\"items\")),r!==void 0&&B(e,\"additionalItems\",n.schema(r,\"items\",\"additionalItems\"))}function WY(e,t,r){if(t!==void 0)if(typeof t==\"string\"&&Object.keys(e).length>0){let n={};r.reference(n,t),o$(e,n)}else r.reference(e,t)}function qY(e,t,r,n){let o=fr(e.dependentRequired)?e.dependentRequired:void 0,s=fr(e.dependentSchemas)?e.dependentSchemas:void 0;if(o===void 0&&s===void 0)return;let a={},i=new Set([...Object.keys(o??{}),...Object.keys(s??{})]);for(let c of i){let u=o?.[c],f=s?.[c],p=n===\"draft-04\"&&Array.isArray(u)&&u.length===0;f===void 0?p||B(a,c,u):u===void 0||p?B(a,c,r.schemaAt(f,[\"dependentSchemas\",c],[\"dependencies\",c])):B(a,c,{allOf:[r.schemaAt(f,[\"dependentSchemas\",c],[\"dependencies\",c,\"allOf\",\"0\"]),{required:u}]})}Object.keys(a).length>0&&B(t,\"dependencies\",a)}function o$(e,t){Array.isArray(e.allOf)?e.allOf.push(t):B(e,\"allOf\",[t])}function JY(e,t,r,n){let o=e.$id,s=e.$anchor;if(s===void 0){o!==void 0&&B(t,r,o);return}(typeof s!=\"string\"||!LY.test(s))&&xu(\"$anchor\",n,\"the anchor is not valid\"),$Y.test(s)||xu(\"$anchor\",n,\"the anchor cannot be represented as a plain-name fragment identifier\"),o===void 0?B(t,r,`#${s}`):xu(\"$anchor\",n,\"it cannot be combined with the schema $id\")}function tS(e){return Wn(gl(e.ast),{schema:e})}var gl=i$(VY);function i$(e,t){let r=on(o=>{let s=Hn(o,void 0),a=e(s,n);return a===s?null:a}),n=du(o=>{let s=r(Di(o));if(s===null)return o;let a=Hn(s,o.context);return o.context===void 0?a:FC(a,c$(o.context))},t);return n}function c$(e){return e.constructorDefault===void 0?e:new Fs(e.isOptional,e.isMutable,void 0,e.annotations)}function u$(e){if(e.propertySignatures.some(t=>typeof t.name!=\"string\"))throw new globalThis.Error(\"Objects property names must be strings\",{cause:e})}function f$(e){return t=>{let r=[...t].sort((o,s)=>e(gn(o))-e(gn(s)));return r.some((o,s)=>o!==t[s])?r:t}}var GY=f$(e=>{switch(e._tag){case\"BigInt\":case\"Symbol\":case\"UniqueSymbol\":return 0;default:return 1}});function VY(e,t){switch(e._tag){case\"Declaration\":{let r=e.annotations?.toCodecJson??e.annotations?.toCodec;if(!qr(r))return ft(e,[HC]);let n=e.typeParameters.map(s=>Wn(gn(s))),o=r(n);return o===void 0?e:ft(e,[pl(o,t)])}case\"Unknown\":return ft(e,[HC]);case\"ObjectKeyword\":return ft(e,[IL]);case\"Undefined\":case\"Void\":case\"Literal\":case\"Number\":return e.toCodecJson();case\"UniqueSymbol\":case\"Symbol\":case\"BigInt\":return e.toCodecStringTree();case\"Objects\":return u$(e),e.recur(t,By);case\"Union\":{let r=GY(e.types);return r!==e.types?new Qr(r,e.options,e.annotations,e.checks,e.encoding,e.context,e.encodingChecks).recur(t):e.recur(t)}case\"Arrays\":case\"Suspend\":return e.recur(t)}return e}function rS(e){return Wn(l$(Mt(e.ast)))}var l$=on(e=>{let t=ZY(e,l$);return t!==e&&e.context!==void 0?FC(t,c$(e.context)):t});function ZY(e,t){switch(e._tag){case\"Declaration\":{let r=e.annotations?.toCodecIso??e.annotations?.toCodec;if(qr(r)){let n=r(e.typeParameters.map(o=>Wn(o)));return ft(e,[pl(n,t)])}return e}case\"Arrays\":case\"Objects\":case\"Union\":case\"Suspend\":return e.recur(t)}return e}function nS(e){return Wn(tQ(e.ast),{schema:e})}function p$(e){return Wn(h$(e.ast))}var YY=f$(e=>{switch(e._tag){case\"Null\":case\"Boolean\":case\"Number\":case\"BigInt\":case\"Symbol\":case\"UniqueSymbol\":return 0;default:return 1}});function QY(e,t,r){switch(e._tag){case\"Declaration\":{let n=e.typeParameters.map(u=>Wn(t(gn(u)))),o=e.annotations?.toCodecStringTree;if(qr(o)){let u=o(n);return u===void 0?e:ft(e,[pl(u,t)])}let s=e.annotations?.toCodecJson,a=qr(s)?s(n):void 0,i=a===void 0?e.annotations?.toCodec:void 0,c=a??(qr(i)?i(n):void 0);return c===void 0?r(e):ft(e,[pl(c,t)])}case\"Null\":return ft(e,[XY]);case\"Boolean\":return ft(e,[eQ]);case\"Unknown\":case\"ObjectKeyword\":return ft(e,[zC]);case\"Enum\":case\"Number\":case\"Literal\":case\"UniqueSymbol\":case\"Symbol\":case\"BigInt\":return e.toCodecStringTree();case\"Objects\":return u$(e),e.recur(t,By);case\"Union\":{let n=YY(e.types);return n!==e.types?new Qr(n,e.options,e.annotations,e.checks,e.encoding,e.context,e.encodingChecks).recur(t):e.recur(t)}case\"Arrays\":case\"Suspend\":return e.recur(t)}return e}var XY=new Tt(new Kn(\"null\"),new Ke(le(()=>null),le(()=>\"null\"))),eQ=new Tt(new Qr([new Kn(\"true\"),new Kn(\"false\")]),new Ke(le(e=>e===\"true\"),uu())),d$=new Ke(le(e=>typeof e==\"string\"?[e]:e),hn()),m$=e=>e.transformation===d$,tQ=i$((e,t)=>QY(e,t,r=>{throw new globalThis.Error(\"Missing structural codec for StringTree\",{cause:r})}),{stopAt:m$}),a$=e=>nr(e)?mu(Jo):Jo,h$=du(e=>{let t=iQ(e);if(My(t)){let r=Oa(new Qr([new jn(t.isMutable,t.elements.map(a$),t.rest.map(a$)),xn],{mode:\"anyOf\"}),t,d$);return nr(e)?mu(r):r}return t},{stopAt:m$});function x$(e){return Wn(rQ(e.ast),{schema:e})}var rQ=qs(e=>oS(eS(gl(e)))),eS=du(e=>{switch(e._tag){case\"Objects\":return e.recur(t=>nQ(eS(t)),D);case\"Arrays\":return e.recur(t=>oS(eS(t)));case\"Declaration\":case\"Union\":case\"Suspend\":return e.recur(eS)}return e}),nQ=dl(e=>nr(e)?g$(e):oS(e)),g$=dl(e=>gm(e)?e.recur(g$):aQ(e)||y$(e)?e:uT(e,fT(ll,S$))),oS=dl(e=>gm(e)?e.recur(oS):My(e)&&e.elements.length===0&&e.rest.length===1?uT(e,fT(Cm(oQ,e.checks),b$)):bC(e)&&e.propertySignatures.length===0&&e.indexSignatures.length>0?uT(e,fT(Cm(sQ,e.checks),E$)):e);function y$(e){let t=pu(e);switch(t._tag){case\"Union\":return t.checks===void 0&&t.types.some(y$);case\"Null\":case\"Unknown\":case\"Any\":case\"Declaration\":return km(Wn(Hn(t,void 0)))(null)}return!1}function uT(e,t){return Hn(new Qr([Hn(e,void 0),t]),e.context)}var lT=e=>new Ke(e,cu(()=>\"Go nil values are never encoded\")),S$=lT(ka(()=>v())),b$=lT(le(()=>[])),E$=lT(le(()=>({}))),oQ=new jn(!1,[],[]),sQ=$y(xn,ll);function fT(e,t){return Oa(ym,e,t)}function aQ(e){if(!Fy(e))return!1;let t=e.types[e.types.length-1].encoding?.[0].transformation;return t===S$||t===b$||t===E$}function iQ(e){return e._tag===\"Declaration\"||e._tag===\"Arrays\"||e._tag===\"Objects\"||e._tag===\"Union\"||e._tag===\"Suspend\"?e.recur(h$):e}var Ege=globalThis.RegExp;var _a=e=>e.replace(/[/\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\");function gu(e,t){return t.length>0&&(e+=`\n at ${Ph(t)}`),new Error(e)}function I$(e){return`#/$defs/${oT(e)}`}var cQ=new Set([...A2,au,...w2]);function sS(e,t){if(e===void 0)return;let r={};for(let i of[\"title\",\"description\",\"format\",\"contentEncoding\",\"contentMediaType\"]){let c=e[i];typeof c==\"string\"&&(r[i]=c)}for(let i of[\"readOnly\",\"writeOnly\"]){let c=e[i];typeof c==\"boolean\"&&(r[i]=c)}let n=e.expected;r.description===void 0&&t?.generateDescriptions===!0&&typeof n==\"string\"&&(r.description=n);let o=e.default;ml(o)&&(r.default=o);let s=e.examples;Array.isArray(s)&&ml(s)&&(r.examples=s);let a=e.contentSchema;if(ml(a)&&(r.contentSchema=a),t?.includeAnnotationKey!==void 0)for(let[i,c]of Object.entries(e))cQ.has(i)||!t.includeAnnotationKey(i)||ml(c)&&B(r,i,c);return Object.keys(r).length===0?void 0:r}function w$(e){let t=e.type===\"number\"||e.type===\"integer\"?e.type:void 0,r=e;if(t!==void 0&&(r={...e},delete r.type),Array.isArray(r.allOf)){let n=[],o=!1;for(let s of r.allOf){let a=w$(s);a.type!==void 0&&(o=!0,(t===void 0||a.type===\"integer\")&&(t=a.type)),Object.keys(a.schema).length>0&&n.push(a.schema)}if(o){let{allOf:s,...a}=r;r=n.length===0?a:{...a,allOf:n}}}return{type:t,schema:r}}function uQ(e){if(!Array.isArray(e.anyOf)||e.anyOf.length!==2||e.anyOf[0]?.type!==\"number\")return!1;let t=e.anyOf[1];return t?.type===\"string\"&&Array.isArray(t.enum)&&t.enum.length===3&&t.enum.includes(\"NaN\")&&t.enum.includes(\"Infinity\")&&t.enum.includes(\"-Infinity\")}var A$=\"|type|format|pattern|multipleOf|minimum|maximum|exclusiveMinimum|exclusiveMaximum|minLength|maxLength|minItems|maxItems|uniqueItems|minProperties|maxProperties|propertyNames|\";function aS(e,t){return Object.keys(e).every(r=>t.includes(`|${r}|`))}function fQ(e,t){return typeof e.$ref!=\"string\"&&t.every(r=>!Object.hasOwn(e,r))}var lQ=\"|minimum|exclusiveMinimum|minLength|minItems|minProperties|\",pQ=\"|maximum|exclusiveMaximum|maxLength|maxItems|maxProperties|\";function dQ(e,t,r){if(typeof e.$ref==\"string\")return;let n={...e,...t};for(let o of r){if(!Object.hasOwn(e,o))continue;let s=e[o],a=t[o];if(typeof s!=\"number\"||typeof a!=\"number\")return;if(lQ.includes(`|${o}|`))n[o]=Math.max(s,a);else if(pQ.includes(`|${o}|`))n[o]=Math.min(s,a);else return}return typeof n.minimum==\"number\"&&typeof n.exclusiveMinimum==\"number\"&&delete n[n.exclusiveMinimum>=n.minimum?\"minimum\":\"exclusiveMinimum\"],typeof n.maximum==\"number\"&&typeof n.exclusiveMaximum==\"number\"&&delete n[n.exclusiveMaximum<=n.maximum?\"maximum\":\"exclusiveMaximum\"],n}var mT=\"|title|description|default|examples|readOnly|writeOnly|\",mQ=A$+mT;function iS(e,t,r){if(Object.keys(e).length===0)return t;let n=Object.keys(t);if(n.length===0)return e;let o=e.type===\"number\"||e.type===\"integer\"?e.type:void 0,s=uQ(e);if(o!==void 0||s){let i=w$(t);if(i.type!==void 0){let c=o===\"integer\"||i.type===\"integer\"?\"integer\":\"number\",u={...e,type:c};s&&delete u.anyOf;let f=Object.keys(i.schema);return f.length===0?u:aS(i.schema,mT)&&fQ(u,f)?{...u,...i.schema}:iS(u,i.schema,r)}}if(r){let i=dQ(e,t,n);if(i!==void 0)return i}let a=Array.isArray(t.allOf)&&n.length===1?t.allOf:[t];return Array.isArray(e.allOf)?{...e,allOf:[...e.allOf,...a]}:typeof e.$ref==\"string\"?{allOf:[e,...a]}:{...e,allOf:a}}function dT(e,t=new Set){return typeof e==\"boolean\"?e:t.has(e)?!0:(t.add(e),e.every(r=>dT(r,t)))}function hQ(e){return Array.isArray(e)}function xQ(e,t,r,n){let o=`^(?:${Sm}|Infinity|-Infinity|NaN)$`,s=new Map,a=new Map,i=new WeakMap,c=new Map,u=new Map,f=Object.keys(r);for(let E of f)S(E,[\"references\",E]);let p=kn(e,(E,R)=>I(E,t[R],[]));for(let{branches:E,schemas:R}of c.values())if(!dT(E))for(let N of R)Array.isArray(N.oneOf)&&(N.anyOf=N.oneOf,delete N.oneOf);for(let E of f){let R=r[E],N=x(R);if(N===void 0)continue;let O=s.get(E).schema,M=u.get(N),U=M?.find(pe=>Z(s.get(pe).schema,O));U===void 0?M===void 0?u.set(N,[E]):M.push(E):a.set(E,U)}let d=kn(p,b),m={};for(let E of f)a.has(E)||B(m,E,b(s.get(E).schema));return{dialect:\"draft-2020-12\",schemas:d,definitions:m};function h(E){return Array.isArray(E.oneOf)&&c.get(E.oneOf)?.schemas.push(E),E}function y(E,R,N){let O=I(E.type,[...R,\"type\"],N),M=sS(E.annotations,n);return M===void 0?O:h(iS(O,M))}function S(E,R){if(!Object.hasOwn(r,E))throw gu(`Invalid reference ${E}`,[...R,\"$ref\"]);let N=s.get(E);if(N!==void 0)return N;let O={schema:{},dependencies:[]};return s.set(E,O),O.schema=I(r[E],[\"references\",E],O.dependencies),O}function b(E){return e$(E,R=>{let N=sT(R);if(N===void 0){if(/^#(?:\\/|%2f)/i.test(R))throw new Error(`Invalid JSON Pointer URI fragment ${JSON.stringify(R)}`);return R}if(!N.startsWith(\"/$defs/\"))return R;let O=N.indexOf(\"/\",7),M=a.get(_m(N.slice(7,O<0?void 0:O)));return M===void 0?R:R.replace(/^#(?:\\/|%2f).*?(?:\\/|%2f).*?(?=\\/|%2f|$)/i,I$(M))})}function x(E){if(E._tag===\"Reference\")return;let R=E.checks.length===0?E.annotations:E.checks[E.checks.length-1].annotations;return typeof R?.identifier!=\"string\"&&typeof R?.[au]==\"string\"?R[au]:void 0}function w(E,R,N,O){let M=E.annotations,U=M?.toJsonSchema;if(U!==void 0){let ee=E.representation?.schemas?.map((vr,is)=>I(vr,[...N,\"representation\",\"schemas\",is],O))??[],Qe=U({type:R,schemas:ee}),qe=hQ(Qe);qe&&O.push(!1);let et=qe?Qe[0]:Qe,De=sS(M,n),xt=De===void 0?et:{...et,...De},vt=De===void 0?A$:mQ;return[xt,E._tag===\"Filter\"&&aS(xt,vt)&&(De===void 0||aS(De,mT))?!0:void 0]}if(E._tag===\"Filter\"){O.push(!1);return}let pe=E.checks.flatMap((ee,Qe)=>{let qe=w(ee,R,[...N,\"checks\",Qe],O);return qe===void 0?[]:[qe[0]]});if(pe.length===0)return;let He=sS(M,n),ze={allOf:pe};return[He===void 0?ze:{...ze,...He}]}function I(E,R,N){if(E._tag===\"Reference\")return N.push(S(E.$ref,R).dependencies),{$ref:I$(E.$ref)};let O=i.get(E);if(O!==void 0)return N.push(O.dependencies),O.schema;let M=[];N.push(M);let U={...T(E,R,M),...sS(E.annotations,n)};if(E._tag===\"String\"&&E.content!==void 0){let pe=E.content;U.contentMediaType=pe.mediaType,delete U.contentSchema,pe.schema!==void 0&&(U.contentSchema=I(pe.schema,[...R,\"content\",\"schema\"],[]))}for(let pe=0;pe({type:typeof U,enum:[U],title:M}));return O.length===0?{not:{}}:{anyOf:O}}case\"TemplateLiteral\":{let{exact:O,pattern:M}=me(E.parts);return O||N.push(!1),{type:\"string\",pattern:M}}case\"Arrays\":{let O={type:\"array\"},M=E.elements.length,U=E.elements.map((pe,He)=>(pe.isOptional&&M--,y(pe,[...R,\"elements\",He],N)));if(U.length>0?(O.prefixItems=U,O.maxItems=E.elements.length,M>0&&(O.minItems=M)):O.items=!1,E.rest.length===1){delete O.maxItems;let pe=I(E.rest[0],[...R,\"rest\",0],N);Object.keys(pe).length>0?O.items=pe:delete O.items}else E.rest.length>1&&(delete O.maxItems,delete O.items,O.minItems=M+E.rest.length-1,N.push(!1));return O}case\"Objects\":return P(E,R,N);case\"Union\":{let O=[],M=E.types.map((U,pe)=>I(U,[...R,\"types\",pe],O));if(N.push(O),M.length===0)return{not:{}};if(E.options?.mode===\"oneOf\")return c.set(M,{branches:O,schemas:[]}),{oneOf:M};if(M.length>1){let U=yQ(M);if(U!==void 0)return U}return{anyOf:M.flatMap(U=>Array.isArray(U.anyOf)&&Object.keys(U).length===1?U.anyOf:[U])}}}}function P(E,R,N){let{indexSignatures:O,propertySignatures:M}=E;if(M.length===0&&O.length===0)return{not:{type:\"null\"}};let U={type:\"object\"},pe={},He=[];for(let[De,xt]of M.entries()){let vt=[...R,\"propertySignatures\",De];if(typeof xt.name!=\"string\")throw gu(\"Objects property names must be strings\",[...vt,\"name\"]);B(pe,xt.name,y(xt,vt,N)),xt.isOptional||He.push(xt.name)}M.length>0&&(U.properties=pe),He.length>0&&(U.required=He);let ze=O.map((De,xt)=>{let vt=[...R,\"indexSignatures\",xt],vr=I(De.type,[...vt,\"type\"],N),is=Z(vr,{not:{}})?!1:vr,Ws=he(De.parameter,[...vt,\"parameter\"],new Set);return Ws===void 0&&N.push(!1),{type:is,patterns:Ws}}),ee={};for(let{patterns:De,type:xt}of ze)for(let vt of De??[]){let vr=ee[vt];B(ee,vt,vr===void 0?xt:vr===!1||xt===!1?!1:h(iS(vr,xt)))}let Qe=Object.keys(ee).length>0;Qe&&(U.patternProperties=ee);let qe=ze.filter(({patterns:De})=>De?.length===0).map(({type:De})=>De),et=ze.some(({patterns:De})=>De===void 0);if(et&&n?.onExcessProperty===\"error\"){let De=[];M.length>0&&De.push({enum:Object.keys(pe)});for(let[vt,vr]of O.entries())De.push(G(vr.parameter,[...R,\"indexSignatures\",vt,\"parameter\"],N,new Set));U.propertyNames=De.length===1?De[0]:{anyOf:De};let xt=ze.map(({type:vt})=>vt);U.additionalProperties=xt.length===1?xt[0]:{anyOf:xt},qe.length>0&&(U.allOf=qe.map(vt=>({type:\"object\",additionalProperties:vt})))}else qe.length===0?U.additionalProperties=et||n?.onExcessProperty!==\"error\":qe.length===1&&M.length===0&&!Qe?U.additionalProperties=qe[0]:U.allOf=qe.map(De=>({type:\"object\",additionalProperties:De}));return typeof U.additionalProperties==\"object\"&&U.additionalProperties!==null&&Object.keys(U.additionalProperties).length===0&&delete U.additionalProperties,U}function G(E,R,N,O){switch(E._tag){case\"Number\":return{type:\"string\",pattern:o};case\"Reference\":return O.has(E.$ref)?{type:\"string\"}:G(r[E.$ref],[\"references\",E.$ref],N,new Set(O).add(E.$ref));case\"Union\":return{anyOf:E.types.map(M=>G(M,R,N,O))};default:return I(E,R,N)}}function he(E,R,N){switch(E._tag){case\"Reference\":{if(S(E.$ref,R),N.has(E.$ref))return;let O=new Set(N).add(E.$ref);return he(r[E.$ref],[\"references\",E.$ref],O)}case\"String\":{if(E.checks.length===0)return[];if(E.checks.length!==1||E.checks[0]._tag!==\"Filter\"||E.checks[0].annotations?.toJsonSchema===void 0)return;let O=[],M=I(E,R,O);return dT(O)&&M.type===\"string\"&&typeof M.pattern==\"string\"&&aS(M,\"|type|pattern|title|description|default|examples|readOnly|writeOnly|\")?[M.pattern]:void 0}case\"TemplateLiteral\":{if(E.checks.length>0)return;let{exact:O,pattern:M}=me(E.parts);return O?[M]:void 0}case\"Union\":{if(E.types.length===0||E.checks.length>0||E.options?.mode===\"oneOf\")return;let O=[];for(let M=0;M0&&(N=!1),U._tag){case\"Reference\":{if(!Object.hasOwn(r,U.$ref))throw gu(`Invalid reference ${U.$ref}`,[]);if(R.has(U.$ref))throw gu(`Invalid recursive TemplateLiteral part ${U.$ref}`,[]);R.add(U.$ref);let pe=M(r[U.$ref]);return R.delete(U.$ref),pe}case\"Literal\":return _a(globalThis.String(U.literal));case\"String\":return xL;case\"Number\":return Sm;case\"BigInt\":return\"-?\\\\d+\";case\"TemplateLiteral\":return U.parts.map(M).join(\"\");case\"Union\":return U.types.length===0?\"(?!)\":(U.options?.mode===\"oneOf\"&&(N=!1),`(?:${U.types.map(M).join(\"|\")})`);default:throw gu(`Invalid TemplateLiteral part ${U._tag}`,[])}}}}function gQ(e){return e===\"string\"||e===\"number\"||e===\"boolean\"||e===\"array\"||e===\"object\"||e===\"null\"||e===\"integer\"}function yQ(e){let t,r=[];for(let n of e){if(Object.keys(n).length!==2||n.type===void 0||!Array.isArray(n.enum)||n.enum.length===0)return;if(t===void 0)t=n.type;else if(n.type!==t)return;for(let s of n.enum){if(r.includes(s))return;r.push(s)}}return{type:t,enum:r}}function cS(e,t){let r=xQ([e.representation],[[\"representation\"]],e.references,t);return{dialect:r.dialect,schema:r.schemas[0],definitions:r.definitions}}var SQ=({identifier:e})=>e;function hT(e){return e===void 0?void 0:{annotations:e}}function Pm(e,t){let{references:r,representations:n}=bQ([e],t);return{representation:n[0],references:r}}function bQ(e,t){let r={},n=new Set,o=new Map;for(let x of e)f(x);let s=t?.referencePolicy??SQ;for(let x of o.values())for(let w of x){let I=s({ast:w.ast,occurrences:w.occurrences,identifier:w.identifier});if(I!==void 0){let T=I===w.identifier||!I.endsWith(\"_\")?\"_\":\"\";w.reference=i(I,T)}else w.isRecursive&&(w.reference=i(`${w.ast._tag}_`,\"\"))}return{representations:kn(e,m),references:r};function i(x,w){let I=x,T=0;for(;n.has(I);)I=`${x}${w}${++T}`;return n.add(I),I}function c(x,w,I){let T=w.fallback;return T!==void 0?ZA(x)===T?x:Go(x,{[au]:T}):I===w.identifier?x:Go(x,{identifier:I})}function u(x,w=x.encoding?.length??0){let I=x,T;for(;I.encoding!==void 0&&w>0;){let R=I.encoding[w-1];if(R.to.encoding===void 0&&R.to._tag===\"String\"){let N=uD(R.transformation.encode);N!==void 0&&(T={mediaType:N.mediaType,schema:N.preserveSchema?u(I,w-1):void 0})}I=R.to,w=I.encoding?.length??0}let P=Di(I),G=Xf(I),he=G===void 0?(I!==x?Xf(x):void 0)??ZA(I):void 0;he!==void 0&&(G=`${he}Encoded`);let me=o.get(P);me===void 0&&(me=[],o.set(P,me));let E=me.find(R=>R.identifier===G&&R.content?.mediaType===T?.mediaType&&R.content?.schema===T?.schema);return E===void 0&&(E={ast:P,identifier:G,fallback:he,content:T,occurrences:0},me.push(E)),E}function f(x){return p(u(x)),x}function p(x){let w=x.ast;if(x.occurrences++,x.visiting){x.isRecursive=!0;return}if(!(x.occurrences>1)){switch(x.visiting=!0,x.content?.schema!==void 0&&p(x.content.schema),d(w.checks),w._tag){default:\"recur\"in w&&w.recur(f);break;case\"TemplateLiteral\":w.parts.forEach(f);break;case\"Suspend\":f(w.thunk());break}x.visiting=!1}}function d(x){x?.forEach(w=>{w.annotations?.representation?.schemas?.forEach(I=>f(Mt(I))),w._tag===\"FilterGroup\"&&d(w.checks)})}function m(x){return h(u(x))}function h(x){let w=x.ast,I=x.reference;if(I!==void 0){if(!x.emitted){x.emitted=!0;let T=x.identifier===void 0?w:c(w,x,I),P=y(T,x.content);B(r,I,P)}return{_tag:\"Reference\",$ref:I}}return y(w,x.content)}function y(x,w){let I={checks:x.checks?.map(S)??[],...x._tag===\"Declaration\"?b(x.annotations):hT(x.annotations)};switch(x._tag){case\"Declaration\":return{_tag:x._tag,typeParameters:x.typeParameters.map(m),...I};default:return{_tag:x._tag,...w===void 0?void 0:{content:{mediaType:w.mediaType,...w.schema===void 0?void 0:{schema:h(w.schema)}}},...I};case\"Literal\":return{_tag:x._tag,literal:x.literal,...I};case\"UniqueSymbol\":return{_tag:x._tag,symbol:x.symbol,...I};case\"Enum\":return{_tag:x._tag,enums:x.enums,...I};case\"TemplateLiteral\":return{_tag:x._tag,parts:x.parts.map(m),...I};case\"Arrays\":return{_tag:x._tag,elements:x.elements.map(T=>{let P=pu(T),G=P.context?.annotations;return{isOptional:nr(P),type:m(T),...hT(G)}}),rest:x.rest.map(m),...I};case\"Objects\":return{_tag:x._tag,propertySignatures:x.propertySignatures.map(T=>{let P=pu(T.type),G=P.context?.annotations;return{name:T.name,type:m(T.type),isOptional:nr(P),isMutable:dL(P),...hT(G)}}),indexSignatures:x.indexSignatures.map(T=>({parameter:m(T.parameter),type:m(T.type)})),...I};case\"Union\":return{_tag:x._tag,types:x.types.map(m),...x.options===void 0?{}:{options:x.options},...I};case\"Suspend\":return{_tag:x._tag,...I,checks:[],thunk:m(x.thunk())}}}function S(x){return{...x._tag===\"Filter\"?{_tag:x._tag,aborted:x.aborted}:{_tag:x._tag,checks:kn(x.checks,S)},...b(x.annotations,!0)}}function b(x,w=!1){if(x===void 0)return;let{representation:I,...T}=x,P=w&&I?.schemas!==void 0?{...I,schemas:I.schemas.map(G=>m(Mt(G)))}:I;return{...P===void 0?void 0:{representation:P},...Object.keys(T).length===0?void 0:{annotations:T}}}}function v$(e){return ut(e)?e.value:{issues:[{message:n0(e.cause)}]}}function O$(e,t){let r=St(e),n={errors:\"all\",...t?.parseOptions},o=P2(t);return _$(e,{validate:a=>{let i=new bc(\"sync\"),c=Rd(q0(r(a,n),{onFailure:o,onSuccess:f=>({value:f})}),{scheduler:i});c.currentDispatcher?.flush();let u=c.pollUnsafe();return u?v$(u):new Promise(f=>{c.addObserver(p=>{f(v$(p))})})}})}function _$(e,t){let r={version:1,vendor:\"effect\",...Object.hasOwn(e,\"~standard\")?e[\"~standard\"]:void 0,...t},n=typeof e==\"function\"?Function.prototype.bind.call(e,void 0):Object.create(Object.getPrototypeOf(e));return Object.defineProperties(n,{...Object.getOwnPropertyDescriptors(e),ast:{value:e.ast,enumerable:!0,configurable:!0},\"~standard\":{value:r,writable:!0,enumerable:!0,configurable:!0}})}function EQ(e){let t=Pm(gl(e));return cS(t)}function k$(e,t){let r=EQ(e);if(t===\"draft-2020-12\"){let n={$schema:Xy,...r.schema};return Object.keys(r.definitions).length>0&&(n.$defs=r.definitions),n}else if(t===\"draft-07\"){let n=XL(r),o={$schema:iT,...n.schema};return Object.keys(n.definitions).length>0&&(o.definitions=n.definitions),o}throw new globalThis.Error(`Unsupported target: ${t}`)}function R$(e){return _$(e,{jsonSchema:{input(t){return k$(e.ast,t.target)},output(t){return k$(Mt(e.ast),t.target)}}})}function M$(e,t){let r=[];return xT(e,t,\"\",r),r}function xT(e,t,r,n){if(!Object.is(e,t)){if(Array.isArray(e)&&Array.isArray(t)){let o=e.length,s=t.length,a=Math.min(o,s);for(let i=0;i=s;i--)n.push({op:\"remove\",path:`${r}/${i}`});for(let i=o;ii)throw new Error(`Array index out of bounds at \"${t.path}\".`);let c=o.slice();return t.op===\"add\"?c.splice(a,0,t.value):t.op===\"remove\"?c.splice(a,1):c[a]=t.value,P$(s,c)}if(uS(o)){if(t.op!==\"add\"&&!Object.hasOwn(o,n))throw new Error(`Property \"${n}\" does not exist at \"${t.path}\".`);let a={...o};return t.op===\"remove\"?delete a[n]:B(a,n,t.value),P$(s,a)}throw new Error(`Cannot ${t.op} at \"${t.path}\" (parent not found or not a container).`)}function CQ(e,t){let r=wQ(t);if(r.length===0)return null;let n=r[r.length-1],o=[],s=e;for(let a=0;a=s.length)return null;o.push({container:s,token:c}),s=s[c];continue}if(uS(s)){if(!Object.hasOwn(s,i))return null;o.push({container:s,token:i}),s=s[i];continue}return null}return{stack:o,parent:s,lastToken:n}}function P$(e,t){let r=t;for(let n=e.length-1;n>=0;n--){let{container:o,token:s}=e[n];if(Array.isArray(o)){let a=o.slice();a[s]=r,r=a}else{let a={...o};B(a,s,r),r=a}}return r}function D$(e){let t=tS(e),r=Zy(t),n=Vy(t);return{empty:[],diff:(o,s)=>M$(r(o),r(s)),combine:(o,s)=>[...o,...s],patch:(o,s)=>{let a=r(o),i=F$(s,a);return Object.is(i,a)?o:n(i)}}}function L$(e,t){let r=Xf(e.ast)??YA(e.ast),n=NL(nS(e));return o=>n(o).pipe(W(s=>vQ(s,{rootName:r,...t})))}function vQ(e,t){let r=t.rootName??\"root\",n=t.arrayItemName??\"item\",o=t.pretty??!0,s=t.indent??\" \",a=t.sortKeys??!0,i=new Set,c=[];return f(r,e,0),c.join(o?`\n`:\"\");function u(p,d){c.push(o?s.repeat(p)+d:d)}function f(p,d,m,h){let{attrs:y,safe:S}=yl.tagInfo(p,h);if(d===void 0)u(m,`<${S}${y}/>`);else if(typeof d==\"string\")u(m,`<${S}${y}>${yl.escapeText(d)}`);else if(typeof d!=\"object\"||d===null)u(m,`<${S}${y}>${yl.escapeText(K(d))}`);else{if(i.has(d))throw new globalThis.Error(\"Cycle detected while serializing to XML.\",{cause:d});i.add(d);try{if(globalThis.Array.isArray(d)){if(d.length===0){u(m,`<${S}${y}/>`);return}u(m,`<${S}${y}>`);for(let w of d)f(n,w,m+1);u(m,``);return}let b=d,x=Object.keys(b);if(a&&x.sort(),x.length===0){u(m,`<${S}${y}/>`);return}u(m,`<${S}${y}>`);for(let w of x)f(yl.parseTagName(w).safe,b[w],m+1,w);u(m,``)}finally{i.delete(d)}}}}var yl={escapeText(e){return e.replace(/&/g,\"&\").replace(//g,\">\")},escapeAttribute(e){return e.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(//g,\">\")},parseTagName(e){let t=e,r=e;return/^[A-Za-z_]/.test(r)||(r=\"_\"+r),r=r.replace(/[^A-Za-z0-9._-]/g,\"_\"),/^xml/i.test(r)&&(r=\"_\"+r),{safe:r,changed:r!==t}},tagInfo(e,t){let{changed:r,safe:n}=yl.parseTagName(e),s=r||t&&t!==e?` data-name=\"${yl.escapeAttribute(t??e)}\"`:\"\";return{safe:n,attrs:s}}};var gT=on(e=>Li(e));function Li(e){let t=va(e)?.toEquivalence;if(t)return t(ul(e)?e.typeParameters.map(Li):[]);switch(e._tag){case\"Never\":return Wa();case\"Declaration\":return OQ(e);case\"Null\":case\"Undefined\":case\"Void\":case\"Unknown\":case\"Any\":case\"String\":case\"Number\":case\"Boolean\":case\"BigInt\":case\"Symbol\":case\"Literal\":case\"UniqueSymbol\":case\"ObjectKeyword\":case\"Enum\":case\"TemplateLiteral\":return Z;case\"Arrays\":{let r=e.elements.map(Li),n=e.rest.map(Li),[o,...s]=n,a=s.length;return Kt((i,c)=>{if(!Array.isArray(i)||!Array.isArray(c))return!1;let u=i.length;if(u!==c.length)return!1;let f=0;for(;f0){for(;fLi(o.type)),n=e.indexSignatures.map(o=>Li(o.type));return Kt((o,s)=>{if(!fr(o)||!fr(s))return!1;for(let a=0;a[Om(s),Li(e.types[a])]);return Kt((s,a)=>{let i=n(s,!1);for(let c=0;c(r??=gT(e.thunk()))(n,o))}}}function OQ(e){let t=e.annotations?.representation;if(t===void 0)return Z;switch(t.id){case\"effect/schema/Option\":{let[r]=yu(e);return(n,o)=>n._tag===o._tag&&(n._tag===\"None\"||r(n.value,o.value))}case\"effect/schema/Result\":{let[r,n]=yu(e);return(o,s)=>o._tag===s._tag&&(o._tag===\"Success\"?r(o.success,s.success):n(o.failure,s.failure))}case\"effect/schema/CauseReason\":{let[r,n]=yu(e);return K$(r,n)}case\"effect/schema/Cause\":{let[r,n]=yu(e);return $$(r,n)}case\"effect/schema/Exit\":{let[r,n,o]=yu(e),s=$$(n,o);return(a,i)=>a._tag===i._tag&&(a._tag===\"Success\"?r(a.value,i.value):s(a.cause,i.cause))}case\"effect/schema/ReadonlyMap\":{let[r,n]=yu(e);return _h(r,n)}case\"effect/schema/ReadonlySet\":return hp(yu(e)[0]);case\"effect/schema/RegExp\":return(r,n)=>r.source===n.source&&r.flags===n.flags;case\"effect/schema/URL\":return(r,n)=>r.toString()===n.toString();default:return Z}}function yu(e){return e.typeParameters.map(Li)}function K$(e,t){return(r,n)=>{if(r._tag!==n._tag)return!1;switch(r._tag){case\"Fail\":return e(r.error,n.error);case\"Die\":return t(r.defect,n.defect);case\"Interrupt\":return r.fiberId===n.fiberId}}}function $$(e,t){let r=Vu(K$(e,t));return(n,o)=>r(n.reasons,o.reasons)}function j$(e,t){return r=>{switch(r._tag){case\"Fail\":return`Fail(${e(r.error)})`;case\"Die\":return`Die(${t(r.defect)})`;case\"Interrupt\":return\"Interrupt\"}}}function B$(e,t){let r=j$(e,t);return n=>`Cause([${n.reasons.map(r).join(\", \")}])`}function H$(e,t){let r=new Map;return n(e);function n(a){let i=r.get(a);return i===void 0&&(i=o(a),r.set(a,i)),i}function o(a){let i=va(a)?.toFormatter;if(typeof i==\"function\")return i(ul(a)?a.typeParameters.map(n):[]);if(t?.onBefore){let c=t.onBefore(a,n);if(c!==void 0)return c}return s(a)}function s(a){switch(a._tag){default:return K;case\"Never\":return()=>\"never\";case\"Void\":return()=>\"void\";case\"Declaration\":{let i=a.annotations?.representation;if(i===void 0)return K;let c=a.typeParameters.map(n);switch(i.id){case\"effect/schema/Option\":{let[u]=c;return Zt({onNone:()=>\"none()\",onSome:f=>`some(${u(f)})`})}case\"effect/schema/Result\":{let[u,f]=c;return mr({onSuccess:p=>`success(${u(p)})`,onFailure:p=>`failure(${f(p)})`})}case\"effect/schema/CauseReason\":return j$(c[0],c[1]);case\"effect/schema/Cause\":return B$(c[0],c[1]);case\"effect/schema/Exit\":{let[u,f,p]=c,d=B$(f,p);return m=>{switch(m._tag){case\"Success\":return`Exit.Success(${u(m.value)})`;case\"Failure\":return`Exit.Failure(${d(m.cause)})`}}}case\"effect/schema/ReadonlyMap\":{let[u,f]=c;return p=>{let d=p.size;if(d===0)return\"ReadonlyMap(0) {}\";let m=globalThis.Array.from(p.entries()).map(([h,y])=>`${u(h)} => ${f(y)}`).sort();return`ReadonlyMap(${d}) { ${m.join(\", \")} }`}}case\"effect/schema/HashMap\":{let[u,f]=c;return p=>{let d=jU(p);if(d===0)return\"HashMap(0) {}\";let m=em(p).map(([h,y])=>`${u(h)} => ${f(y)}`).sort();return`HashMap(${d}) { ${m.join(\", \")} }`}}case\"effect/schema/ReadonlySet\":{let[u]=c;return f=>{let p=f.size;if(p===0)return\"ReadonlySet(0) {}\";let d=globalThis.Array.from(f.values()).map(m=>`${u(m)}`).sort();return`ReadonlySet(${p}) { ${d.join(\", \")} }`}}case\"effect/schema/HashSet\":{let[u]=c;return f=>{let p=JU(f);if(p===0)return\"HashSet(0) {}\";let d=globalThis.Array.from(f).map(m=>`${u(m)}`).sort();return`HashSet(${p}) { ${d.join(\", \")} }`}}case\"effect/schema/Chunk\":{let[u]=c;return f=>{let p=eN(f);if(p===0)return\"Chunk(0) {}\";let d=globalThis.Array.from(f).map(m=>`${u(m)}`);return`Chunk(${p}) { ${d.join(\", \")} }`}}default:return K}}case\"Arrays\":{let i=a.elements.map(d=>n(d)),c=a.rest.map(n),[u,...f]=c,p=f.length;return d=>{let m=[],h=0;for(;h0){for(;hn(u.type)),c=a.indexSignatures.map(u=>n(u.type));return a.propertySignatures.length===0&&a.indexSignatures.length===0?K:u=>{let f=[],p=new Set;for(let d=0;d0?\"{ \"+f.join(\", \")+\" }\":\"{}\"}}case\"Union\":{let i=Mt(a).types,c=Im(i),u=i.map((f,p)=>[Om(f),n(a.types[p])]);return f=>{let p=c(f,!1);for(let d=0;d(i??=n(a.thunk()))(c)}}}}var yT=l(2,(e,t)=>ET(e,(r,n)=>W$(t,r)?[r,n]:void 0)),ST=l(2,(e,t)=>ET(e,(r,n)=>W$(t,r)?void 0:[r,n])),z$=l(2,(e,t)=>({...e,...t}));var bT=l(2,(e,t)=>ET(e,(r,n)=>[Object.hasOwn(t,r)?t[r]:r,n]));var Kr=e=>e;function W$(e,t){return e.some(r=>r===t||typeof r==\"number\"&&String(r)===t)}function ET(e,t){let r={};for(let n of Reflect.ownKeys(e)){if(!Object.prototype.propertyIsEnumerable.call(e,n))continue;let o=t(n,e[n]);if(o){let[s,a]=o;B(r,s,a)}}return r}function G$(e,t){return Qo(Sl(\"Iso\",e,t))}function q$(e,t){return Qo(Sl(\"Lens\",e,t))}function Sl(e,t,r){return[{_tag:\"PrimitiveNode\",kind:e,get:t,set:r}]}var PQ={kind:\"Iso\",get:D,set:D},fS=class{_tag=\"PathNode\";kind=\"Lens\";path;get;set;constructor(t){this.path=t,this.get=r=>{let n=r;for(let o=0;o{let o=lS(n),s=o,a=0;for(;aSL(t,r)}};function Su(e,t){if(e.length===0)return t;if(t.length===0)return e;let r=e.slice();for(let n=0;nr)}modify(t){return r=>_p(Yt(this.getResult(r),n=>this.replaceResult(t(n),r)),()=>r)}compose(t){return Qo(Su(this.node,t.node))}key(t){return Qo(Su(this.node,[new fS([t])]))}optionalKey(t){return Qo(Su(this.node,Sl(\"Lens\",r=>r[t],(r,n)=>{let o=lS(n);return r===void 0?Array.isArray(o)&&(typeof t==\"number\"||typeof t==\"string\"&&nf(t))?o.splice(Number(t),1):delete o[t]:B(o,t,r),o})))}check(...t){return Qo(Su(this.node,[new Mm(t)]))}refine(t,r){return Qo(Su(this.node,[new Mm([Ly(t,r)])]))}tag(t){let r=q(new fe({expected:`${JSON.stringify(t)} tag`}));return Qo(Su(this.node,Sl(\"Prism\",n=>n._tag===t?j(n):r,D)))}at(t,...r){let n=q(new Ot([t],new Ni(void 0)));return Qo(Su(this.node,Sl(\"Optional\",o=>Object.hasOwn(o,t)?j(o[t]):n,(o,s)=>{if(Object.hasOwn(s,t)){let a=lS(s);return B(a,t,o),j(a)}else return n})))}pick(t){return this.compose(q$(yT(t),(r,n)=>({...ST(n,t),...r})))}omit(t){return this.compose(q$(ST(t),(r,n)=>({...yT(n,t),...r})))}notUndefined(){return this.refine(cs,{expected:\"a value other than `undefined`\"})}forEach(t){let r=t(pS());return MQ(n=>sr(this.getResult(n),o=>{let s=[];for(let a=0;aYt(this.getResult(o),s=>{let a=[];for(let c=0;c_p(Yt(this.getResult(r),n=>this.replaceResult(n.map(t),r)),()=>r)}},wT=class extends bl{get;set;constructor(t,r,n){super(t,o=>j(r(o)),o=>j(n(o))),this.get=r,this.set=n}replace(t,r){return this.set(t)}modify(t){return r=>this.set(t(this.get(r)))}},AT=class extends bl{get;constructor(t,r,n){super(t,o=>j(r(o)),(o,s)=>j(n(o,s))),this.get=r,this.replace=n}modify(t){return r=>this.replace(t(this.get(r)),r)}},CT=class extends bl{set;constructor(t,r,n){super(t,r,(o,s)=>j(n(o))),this.set=n}replace(t,r){return this.set(t)}modify(t){return r=>_p(sr(this.getResult(r),n=>this.set(t(n))),()=>r)}};function Qo(e){let t=e[0]??PQ;if(e.length>1){let r=e.reduce((n,o)=>UQ(n,o.kind),\"Iso\");t={kind:r,get:FQ(e,r),set:NQ(e,r)}}switch(t.kind){case\"Iso\":return new wT(e,t.get,t.set);case\"Lens\":return new AT(e,t.get,t.set);case\"Prism\":return new CT(e,t.get,t.set);case\"Optional\":return new bl(e,t.get,t.set)}}function lS(e){if(Array.isArray(e))return e.slice();if(typeof e==\"object\"&&e!==null){let t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)throw new Error(\"Cannot clone object with non-Object constructor or null prototype\");return{...e}}return e}function FQ(e,t){return r=>{for(let n=0;n{for(let n=e.length-1;n>=0;n--)r=e[n].set(r);return r}:(r,n)=>{let o=e.length,s=new Array(o);for(let a=0;a=0;a--){let i=e[a];if(J$(i.kind))r=i.set(r);else if(i.kind===\"Lens\")r=i.set(r,s[a]);else{let c=i.set(r,s[a]);if(ae(c))return c;r=c.success}}return t===\"Optional\"?j(r):r}}function TT(e){return e===\"Prism\"||e===\"Optional\"}function J$(e){return e===\"Iso\"||e===\"Prism\"}function UQ(e,t){return e===\"Iso\"?t:t===\"Iso\"||e===t?e:\"Optional\"}var DQ=Qo([]);function pS(){return DQ}function Z$(e){let t=rS(e);return G$(Zy(t),Vy(t))}function Y$(e){return pS()}function Q$(e){return pS()}var El=\"~effect/Schema/SchemaError\";function X$(e){return A(e,El)&&e[El]===El}var eK=Kt((e,t)=>{if(e.length!==t.length)return!1;for(let r=0;re.value,es=e=>e,Ra=e=>e.bytes,xo=class extends Ut(\"NetAddressError\"){},Il=e=>A(e,qn),Ir=e=>Il(e)&&e._tag===\"Ipv4Address\",go=e=>Il(e)&&e._tag===\"Ipv6Address\",vT=e=>Ir(e)||go(e),wl=e=>Ir(e)?32:128;var Al=e=>Il(e)&&e._tag===\"MacAddress\",Nm=e=>Il(e)&&e._tag===\"InetAddressV4\",Um=e=>Il(e)&&e._tag===\"InetAddressV6\",kT=e=>Nm(e)||Um(e),dS=e=>Il(e)&&e._tag===\"UnixPathAddress\",rK=e=>kT(e)||dS(e),$Q={...$t,_tag:\"Ipv4Address\",[qn]:qn,[ne](e){return Ir(e)&&Xo(this)===Xo(e)},[re](){return lr(Ee(jQ,Xo(this)|0))},toString(){return wr(this)},toJSON(){return this.toString()}},KQ={...$t,_tag:\"Ipv6Address\",[qn]:qn,[ne](e){if(!go(e))return!1;let t=es(this),r=es(e);return t.w0===r.w0&&t.w1===r.w1&&t.w2===r.w2&&t.w3===r.w3},[re](){let e=es(this),t=Ee(HQ,e.w0|0);return t=Ee(t,e.w1|0),t=Ee(t,e.w2|0),lr(Ee(t,e.w3|0))},toString(){return wr(this)},toJSON(){return this.toString()}},BQ={...$t,_tag:\"MacAddress\",[qn]:qn,[ne](e){return Al(e)&&eK(Ra(this),Ra(e))},[re](){return Ee(zQ,wo(Ra(this)))},toString(){return RT(this)},toJSON(){return this.toString()}},jQ=Pe(\"Ipv4Address\"),HQ=Pe(\"Ipv6Address\"),zQ=Pe(\"MacAddress\"),WQ=e=>{let t=Object.create($Q);return t.value=e>>>0,Object.freeze(t)},qQ=(e,t,r,n)=>{let o=Object.create(KQ);return o.w0=e>>>0,o.w1=t>>>0,o.w2=r>>>0,o.w3=n>>>0,Object.freeze(o)},JQ=(e,t,r,n)=>(e<<24|t<<16|r<<8|n)>>>0;var Fm=e=>[e>>>24,e>>>16&255,e>>>8&255,e&255],GQ=e=>{let t=Object.assign(Object.create(BQ),{bytes:new Uint8Array(e)});return Object.freeze(t)};var bt=(e,t)=>q(new xo({input:e,message:t})),nK=(e,t)=>{for(let r=0;rt)return!1}return!0},VQ=e=>nK(e,255)?j(WQ(JQ(e[0],e[1],e[2],e[3]))):bt(e,\"octets must be integers from 0 through 255\"),ZQ=e=>nK(e,65535)?j(qQ(e[0]*65536+e[1],e[2]*65536+e[3],e[4]*65536+e[5],e[6]*65536+e[7])):bt(e,\"segments must be integers from 0 through 65535\");var oK=e=>/^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/.test(e)?j(GQ(new Uint8Array(e.split(\":\").map(t=>Number.parseInt(t,16))))):bt(e,\"expected six two-digit hexadecimal octets separated by colons\");var bu=e=>{let t=e.split(\".\");if(t.length!==4||t.some(n=>!/^\\d{1,3}$/.test(n)))return bt(e,\"expected exactly four decimal octets\");if(t.some(n=>n.length>1&&n[0]===\"0\"))return bt(e,\"leading zeroes are not allowed\");let r=t.map(Number);return r.some(n=>n>255)?bt(e,\"octets must be at most 255\"):VQ([r[0],r[1],r[2],r[3]])},YQ=e=>{if(e.includes(\"[\")||e.includes(\"]\")||e.includes(\"%\"))return bt(e,\"brackets and zone identifiers are not valid in a bare IPv6 address\");let t=e.split(\"::\");if(t.length>2)return bt(e,\"only one compression marker is allowed\");let r=t[0]===\"\"?[]:t[0].split(\":\"),n=t.length===2&&t[1]!==\"\"?t[1].split(\":\"):[];if(r.some(f=>f===\"\")||n.some(f=>f===\"\"))return bt(e,\"empty segments are only valid in the compression marker\");let o=n.length>0?n[n.length-1]:r.length>0?r[r.length-1]:\"\",s;if(o.includes(\".\")){if(t.length===2&&n.length===0)return bt(e,\"embedded IPv4 syntax must be trailing\");let f=sr(bu(o),p=>{let d=Xo(p);return[d>>>16,d&65535]});if(ae(f))return f;s=f.success,n.length>0?n.pop():r.pop()}let a=r.length+n.length+(s?2:0);if(t.length===1?a!==8:a>=8)return bt(e,t.length===1?\"expected eight segments\":\"compression must replace at least one segment\");let i=f=>/^[0-9a-fA-F]{1,4}$/.test(f)?Number.parseInt(f,16):void 0,c=r.map(i),u=n.map(i);return c.some(f=>f===void 0)||u.some(f=>f===void 0)?bt(e,\"segments must contain one through four hexadecimal digits\"):j([...c,...Array(8-a).fill(0),...u,...s??[]])},Eu=e=>Yt(YQ(e),t=>ZQ(t)),$i=e=>e.includes(\":\")?Eu(e):bu(e);var OT=e=>{if(typeof e!=\"string\"||!e.includes(\"%\"))return!1;let t=Dm(e);return rt(t)&&t.success===e},Dm=e=>{let t=e.indexOf(\"%\");if(t===-1)return bt(e,\"expected an IPv6 zone\");let r=e.slice(t+1);if(r.length===0||/[%[\\]/\\s\\p{Cc}]/u.test(r))return bt(e,\"invalid IPv6 scope identifier\");if(/^\\d+$/.test(r)){let n=Number(r);if(n>4294967295)return bt(e,\"scope identifier must be an unsigned 32-bit integer\");r=String(n)}return sr(Eu(e.slice(0,t)),n=>`${wr(n)}%${r}`)};var mS=e=>Fm(Xo(e)),QQ=e=>{let{w0:t,w1:r,w2:n,w3:o}=es(e);return[t>>>16,t&65535,r>>>16,r&65535,n>>>16,n&65535,o>>>16,o&65535]},_T=e=>{let{w0:t,w1:r,w2:n,w3:o}=es(e);return[...Fm(t),...Fm(r),...Fm(n),...Fm(o)]};var RT=e=>Array.from(Ra(e),t=>t.toString(16).padStart(2,\"0\")).join(\":\"),hS=e=>Ra(e).every(t=>t===255),XQ=e=>(Ra(e)[0]&1)!==0,xS=e=>(Ra(e)[0]&1)===0,PT=e=>(Ra(e)[0]&2)!==0,MT=e=>(Ra(e)[0]&2)===0;var wr=e=>{if(Ir(e))return mS(e).join(\".\");let t=QQ(e);if(eX(e))return`::ffff:${t[6]>>8}.${t[6]&255}.${t[7]>>8}.${t[7]&255}`;let r=-1,n=0,o=-1;for(let i=0;i<=8;i++)i<8&&t[i]===0?o===-1&&(o=i):o!==-1&&(i-o>n&&(r=o,n=i-o),o=-1);if(n<2)return t.map(i=>i.toString(16)).join(\":\");let s=t.slice(0,r).map(i=>i.toString(16)).join(\":\"),a=t.slice(r+n).map(i=>i.toString(16)).join(\":\");return`${s}::${a}`},gS=e=>{if(Ir(e))return Xo(e)===0;let{w0:t,w1:r,w2:n,w3:o}=es(e);return t===0&&r===0&&n===0&&o===0},FT=e=>{if(Ir(e))return Xo(e)>>>24===127;let{w0:t,w1:r,w2:n,w3:o}=es(e);return t===0&&r===0&&n===0&&o===1},Cl=e=>Al(e)?XQ(e):Ir(e)?Xo(e)>>>28===14:es(e).w0>>>24===255,yS=e=>Al(e)?hS(e):Xo(e)===4294967295,NT=e=>Al(e)?xS(e):!Cl(e)&&!gS(e)&&(!Ir(e)||!yS(e)),UT=e=>Ir(e)?Xo(e)>>>16===43518:(es(e).w0>>>16&65472)===65152,DT=e=>{let t=Xo(e);return t>>>24===10||(t>>>16&65520)===44048||t>>>16===49320},LT=e=>(es(e).w0>>>24&254)===252,eX=e=>{let{w0:t,w1:r,w2:n}=es(e);return t===0&&r===0&&n===65535};var tX={...$t,_tag:\"InetAddressV4\",[qn]:qn,[ne](e){return Nm(e)&&this.port===e.port&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.port))},toString(){return SS(this)},toJSON(){return this.toString()}},rX={...$t,_tag:\"InetAddressV6\",[qn]:qn,[ne](e){return Um(e)&&this.port===e.port&&this.scopeId===e.scopeId&&Z(this.address,e.address)},[re](){return Ee(Ee(V(this.address),Lt(this.port)),Lt(this.scopeId))},toString(){return SS(this)},toJSON(){return this.toString()}},sK=e=>Number.isInteger(e)&&e>=0&&e<=65535,nX=(e,t)=>{if(!sK(t))return bt(e,\"port must be an integer from 0 through 65535\");let r=Object.create(tX);return r.address=e,r.port=t,j(Object.freeze(r))},oX=(e,t,r)=>{if(!sK(t))return bt(e,\"port must be an integer from 0 through 65535\");let n=r?.scopeId??0;if(!Number.isInteger(n)||n<0||n>4294967295)return bt(e,\"scopeId must be an unsigned 32-bit integer\");let o=Object.create(rX);return o.address=e,o.port=t,o.scopeId=n,j(Object.freeze(o))};var $T=e=>{let t,r,n=0,o=e.startsWith(\"[\");if(o){let s=e.indexOf(\"]\");if(s<0||e[s+1]!==\":\"||e.indexOf(\"]\",s+1)!==-1)return bt(e,\"expected [IPv6]:port\");t=e.slice(1,s),r=e.slice(s+2);let a=t.indexOf(\"%\");if(a!==-1){let i=t.slice(a+1);if(t.indexOf(\"%\",a+1)!==-1||!/^\\d+$/.test(i))return bt(e,\"scope identifier must be decimal\");if(n=Number(i),!Number.isInteger(n)||n>4294967295)return bt(e,\"scope identifier must be an unsigned 32-bit integer\");t=t.slice(0,a)}}else{let s=e.lastIndexOf(\":\");if(s<0)return bt(e,\"expected host:port or [IPv6]:port\");if(e.indexOf(\":\")!==s)return bt(e,\"IPv6 addresses must be bracketed\");t=e.slice(0,s),r=e.slice(s+1)}return/^(0|[1-9]\\d*)$/.test(r)?Yt($i(t),s=>o!==go(s)?bt(e,\"only IPv6 addresses use brackets\"):go(s)?oX(s,Number(r),{scopeId:n}):nX(s,Number(r))):bt(e,\"port must be an unpadded decimal integer\")};var sX=e=>wr(e.address)+(Um(e)&&e.scopeId!==0?`%${e.scopeId}`:\"\");var SS=e=>{let t=sX(e);return Nm(e)?`${t}:${e.port}`:`[${t}]:${e.port}`};var aX={...$t,_tag:\"UnixPathAddress\",[qn]:qn,[ne](e){return dS(e)&&this.path===e.path},[re](){return Ee(Pe(\"UnixPathAddress\"),Pe(this.path))},toString(){return this.path},toJSON(){return this.toString()}},aK=e=>{let t=Object.create(aX);return t.path=e,Object.freeze(t)};var KT=\"~effect/net/Host\",Ki=(e,t)=>q(new xo({input:e,message:t})),iK=/^[a-z0-9_.-]*$/i,iX=/[\\u0080-\\uffff]/g,cX=/^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/,uX=/^(?:\\d+|0x[0-9a-f]*)$/,cK=e=>{if(e===\".\")return;let t=e.endsWith(\".\")?e.slice(0,-1):e;if(t.length===0)return\"domain name must not be empty\";if(t.length>253)return\"domain name must be at most 253 characters\";let r=t.split(\".\");for(let n of r){if(n.length===0)return\"domain name labels must not be empty\";if(n.length>63)return\"domain name labels must be at most 63 characters\";if(!cX.test(n))return\"domain name labels must contain only letters, digits, hyphens, or underscores and must not start or end with a hyphen\"}if(uX.test(r[r.length-1]))return\"the last domain name label must not be numeric\"},fX=e=>{if(iK.test(e))return e.toLowerCase();if(iK.test(e.normalize(\"NFC\").replace(iX,\"\")))try{return new URL(`http://${e}`).hostname}catch{return}},Pa=e=>typeof e==\"string\"&&/^[a-z0-9_.-]+$/.test(e)&&cK(e)===void 0;var jT=e=>A(e,KT),bS=e=>{let t=fX(e);if(t===void 0)return Ki(e,\"invalid domain name\");let r=cK(t);return r===void 0?j(t):Ki(e,r)};var lX=e=>{if(e.includes(\"%\"))return Dm(e);if(e.includes(\":\"))return $i(e);if(/^[\\d.]+$/.test(e)){let t=$i(e);if(rt(t))return t}return bS(e)};var pX=e=>typeof e==\"string\"?e:wr(e);var dX={...$t,_tag:\"HostPort\",[KT]:KT,[ne](e){return jT(e)&&this.port===e.port&&Z(this.host,e.host)},[re](){return Ee(V(this.host),Lt(this.port))},toString(){return HT(this)},toJSON(){return this.toString()}},mX=e=>Number.isInteger(e)&&e>=0&&e<=65535,hX=(e,t)=>{let r=Object.create(dX);return r.host=e,r.port=t,Object.freeze(r)};var uK=e=>{let t,r;if(e.startsWith(\"[\")){let o=e.indexOf(\"]\");if(o===-1||e[o+1]!==\":\")return Ki(e,\"expected [IPv6]:port\");if(t=e.slice(1,o),r=e.slice(o+2),!t.includes(\":\"))return Ki(e,\"only IPv6 addresses use brackets\")}else{let o=e.lastIndexOf(\":\");if(o===-1)return Ki(e,\"expected host:port\");if(e.indexOf(\":\")!==o)return Ki(e,\"IPv6 addresses must be bracketed\");t=e.slice(0,o),r=e.slice(o+1)}if(!/^(0|[1-9]\\d*)$/.test(r))return Ki(e,\"port must be an unpadded decimal integer\");let n=Number(r);return mX(n)?sr(lX(t),o=>hX(o,n)):Ki(e,\"port must be an integer from 0 through 65535\")};var HT=e=>{let t=pX(e.host);return t.includes(\":\")?`[${t}]:${e.port}`:`${t}:${e.port}`};var WT=\"~effect/net/Dns/DnsRecord\",zT=e=>Number.isInteger(e)&&e>=0&&e<=255,Tl=e=>Number.isInteger(e)&&e>=0&&e<=65535,pK=e=>Number.isInteger(e)&&e>=0&&e<=4294967295,Bi=e=>typeof e==\"string\",ES=e=>Fp(e)&&sn(e)&&pK(hs(e)),dK={A:{address:Ir},AAAA:{address:go},CAA:{critical:e=>typeof e==\"boolean\",tag:e=>Bi(e)&&/^[a-z0-9]+$/i.test(e),value:Bi},CNAME:{target:Pa},MX:{exchange:Pa,priority:Tl},NAPTR:{order:Tl,preference:Tl,flags:Bi,service:Bi,regexp:Bi,replacement:Pa},NS:{host:Pa},PTR:{host:e=>Bi(e)&&e.length>0},SOA:{primary:Pa,admin:e=>Bi(e)&&e.length>0,serial:pK,refresh:ES,retry:ES,expire:ES,minimum:ES},SRV:{target:Pa,port:Tl,priority:Tl,weight:Tl},TLSA:{certUsage:zT,selector:zT,matchingType:zT,data:e=>e instanceof Uint8Array&&e.length>0},TXT:{chunks:e=>Array.isArray(e)&&e.length>0&&e.every(Bi)}},qT=Object.keys(dK),xX=e=>qT.includes(e),JT=e=>A(e,WT),gX={...$t,[WT]:WT,[ne](e){return JT(e)&&e._tag===this._tag&&Object.keys(this).every(t=>Z(this[t],e[t]))},[re](){return dp(this,Object.keys(this))},toString(){return SX(this)},toJSON(){return{...this}}},mK=(e,t)=>{if(!xX(e))return q(new xo({input:e,message:\"unknown DNS record type\"}));let r=typeof t==\"object\"&&t!==null?t:{},n=Object.create(gX);n._tag=e;for(let[o,s]of Object.entries(dK[e])){let a=r[o];if(!s(a))return q(new xo({input:t,message:`invalid ${e} record ${o}`}));n[o]=Array.isArray(a)?Object.freeze([...a]):a instanceof Uint8Array?new Uint8Array(a):a}return j(Object.freeze(n))};var hK=new TextEncoder,xK=e=>`\\\\${e.toString().padStart(3,\"0\")}`,$m=e=>{let t='\"';for(let r of hK.encode(e))t+=r===34||r===92?`\\\\${String.fromCharCode(r)}`:r<32||r>126?xK(r):String.fromCharCode(r);return t+'\"'},yX=[34,36,40,41,59,64],lK=e=>{let t=hK.encode(e),r=\"\";for(let n=0;n126?r+=xK(o):r+=yX.includes(o)?`\\\\${String.fromCharCode(o)}`:String.fromCharCode(o)}return r},SX=e=>{switch(e._tag){case\"A\":case\"AAAA\":return`${e._tag} ${wr(e.address)}`;case\"CAA\":return`CAA ${e.critical?128:0} ${e.tag} ${$m(e.value)}`;case\"CNAME\":return`CNAME ${e.target}`;case\"MX\":return`MX ${e.priority} ${e.exchange}`;case\"NAPTR\":return`NAPTR ${e.order} ${e.preference} ${$m(e.flags)} ${$m(e.service)} ${$m(e.regexp)} ${e.replacement}`;case\"NS\":return`NS ${e.host}`;case\"PTR\":return`PTR ${lK(e.host)}`;case\"SOA\":return`SOA ${e.primary} ${lK(e.admin)} ${e.serial} ${hs(e.refresh)} ${hs(e.retry)} ${hs(e.expire)} ${hs(e.minimum)}`;case\"SRV\":return`SRV ${e.priority} ${e.weight} ${e.port} ${e.target}`;case\"TLSA\":return`TLSA ${e.certUsage} ${e.selector} ${e.matchingType} ${gx(e.data).toUpperCase()}`;case\"TXT\":return`TXT ${e.chunks.map($m).join(\" \")}`}};var GT=\"~effect/net/IpInterface\",gK=e=>Km(e)&&Ir(e.address),yK=e=>Km(e)&&go(e.address),Km=e=>A(e,GT),wX={...$t,_tag:\"IpInterface\",[GT]:GT,[ne](e){return Km(e)&&this.prefixLength===e.prefixLength&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.prefixLength))},toString(){return jm(this)},toJSON(){return this.toString()}},VT=(e,t)=>q(new xo({input:e,message:t})),Bm=(e,t)=>{let r=wl(e);if(!Number.isInteger(t)||t<0||t>r)return VT(e,`prefix length must be an integer from 0 through ${r}`);let n=Object.assign(Object.create(wX),{address:e,prefixLength:t});return j(Object.freeze(n))},ZT=(e,t)=>{let r=e.indexOf(\"/\");if(r===-1&&t?.prefix!==\"required\")return j({address:e,prefixLength:void 0});if(r<=0||r!==e.lastIndexOf(\"/\")||r===e.length-1)return VT(e,\"expected an address and prefix length separated by one slash\");let n=e.slice(r+1);return/^(0|[1-9][0-9]*)$/.test(n)?j({address:e.slice(0,r),prefixLength:Number(n)}):VT(e,\"prefix length must be an unpadded ASCII decimal integer\")},IS=(e,t)=>Yt(ZT(e,t),r=>Yt(bu(r.address),n=>Bm(n,r.prefixLength??wl(n)))),wS=(e,t)=>Yt(ZT(e,t),r=>Yt(Eu(r.address),n=>Bm(n,r.prefixLength??wl(n)))),AS=(e,t)=>Yt(ZT(e,t),r=>Yt($i(r.address),n=>Bm(n,r.prefixLength??wl(n))));var jm=e=>`${wr(e.address)}/${e.prefixLength}`;var YT=\"~effect/net/IpNetwork\",bK=e=>Hm(e)&&Ir(e.address),EK=e=>Hm(e)&&go(e.address),Hm=e=>A(e,YT),AX={...$t,_tag:\"IpNetwork\",[YT]:YT,[ne](e){return Hm(e)&&this.prefixLength===e.prefixLength&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.prefixLength))},toString(){return zm(this)},toJSON(){return this.toString()}},CX=e=>{let t=Object.assign(Object.create(AX),{address:e.address,prefixLength:e.prefixLength});return Object.freeze(t)},TX=e=>Ir(e)?mS(e):_T(e);var vX=(e,t)=>{let r=Math.floor(t/8),n=t%8;return e.map((o,s)=>sYt(Bm(e,t),r=>{let n=TX(e),o=vX(n,t);return n.some((s,a)=>s!==o[a])?q(new xo({input:e,message:\"address has non-zero host bits\"})):j(CX(r))});var IK=e=>Yt(IS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength)),wK=e=>Yt(wS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength)),AK=e=>Yt(AS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength));var zm=e=>`${wr(e.address)}/${e.prefixLength}`;var XT=\"~effect/SemVer\",ev=\"~effect/SemVer/SemVerError\",CS=class extends Ut(\"SemVerError\"){[ev]=ev},OX=e=>A(e,ev),yo=e=>{throw new CS({message:e})},_X=e=>lE({try:e,catch:t=>{if(!OX(t))throw t;return t}}),tv=(e,t,r)=>rf(_X(()=>r(t)),n=>new CS({message:`Invalid ${e} ${JSON.stringify(t)}: ${n.message}`,input:t})),RX=/^(?:0|[1-9]\\d*)$/,PX=/^\\d+$/,TK=/^[0-9A-Za-z-]+$/,Wm=(e,t)=>!Number.isSafeInteger(e)||e<0?yo(`${t} must be a non-negative safe integer, received ${e}`):e,vl=(e,t)=>RX.test(e)?Wm(Number(e),t):yo(`${t} must be a non-negative integer without leading zeros, received ${JSON.stringify(e)}`),TS=e=>typeof e==\"number\"?Wm(e,\"numeric pre-release identifier\"):TK.test(e)?PX.test(e)?vl(e,\"numeric pre-release identifier\"):e:yo(`pre-release identifier must be non-empty [0-9A-Za-z-], received ${JSON.stringify(e)}`),vK=e=>TK.test(e)?e:yo(`build identifier must be non-empty [0-9A-Za-z-], received ${JSON.stringify(e)}`);var MX={[XT]:XT,[ne](e){return rv(e)&&NX(this,e)},[re](){return Pe(Iu(this))},toString(){return`SemVer(${Iu(this)})`},toJSON(){return{_id:\"SemVer\",value:Iu(this)}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},kK=(e,t,r,n,o)=>{let s=Object.create(MX);return s.major=e,s.minor=t,s.patch=r,s.prerelease=n,s.build=o,s};var rv=e=>A(e,XT),nv=e=>kK(Wm(e.major,\"major\"),Wm(e.minor,\"minor\"),Wm(e.patch,\"patch\"),e.prerelease?.map(TS)??[],e.build?.map(vK)??[]),FX=e=>{let t=e,r=[],n=t.indexOf(\"+\");n!==-1&&(r=t.slice(n+1).split(\".\").map(vK),t=t.slice(0,n));let o=[],s=t.indexOf(\"-\");s!==-1&&(o=t.slice(s+1).split(\".\").map(TS),t=t.slice(0,s));let a=t.split(\".\");return a.length!==3?yo(\"expected MAJOR.MINOR.PATCH\"):kK(vl(a[0],\"major\"),vl(a[1],\"minor\"),vl(a[2],\"patch\"),o,r)},OK=e=>tv(\"SemVer\",e,FX);var Iu=e=>{let t=`${e.major}.${e.minor}.${e.patch}`;return e.prerelease.length>0&&(t+=`-${e.prerelease.join(\".\")}`),e.build.length>0&&(t+=`+${e.build.join(\".\")}`),t};var CK=Vu(Wa()),NX=Kt((e,t)=>e.major===t.major&&e.minor===t.minor&&e.patch===t.patch&&CK(e.prerelease,t.prerelease)&&CK(e.build,t.build));var av=\"~effect/SemVerRange\",UX={[av]:av,[ne](e){return iv(e)&&ji(this)===ji(e)},[re](){return Pe(ji(this))},toString(){return`SemVerRange(${ji(this)})`},toJSON(){return{_id:\"SemVerRange\",value:ji(this)}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},iv=e=>A(e,av);var DX={components:[],prerelease:[]},LX=/^(<=|>=|<|>|=|~|\\^)?(.*)$/,$X=e=>e===\"x\"||e===\"X\"||e===\"*\",KX=[\"major\",\"minor\",\"patch\"],ov=e=>{if(e.length===0)return yo(\"expected a version after the operator\");if(e.includes(\"+\"))return yo(`build metadata is not allowed in ranges, received ${JSON.stringify(e)}`);let t=e.indexOf(\"-\"),r=(t===-1?e:e.slice(0,t)).split(\".\");if(r.length>3)return yo(`expected at most MAJOR.MINOR.PATCH, received ${JSON.stringify(e)}`);let n=[];for(let o=0;o{let t=e.split(/\\s+/).filter(n=>n.length>0);if(t.length===0)return yo(\"expected a comparator\");if(t.length===3&&t[1]===\"-\")return[{_tag:\"Hyphen\",from:ov(t[0]),to:ov(t[2])}];let r=[];for(let n=0;n{let t=Object.create(UX);return t.sets=e,t},jX=e=>e.trim().length===0?HX:RK(e.split(\"||\").map(BX)),cv=e=>tv(\"SemVer range\",e,jX),PK=e=>ms(cv(e));var HX=RK([[{_tag:\"Comparator\",operator:\"=\",version:DX}]]);var sv=e=>{if(e.components.length===0)return\"*\";let t=e.components.join(\".\");return e.prerelease.length===0?t:`${t}-${e.prerelease.join(\".\")}`},zX=e=>e._tag===\"Hyphen\"?`${sv(e.from)} - ${sv(e.to)}`:`${e.operator===\"=\"?\"\":e.operator}${sv(e.version)}`,ji=e=>e.sets.map(t=>t.map(zX).join(\" \")).join(\" || \");var qm=Qy;function yn(){return(e,t,r)=>Q(new fl(e.map(Em),n=>t(n.map(o=>Q(o))),r))}function je(e,t){return yn()([],()=>(r,n,o)=>e(r)?g(r):F(new _t(n,r,o)),t)}function WX(e){return e}function qX(e){return t=>t.annotate(e)}function JX(e){return t=>fv(fv(t).annotate(e))}function GX(e){return t=>t.rebuild(Tm(t.ast,e))}function VX(e){return e}var Ma=class extends Ut(\"SchemaError\"){[El]=El;constructor(t){let r=Co();pr(0);try{super({issue:t})}finally{pr(r)}}get message(){return U2(this.issue)}toJSON(){return{_tag:this._tag,message:this.message}}[Je](){return this.toJSON()}toString(){return`SchemaError(${this.message})`}};function JK(e){return X$(e)}function GK(e){return Ve(e)?hv(e):nt(e,t=>da(()=>fa(t,r=>new Ma(r))))}function hv(e){return ut(e)?e:Fn(fa(e.cause,t=>new Ma(t)))}function VK(e,t){let r;for(let n of e.reasons){if(!ai(n)||!JK(n.error))throw new globalThis.Error(t,{cause:e});r??=n.error}if(r===void 0)throw new globalThis.Error(t,{cause:e});return r}function ZK(e){return kg(e).then(t=>{if(ut(t))return t.value;throw VK(t.cause,\"Promise adapter can only reject schema errors\")})}function YK(e){let t=Ts(e);if(ut(t))return t.value;throw VK(t.cause,\"Sync adapter can only throw schema errors\")}function ZX(e,t){return O$(e,t)}function YX(e){return R$(e)}var QX=km,XX=RL;function OS(e,t){let r=St(e,t);return(n,o)=>GK(r(n,o))}var eee=OS;function QK(e,t){let r=PL(e,t);return(n,o)=>hv(r(n,o))}var tee=QK,ree=YC,nee=ML;function XK(e,t){let r=FL(e,t);return(n,o)=>rf(r(n,o),s=>new Ma(s))}var oee=XK;function eB(e,t){let r=OS(e,t);return(n,o)=>ZK(r(n,o))}var see=eB;function tB(e,t){let r=OS(e,t);return(n,o)=>YK(r(n,o))}var aee=tB;function _S(e,t){let r=hu(e,t);return(n,o)=>GK(r(n,o))}var iee=_S;function rB(e,t){let r=UL(e,t);return(n,o)=>hv(r(n,o))}var cee=rB,uee=QC,fee=DL;function nB(e,t){let r=LL(e,t);return(n,o)=>rf(r(n,o),s=>new Ma(s))}var lee=nB;function oB(e,t){let r=_S(e,t);return(n,o)=>ZK(r(n,o))}var pee=oB;function sB(e,t){let r=_S(e,t);return(n,o)=>YK(r(n,o))}var dee=sB,Q=Wn;function RS(e){return A(e,qm)&&e[qm]===qm}var rs=Kr(e=>Q(mu(e.ast),{schema:e})),mee=Kr(e=>e.schema),Pl=Kr(e=>{let t=NS(e);return Q(lL(e.ast),{schema:t})}),hee=Kr(e=>e.schema.members[0]),xee=Kr(e=>Q(UC(e.ast),{schema:e})),gee=Kr(e=>e.schema),Sn=Kr(e=>Q(Mt(e.ast),{schema:e})),Ml=Kr(e=>Q(gn(e.ast),{schema:e})),Jm=\"~effect/Schema/flip\";function yee(e){return A(e,Jm)&&e[Jm]===Jm}function fv(e){return yee(e)?e.schema.rebuild(Bn(e.ast)):Q(Bn(e.ast),{[Jm]:Jm,schema:e})}function zt(e){let t=Q(new Kn(e),{literal:e,transform(r){return t.pipe(J(zt(r),{decode:le(()=>r),encode:le(()=>e)}))}});return t}function aB(e){return e.map(t=>RS(t)?t.ast:new Kn(t))}function See(e){return Q(new IC(aB(e)),{parts:e})}function bee(e){return Q(qD(aB(e)),{parts:e})}function Eee(e){return Q(new WD(Object.keys(e).filter(t=>typeof e[e[t]]!=\"number\").map(t=>[t,e[t]])),{enums:e})}var iB=Q(ll),Iee=Q(HD),Fl=Q(Jo),PS=Q(ym),xv=Q(EC),H=Q(xn),wee=H,wu=Q(wC),Gm=Q(VD),cB=Q(ZD),Nl=Q(YD),Aee=Q(jD),Cee=Q(zD);function Tee(e){return Q(new GD(e))}function gv(e,t){return Q(e,{fields:t,mapFields(r,n){let o=r(this.fields);return gv(Ny(o,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function ve(e){return gv(Ny(e,void 0),e)}function vee(e){return Kr(t=>t.mapFields(z$(e)))}var kee=e=>typeof e==\"symbol\"?e:globalThis.String(e);function Oee(e){return function(t){let r={},n=Object.create(null),o=Object.create(null),s=new Set;for(let a of Reflect.ownKeys(t.fields)){let i=Ml(t.fields[a]),c=Object.hasOwn(e,a),u=c?e[a]:a,f=kee(u);if(s.has(f))throw new globalThis.Error(`Duplicate encoded keys: ${us(u)}`);s.add(f),B(r,u,i),c&&(n[a]=u,o[u]=a)}return ve(r).pipe(J(t,Ge({decode:bT(o),encode:bT(n)})))}}function _ee(e,t){return r=>{let n=gc(r.fields,Sn),o=ve({...n,...e});return r.pipe(J(o,Ge({decode:s=>{let a={...s};for(let i in e){let c=t[i],u=c(s);Ce(u)&&B(a,i,u.value)}return a},encode:s=>{let a={...s};for(let i in e)delete a[i];return a}})))}}function Na(e,t){return Q($y(e.ast,t.ast),{key:e,value:t})}function Ree(e,t){return Q(rL(e.ast,t.map(Em)),{schema:e,records:t})}function uB(e,t){return Q(e,{elements:t,mapElements(r,n){let o=r(this.elements);return uB(vC(o,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function Ds(e){return uB(vC(e),e)}function Pee(e,t){return Q(nL(e.ast,t.map(Em)),{schema:e,rest:t})}var Be=Kr(e=>Q(new jn(!1,[],[e.ast]),{value:e}));function MS(e,t,r){return t!==void 0&&r!==void 0?e.check(Av(t,r)):t!==void 0?e.check(wv(t)):r!==void 0?e.check(_B(r)):e}var FS=Kr(e=>Q(new jn(!1,[e.ast],[e.ast]),{value:e}));function Mee(e){let t=Be(e),r=Be(Sn(e)),n=J(Ds([Fl]),Ge({decode:o=>[o],encode:([o])=>o}))(e);return Q(st([n,t]).pipe(J(r)).ast,{from:st([e,t]),to:r})}function Fee(e){return Be(e).check(Tv())}var Nee=Kr(e=>Q(oL(e.ast),{schema:e}));function fB(e,t){return Q(e,{members:t,mapMembers(r,n){let o=r(this.members);return fB(Uy(o,this.ast.options,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function st(e,t){return fB(Uy(e,t,void 0),e)}function Jn(e){let t=e.map(zt);return Q(Uy(t,void 0,void 0),{literals:e,members:t,mapMembers(r){return st(r(this.members))},pick(r){return Jn(r)},transform(r){return st(t.map((n,o)=>n.transform(r[o])))}})}var yv=Kr(e=>st([e,PS])),NS=Kr(e=>st([e,xv])),lB=Kr(e=>st([e,PS,xv]));function pB(e){return Q(new OC(()=>e().ast))}function Uee(...e){return t=>t.check(...e)}function dB(e,t){return r=>Q(Us(r.ast,[Ly(e,t)]),{schema:r})}function US(e){return t=>Q(t.ast,{schema:t,identifier:e})}function Dee(e,t){return r=>(t.checks?r.check(...t.checks):r).pipe(US(e))}function mB(e){return t=>Q(uL(t.ast,new Ty(e,D)),{schema:t})}function hB(e){return t=>Q(fL(t.ast,new Ty(D,e)),{schema:t})}function Lee(e){return xB(e)}function xB(e){return t=>mB($f(e))(t)}function $ee(e){return gB(e)}function gB(e){return t=>hB($f(e))(t)}function J(e,t){return r=>Q(Oa(r.ast,e.ast,t?vy(t):nl()),{from:r,to:e})}function Hi(){return(e,t)=>ke()(e,{decode:t,encode:$2})}var yB=Jn([\"true\",\"yes\",\"on\",\"1\",\"y\"]),SB=Jn([\"false\",\"no\",\"off\",\"0\",\"n\"]),Sv=Jn([...yB.literals,...SB.literals]).pipe(J(Gm,Ge({decode:e=>e===\"true\"||e===\"yes\"||e===\"on\"||e===\"1\"||e===\"y\",encode:e=>e?\"true\":\"false\"})));function Kee(e){return t=>J(Sn(t),e)(t)}function bv(e,t){return r=>t?J(r,t)(e):J(r)(e)}function Bee(e){return t=>J(t,e)(Ml(t))}function bB(e){return t=>Q(pL(t.ast,e),{schema:t})}function EB(e){return Ve(e)&&e._tag===\"Success\"?e:nt(e,t=>da(()=>fa(t,r=>r.issue)))}function Ev(e,t){let r=t?.encodingStrategy===\"omit\"?nC():hn();return n=>rs(Ml(n)).pipe(J(n,{decode:oC(EB(e)),encode:r}))}function jee(e,t){return r=>Sn(r).pipe(Ev(e,t),bv(rs(r)))}function IB(e,t){let r=t?.encodingStrategy===\"omit\"?nC():hn();return n=>Pl(Ml(n)).pipe(J(n,{decode:oC(EB(e)),encode:r}))}function Hee(e,t){return r=>Sn(r).pipe(IB(e,t),bv(Pl(r)))}function Fa(e){return zt(e).pipe(bB(g(e)))}function zee(e){return Fa(e).pipe(Ev(g(e),{encodingStrategy:\"omit\"}))}function Vm(e,t){return ve({_tag:Fa(e),...t})}function wB(e){return t=>{let r={},n=[],o=new Set,s={},a=f=>p=>f.includes(p[e]);return i(t),Object.assign(t,{tag:e,cases:r,discriminants:n,isAnyOf:a,guards:s,match:c,matchOrElse:u});function i(f){let p=f.ast;if(Fy(p)&&\"members\"in f&&globalThis.Array.isArray(f.members)&&f.members.every(RS))return f.members.forEach(i);let d=il(p);if(d.length>0){let m=d.find(h=>h.key===e)?.literal;if(vh(m)){let h=typeof m==\"number\"?globalThis.String(m):m;if(o.has(h))throw new globalThis.Error(`Duplicate discriminant: ${globalThis.String(m)}`);o.add(h),n.push(m),B(r,m,f),B(s,m,km(Sn(f)));return}}throw new globalThis.Error(\"No literal or unique symbol found\")}function c(){if(arguments.length===1){let h=arguments[0];return function(y){let S=y[e];return(Object.hasOwn(h,S)?h[S]:void 0)(y)}}let f=arguments[0],p=arguments[1],d=f[e];return(Object.hasOwn(p,d)?p[d]:void 0)(f)}function u(){if(arguments.length===2){let y=arguments[0],S=arguments[1];return function(b){let x=b[e];return(Object.hasOwn(y,x)?y[x]??S:S)(b)}}let f=arguments[0],p=arguments[1],d=arguments[2],m=f[e];return(Object.hasOwn(p,m)?p[m]??d:d)(f)}}}function Wee(e){let t={},r=[];for(let u of Object.keys(e)){let f=Vm(u,e[u]);B(t,u,f),r.push(f)}let n=st(r),{tag:o,guards:s,isAnyOf:a,match:i,matchOrElse:c}=wB(\"_tag\")(n);return Q(n.ast,{tag:o,cases:t,isAnyOf:a,guards:s,match:i,matchOrElse:c})}function qee(){return e=>e}function Au(e,t){return je(r=>r instanceof e,t)}function ke(){return(e,t)=>new Tt(e.ast,vy(t))}var Ne=Dy;function Jee(e,t=void 0){return new fu(e,t)}var FK=\"^\\\\S[\\\\s\\\\S]*\\\\S$|^\\\\S$|^$\";function AB(e){let t=new globalThis.RegExp(FK);return Ne(r=>r.trim()===r,{expected:\"a string with no leading or trailing whitespace\",representation:{id:\"effect/schema/isTrimmed\",payload:null},toJsonSchema:()=>({pattern:t.source}),toCode:()=>({runtime:\"Schema.isTrimmed()\"}),arbitraryConstraint:{patterns:[{source:FK,flags:\"\"}]},...e})}function zi(e,t){let r=e.source,n=e.flags,o=/^[dg]*uy?$/.test(n),s=n===\"\"?`new globalThis.RegExp(${K(r)})`:`new globalThis.RegExp(${K(r)}, ${K(n)})`;return wm(e,{toJsonSchema:()=>o?{pattern:n.endsWith(\"y\")?`^(?:${r})`:r}:[{},!0],toCode:()=>({runtime:`Schema.isPattern(${s})`}),...t})}function Gee(e){return $C({toCode:()=>({runtime:\"Schema.isStringFinite()\"}),...e})}function Vee(e){return KC({toCode:()=>({runtime:\"Schema.isStringBigInt()\"}),...e})}function Zee(e){return jC({toCode:()=>({runtime:\"Schema.isStringSymbol()\"}),...e})}var Yee=e=>e?new globalThis.RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$/;function Qee(e,t){let r=Yee(e);return zi(r,{expected:e?`a UUID v${e}`:\"a UUID\",representation:{id:\"effect/schema/isUUID\",payload:{version:e??null}},toJsonSchema:()=>({pattern:r.source,format:\"uuid\"}),toCode:()=>({runtime:e===void 0?\"Schema.isUUID()\":`Schema.isUUID(${e})`}),...t})}var Xee=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/u;function ete(e){return zi(Xee,{expected:\"a GUID\",representation:{id:\"effect/schema/isGUID\",payload:null},toCode:()=>({runtime:\"Schema.isGUID()\"}),...e})}var tte=/^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/u;function rte(e){return zi(tte,{representation:{id:\"effect/schema/isULID\",payload:null},toCode:()=>({runtime:\"Schema.isULID()\"}),...e})}var nte=/^[\\x00-\\x7F]*$/u;function ote(e){return zi(nte,{expected:\"an ASCII string\",representation:{id:\"effect/schema/isAscii\",payload:null},toCode:()=>({runtime:\"Schema.isAscii()\"}),...e})}function CB(e){let t=\"^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$\",r=/^[0-9a-zA-Z+/]*={0,2}$/;return Ne(n=>n.length%4===0&&r.test(n),{expected:\"a base64 encoded string\",representation:{id:\"effect/schema/isBase64\",payload:null},toJsonSchema:()=>({pattern:t}),arbitraryConstraint:{patterns:[{source:t,flags:\"\"}]},toCode:()=>({runtime:\"Schema.isBase64()\"}),...e})}function ste(e){let t=\"^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$\",r=/^[0-9a-zA-Z-_]*={0,2}$/;return Ne(n=>r.test(n)&&(n.endsWith(\"=\")?n.length%4===0:n.length%4!==1),{expected:\"a base64url encoded string\",representation:{id:\"effect/schema/isBase64Url\",payload:null},toJsonSchema:()=>({pattern:t}),arbitraryConstraint:{patterns:[{source:t,flags:\"\"}]},toCode:()=>({runtime:\"Schema.isBase64Url()\"}),...e})}function Iv(e,t,r){if(e.length===0)return t.length===0?{}:[{},!0];let n={pattern:new globalThis.RegExp(r).source};return e===t?n:[n,!0]}function ate(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(`^${_a(e)}`),o=e.replace(/[\\uD800-\\uDBFF]$/,\"\");return Ne(s=>s.startsWith(e),{expected:`a string starting with ${r}`,representation:{id:\"effect/schema/isStartingWith\",payload:{startsWith:e}},toJsonSchema:()=>Iv(o,e,`^${_a(o)}`),toCode:()=>({runtime:`Schema.isStartingWith(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}function ite(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(`${_a(e)}$`),o=e.replace(/^[\\uDC00-\\uDFFF]/,\"\");return Ne(s=>s.endsWith(e),{expected:`a string ending with ${r}`,representation:{id:\"effect/schema/isEndingWith\",payload:{endsWith:e}},toJsonSchema:()=>Iv(o,e,`${_a(o)}$`),toCode:()=>({runtime:`Schema.isEndingWith(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}function cte(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(_a(e)),o=e.replace(/^[\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF]$/g,\"\");return Ne(s=>s.includes(e),{expected:`a string including ${r}`,representation:{id:\"effect/schema/isIncluding\",payload:{includes:e}},toJsonSchema:()=>Iv(o,e,_a(o)),toCode:()=>({runtime:`Schema.isIncluding(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}var NK=\"^[^a-z]*$\";function ute(e){let t=new globalThis.RegExp(NK);return Ne(r=>r.toUpperCase()===r,{expected:\"a string with all characters in uppercase\",representation:{id:\"effect/schema/isUppercased\",payload:null},toJsonSchema:()=>[{pattern:t.source},!0],toCode:()=>({runtime:\"Schema.isUppercased()\"}),arbitraryConstraint:{patterns:[{source:NK,flags:\"\"}]},...e})}var UK=\"^[^A-Z]*$\";function fte(e){let t=new globalThis.RegExp(UK);return Ne(r=>r.toLowerCase()===r,{expected:\"a string with all characters in lowercase\",representation:{id:\"effect/schema/isLowercased\",payload:null},toJsonSchema:()=>[{pattern:t.source},!0],toCode:()=>({runtime:\"Schema.isLowercased()\"}),arbitraryConstraint:{patterns:[{source:UK,flags:\"\"}]},...e})}var DK=\"^(?:[^a-z][\\\\s\\\\S]*)?$\";function lte(e){return Ne(t=>{let[r=\"\"]=t;return r.toUpperCase()===r},{expected:\"a string with the first character in uppercase\",representation:{id:\"effect/schema/isCapitalized\",payload:null},toJsonSchema:()=>[{pattern:DK},!0],toCode:()=>({runtime:\"Schema.isCapitalized()\"}),arbitraryConstraint:{patterns:[{source:DK,flags:\"\"}]},...e})}var LK=\"^(?:[^A-Z][\\\\s\\\\S]*)?$\";function pte(e){return Ne(t=>{let[r=\"\"]=t;return r.toLowerCase()===r},{expected:\"a string with the first character in lowercase\",representation:{id:\"effect/schema/isUncapitalized\",payload:null},toJsonSchema:()=>[{pattern:LK},!0],toCode:()=>({runtime:\"Schema.isUncapitalized()\"}),arbitraryConstraint:{patterns:[{source:LK,flags:\"\"}]},...e})}var Ul=Q(RC),dte=_C;function Zm(e){let t=ef(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value greater than ${r(n)}`,arbitraryConstraint:{order:e.order,minimum:n,exclusiveMinimum:!0},...e.annotate?.(n),...o})}function Ym(e){let t=Vh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value greater than or equal to ${r(n)}`,arbitraryConstraint:{order:e.order,minimum:n},...e.annotate?.(n),...o})}function Qm(e){let t=Jh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value less than ${r(n)}`,arbitraryConstraint:{order:e.order,maximum:n,exclusiveMaximum:!0},...e.annotate?.(n),...o})}function Xm(e){let t=Gh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value less than or equal to ${r(n)}`,arbitraryConstraint:{order:e.order,maximum:n},...e.annotate?.(n),...o})}function eh(e){let t=Vh(e.order),r=ef(e.order),n=Gh(e.order),o=Jh(e.order),s=e.formatter??K;return(a,i)=>{let c=a.exclusiveMinimum?r:t,u=a.exclusiveMaximum?o:n;return Ne(f=>c(f,a.minimum)&&u(f,a.maximum),{expected:`a value between ${s(a.minimum)}${a.exclusiveMinimum?\" (excluded)\":\"\"} and ${s(a.maximum)}${a.exclusiveMaximum?\" (excluded)\":\"\"}`,arbitraryConstraint:{order:e.order,minimum:a.minimum,maximum:a.maximum,...a.exclusiveMinimum&&{exclusiveMinimum:!0},...a.exclusiveMaximum&&{exclusiveMaximum:!0}},...e.annotate?.(a),...i})}}function mte(e){return(t,r)=>{let n=e.formatter??K;return Ne(o=>e.remainder(o,t)===e.zero,{expected:`a value that is a multiple of ${n(t)}`,...e.annotate?.(t),...r})}}function Ol(e){if(!globalThis.Number.isFinite(e))throw new globalThis.RangeError(`Expected a finite number, got ${K(e)}`);return e}var hte=Zm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isGreaterThan\",payload:{exclusiveMinimum:Ol(e)}},toJsonSchema:()=>({exclusiveMinimum:e}),toCode:()=>({runtime:`Schema.isGreaterThan(${K(e)})`})})}),TB=Ym({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualTo\",payload:{minimum:Ol(e)}},toJsonSchema:()=>({minimum:e}),toCode:()=>({runtime:`Schema.isGreaterThanOrEqualTo(${K(e)})`})})}),xte=Qm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isLessThan\",payload:{exclusiveMaximum:Ol(e)}},toJsonSchema:()=>({exclusiveMaximum:e}),toCode:()=>({runtime:`Schema.isLessThan(${K(e)})`})})}),gte=Xm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualTo\",payload:{maximum:Ol(e)}},toJsonSchema:()=>({maximum:e}),toCode:()=>({runtime:`Schema.isLessThanOrEqualTo(${K(e)})`})})}),Ls=eh({order:Qs,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetween\",payload:{minimum:Ol(e.minimum),maximum:Ol(e.maximum),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>({[t?\"exclusiveMinimum\":\"minimum\"]:e.minimum,[r?\"exclusiveMaximum\":\"maximum\"]:e.maximum}),toCode:()=>({runtime:`Schema.isBetween({ minimum: ${K(e.minimum)}, maximum: ${K(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}});function yte(e,t){if(!globalThis.Number.isFinite(e)||e===0)throw new globalThis.RangeError(`Expected a finite non-zero number, got ${globalThis.String(e)}`);return e=globalThis.Math.abs(e),Ne(r=>D1(r,e)===0,{expected:`a value that is a multiple of ${e}`,representation:{id:\"effect/schema/isMultipleOf\",payload:{divisor:e}},toJsonSchema:()=>({multipleOf:e}),toCode:()=>({runtime:`Schema.isMultipleOf(${K(e)})`}),...t})}function DS(e){return Ne(t=>globalThis.Number.isSafeInteger(t),{expected:\"an integer\",representation:{id:\"effect/schema/isInt\",payload:null},toJsonSchema:()=>({type:\"integer\",minimum:globalThis.Number.MIN_SAFE_INTEGER,maximum:globalThis.Number.MAX_SAFE_INTEGER}),toCode:()=>({runtime:\"Schema.isInt()\"}),arbitraryConstraint:{number:\"integer\"},...e})}var en=wu.check(DS()),ts=en.check(TB(0));function Ste(e){return new fu([DS(),Ls({minimum:-2147483648,maximum:2147483647})],{expected:\"a 32-bit integer\",...e})}function bte(e){return new fu([DS(),Ls({minimum:0,maximum:4294967295})],{expected:\"a 32-bit unsigned integer\",...e})}function _l(e){if(globalThis.Number.isNaN(e.getTime()))throw new globalThis.RangeError(`Expected a valid Date, got ${K(e)}`);return e.toISOString()}function Rl(e){return`new globalThis.Date(${K(e.getTime())})`}var Ete=Zm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanDate\",payload:{exclusiveMinimum:_l(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanDate(${Rl(e)})`})})}),Ite=Ym({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualToDate\",payload:{minimum:_l(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanOrEqualToDate(${Rl(e)})`})})}),wte=Qm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isLessThanDate\",payload:{exclusiveMaximum:_l(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanDate(${Rl(e)})`})})}),Ate=Xm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualToDate\",payload:{maximum:_l(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanOrEqualToDate(${Rl(e)})`})})}),Cte=eh({order:Xu,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetweenDate\",payload:{minimum:_l(e.minimum),maximum:_l(e.maximum),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenDate({ minimum: ${Rl(e.minimum)}, maximum: ${Rl(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}}),Tte=Zm({order:Qu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanBigInt\",payload:{exclusiveMinimum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanBigInt(${K(e)})`})})}),vB=Ym({order:Qu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualToBigInt\",payload:{minimum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanOrEqualToBigInt(${K(e)})`})})}),vte=Qm({order:Qu,annotate:e=>({representation:{id:\"effect/schema/isLessThanBigInt\",payload:{exclusiveMaximum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanBigInt(${K(e)})`})})}),kte=Xm({order:Qu,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualToBigInt\",payload:{maximum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanOrEqualToBigInt(${K(e)})`})})}),Ote=eh({order:Qu,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetweenBigInt\",payload:{minimum:e.minimum.toString(10),maximum:e.maximum.toString(10),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenBigInt({ minimum: ${K(e.minimum)}, maximum: ${K(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}});function wv(e,t){return e=Br(e),kB(e,Math.ceil(e/2),t)}function kB(e,t,r){return Ne(n=>n.length>=e,{expected:`a value with a length of at least ${e}`,representation:{id:\"effect/schema/isMinLength\",payload:{minLength:e}},toJsonSchema:({type:n})=>n===\"string\"?e<=1?{minLength:t}:[{minLength:t},!0]:n===\"array\"?{minItems:e}:n===void 0?[{minLength:t,minItems:e},!0]:[{},!0],toCode:()=>({runtime:`Schema.isMinLength(${e})`}),[pn]:!0,arbitraryConstraint:{minLength:e},...r})}function OB(e){return kB(1,1,e)}function _B(e,t){return e=Br(e),Ne(r=>r.length<=e,{expected:`a value with a length of at most ${e}`,representation:{id:\"effect/schema/isMaxLength\",payload:{maxLength:e}},toJsonSchema:({type:r})=>r===\"string\"?e===0?{maxLength:e}:[{maxLength:e},!0]:r===\"array\"?{maxItems:e}:r===void 0?[{maxLength:e,maxItems:e},!0]:[{},!0],toCode:()=>({runtime:`Schema.isMaxLength(${e})`}),[pn]:!0,arbitraryConstraint:{maxLength:e},...t})}function Av(e,t,r){return e=Br(e),t=Br(t),Ne(n=>n.length>=e&&n.length<=t,{expected:e===t?`a value with a length of ${e}`:`a value with a length between ${e} and ${t}`,representation:{id:\"effect/schema/isBetweenLength\",payload:{minimum:e,maximum:t}},toJsonSchema:({type:n})=>n===\"string\"?t===0||Math.ceil(e/2)>t?{minLength:Math.ceil(e/2),maxLength:t}:[{minLength:Math.ceil(e/2),maxLength:t},!0]:n===\"array\"?{minItems:e,maxItems:t}:n===void 0?[{minLength:Math.ceil(e/2),maxLength:t,minItems:e,maxItems:t},!0]:[{},!0],toCode:()=>({runtime:`Schema.isBetweenLength(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minLength:e,maxLength:t},...r})}function _te(e,t){return e=Br(e),Ne(r=>Cv(r,e)>=e,{expected:`a string with at least ${e} code points`,representation:{id:\"effect/schema/isMinCodePoints\",payload:{minCodePoints:e}},toJsonSchema:()=>({minLength:e}),toCode:()=>({runtime:`Schema.isMinCodePoints(${e})`}),arbitraryConstraint:{minCodePoints:e},...t})}function Rte(e,t){return e=Br(e),Ne(r=>Cv(r,e+1)<=e,{expected:`a string with at most ${e} code points`,representation:{id:\"effect/schema/isMaxCodePoints\",payload:{maxCodePoints:e}},toJsonSchema:()=>({maxLength:e}),toCode:()=>({runtime:`Schema.isMaxCodePoints(${e})`}),arbitraryConstraint:{maxCodePoints:e},...t})}function Pte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>{let o=Cv(n,t+1);return o>=e&&o<=t},{expected:e===t?`a string with ${e} code points`:`a string with between ${e} and ${t} code points`,representation:{id:\"effect/schema/isBetweenCodePoints\",payload:{minimum:e,maximum:t}},toJsonSchema:()=>({allOf:[{minLength:e},{maxLength:t}]}),toCode:()=>({runtime:`Schema.isBetweenCodePoints(${e}, ${t})`}),arbitraryConstraint:{minCodePoints:e,maxCodePoints:t},...r})}function Cv(e,t){if(t===0)return 0;let r=0;for(let n of e)if(++r>=t)break;return r}function Br(e){if(!globalThis.Number.isFinite(e))throw new globalThis.RangeError(`Expected a finite number, got ${e}`);return Math.max(0,Math.floor(e))}function Mte(e,t){return e=Br(e),Ne(r=>r.size>=e,{expected:`a value with a size of at least ${e}`,representation:{id:\"effect/schema/isMinSize\",payload:{minSize:e}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isMinSize(${e})`}),[pn]:!0,arbitraryConstraint:{minSize:e},...t})}function Fte(e,t){return e=Br(e),Ne(r=>r.size<=e,{expected:`a value with a size of at most ${e}`,representation:{id:\"effect/schema/isMaxSize\",payload:{maxSize:e}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isMaxSize(${e})`}),[pn]:!0,arbitraryConstraint:{maxSize:e},...t})}function Nte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>n.size>=e&&n.size<=t,{expected:e===t?`a value with a size of ${e}`:`a value with a size between ${e} and ${t}`,representation:{id:\"effect/schema/isBetweenSize\",payload:{minimum:e,maximum:t}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenSize(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minSize:e,maxSize:t},...r})}function Ute(e,t){return e=Br(e),Ne(r=>Reflect.ownKeys(r).length>=e,{expected:`a value with at least ${e===1?\"1 entry\":`${e} entries`}`,representation:{id:\"effect/schema/isMinProperties\",payload:{minProperties:e}},toJsonSchema:({type:r})=>r===\"object\"?{minProperties:e}:[{minProperties:e},!0],toCode:()=>({runtime:`Schema.isMinProperties(${e})`}),[pn]:!0,arbitraryConstraint:{minProperties:e},...t})}function Dte(e,t){return e=Br(e),Ne(r=>Reflect.ownKeys(r).length<=e,{expected:`a value with at most ${e===1?\"1 entry\":`${e} entries`}`,representation:{id:\"effect/schema/isMaxProperties\",payload:{maxProperties:e}},toJsonSchema:({type:r})=>r===\"object\"?{maxProperties:e}:[{maxProperties:e},!0],toCode:()=>({runtime:`Schema.isMaxProperties(${e})`}),[pn]:!0,arbitraryConstraint:{maxProperties:e},...t})}function Lte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>Reflect.ownKeys(n).length>=e&&Reflect.ownKeys(n).length<=t,{expected:e===t?`a value with exactly ${e===1?\"1 entry\":`${e} entries`}`:`a value with between ${e} and ${t} entries`,representation:{id:\"effect/schema/isBetweenProperties\",payload:{minimum:e,maximum:t}},toJsonSchema:({type:n})=>n===\"object\"?{minProperties:e,maxProperties:t}:[{minProperties:e,maxProperties:t},!0],toCode:()=>({runtime:`Schema.isBetweenProperties(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minProperties:e,maxProperties:t},...r})}function $te(e,t){let r=Ml(e),n=_L(r.ast);return Ne((o,s,a)=>{let i=Reflect.ownKeys(o),c=[];for(let u of i){let f=n(u,a);if(f!==void 0&&(c.push(new Ot([u],f)),a.errors===\"first\"))break}return Mr(c)?new Ht(s,c,o,a):!0},{expected:\"an object with property names matching the schema\",representation:{id:\"effect/schema/isPropertyNames\",payload:null,schemas:[r.ast]},toJsonSchema:({schemas:o,type:s})=>s===\"object\"?{propertyNames:o[0]}:[{propertyNames:o[0]},!0],toCode:({schemas:o})=>({runtime:`Schema.isPropertyNames(${o[0].runtime})`}),[pn]:!0,...t})}function Tv(e){return Ne(t=>cx(t).length===t.length,{expected:\"an array with unique items\",representation:{id:\"effect/schema/isUnique\",payload:null},toJsonSchema:()=>({uniqueItems:!0}),toCode:()=>({runtime:\"Schema.isUnique()\"}),arbitraryConstraint:{uniqueBy:D},...e})}function RB(e){return Ne(t=>cx(t.map(([r])=>r)).length===t.length,{expected:\"an array with unique keys\",representation:{id:\"effect/schema/isUniqueKey\",payload:null},toCode:()=>({runtime:\"Schema.isUniqueKey()\"}),arbitraryConstraint:{uniqueBy:t=>t[0]},...e})}var th=H.check(OB()),Kte=H.check(Av(1,1)),PB=e=>(e?.includeStack===!0?1:0)|(e?.excludeCause===!0?2:0),MB=e=>{switch(e){case 0:return;case 1:return{includeStack:!0};case 2:return{excludeCause:!0};case 3:return{includeStack:!0,excludeCause:!0}}},$K=[];function Bte(e){let t=PB(e),r=$K[t];if(r!==void 0)return r;let n=MB(t),o=Au(globalThis.Error,{representation:{id:\"effect/schema/Error\",payload:n??null},toCode:()=>({runtime:n!==void 0?`Schema.ErrorInstance(${K(n)})`:\"Schema.ErrorInstance()\",Type:\"globalThis.Error\"}),expected:\"Error\",toCodecJson:()=>ke()(Joe,SD(n))});return $K[t]=o,o}var KK=[];function jte(e){let t=PB(e),r=KK[t];if(r!==void 0)return r;let n=BS.pipe(J(Fl,bD(MB(t))));return KK[t]=n,n}function Hte(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(Ds([n,o]));return(a,i,c)=>a instanceof globalThis.Map?Sr(St(s)([...a],c),{onSuccess:u=>new globalThis.Map(u),onFailure:u=>mn(i,\"entries\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/ReadonlyMap\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.ReadonlyMap(${n[0].runtime}, ${n[1].runtime})`,Type:`globalThis.ReadonlyMap<${n[0].Type}, ${n[1].Type}>`}),expected:\"ReadonlyMap\",toCodec:([n,o])=>ke()(Be(Ds([n,o])),Ge({decode:s=>new globalThis.Map(s),encode:s=>[...s.entries()]}))});return Q(r.ast,{key:e,value:t})}function zte(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>o instanceof globalThis.Set?Sr(St(n)([...o],a),{onSuccess:i=>new globalThis.Set(i),onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/ReadonlySet\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.ReadonlySet(${r[0].runtime})`,Type:`globalThis.ReadonlySet<${r[0].Type}>`}),expected:\"ReadonlySet\",toCodec:([r])=>ke()(Be(r),Ge({decode:n=>new globalThis.Set(n),encode:n=>[...n.values()]}))});return Q(t.ast,{value:e})}var Wte=Au(globalThis.RegExp,{representation:{id:\"effect/schema/RegExp\",payload:null},toCode:()=>({runtime:\"Schema.RegExp\",Type:\"globalThis.RegExp\"}),expected:\"RegExp\",toCodecJson:()=>ke()(ve({source:H,flags:H}),mt({decode:(e,t)=>Ff({try:()=>new globalThis.RegExp(e.source,e.flags),catch:()=>new fe({expected:\"valid RegExp source and flags\"},e,t)}),encode:e=>g({source:e.source,flags:e.flags})}))}),FB=H.annotate({expected:\"a string that will be decoded as a URL\"}),LS=Au(globalThis.URL,{representation:{id:\"effect/schema/URL\",payload:null},toCode:()=>({runtime:\"Schema.URL\",Type:\"globalThis.URL\"}),expected:\"URL\",toCodecJson:()=>ke()(FB,uC)}),qte=FB.pipe(J(LS,uC)),NB=H.annotate({expected:\"a string that will be decoded as a Date\"}),Dl=je(e=>e instanceof globalThis.Date&&!globalThis.Number.isNaN(e.getTime()),{representation:{id:\"effect/schema/Date\",payload:null},toCode:()=>({runtime:\"Schema.Date\",Type:\"globalThis.Date\"}),expected:\"a valid Date\",toCodecJson:()=>ke()(NB,iC)}),Jte=NB.pipe(J(Dl,iC)),Gte=en.pipe(J(Dl,dD)),Vte=H.annotate({expected:\"a string that will be decoded as JSON\"});function vv(e,t){return Vte.pipe(J(e,_D(t)))}var Zte=vv(Fl),UB=Au(globalThis.File,{representation:{id:\"effect/schema/File\",payload:null},toCode:()=>({runtime:\"Schema.File\",Type:\"globalThis.File\"}),expected:\"File\",toCodecJson:()=>ke()(ve({data:H.check(CB()),type:H,name:H,lastModified:en}),mt({decode:(e,t)=>mr(Xc(e.data),{onFailure:()=>F(new fe({expected:\"a valid Base64 string\"},e.data,t)),onSuccess:r=>{let n=new globalThis.Uint8Array(r);return g(new globalThis.File([n],e.name,{type:e.type,lastModified:e.lastModified}))}}),encode:(e,t)=>fi({try:async()=>{let r=new globalThis.Uint8Array(await e.arrayBuffer());return{data:Ca(r),type:e.type,name:e.name,lastModified:e.lastModified}},catch:()=>new fe({expected:\"a readable File\"},e,t)})}))}),DB=je(e=>e instanceof globalThis.FormData,{representation:{id:\"effect/schema/FormData\",payload:null},toCode:()=>({runtime:\"Schema.FormData\",Type:\"globalThis.FormData\"}),expected:\"FormData\",toCodecJson:()=>ke()(Be(Ds([H,st([ve({_tag:Fa(\"String\"),value:H}),ve({_tag:Fa(\"File\"),value:UB})])])),mt({decode:e=>{let t=new globalThis.FormData;for(let[r,n]of e)t.append(r,n.value);return g(t)},encode:e=>g(globalThis.Array.from(e.entries()).map(([t,r])=>typeof r==\"string\"?[t,{_tag:\"String\",value:r}]:[t,{_tag:\"File\",value:r}]))}))});function Yte(e){return DB.pipe(J(e,RD))}var LB=Au(globalThis.URLSearchParams,{representation:{id:\"effect/schema/URLSearchParams\",payload:null},toCode:()=>({runtime:\"Schema.URLSearchParams\",Type:\"globalThis.URLSearchParams\"}),expected:\"URLSearchParams\",toCodecJson:()=>ke()(H.annotate({expected:\"a query string that will be decoded as URLSearchParams\"}),Ge({decode:e=>new globalThis.URLSearchParams(e),encode:e=>e.toString()}))});function Qte(e){return LB.pipe(J(e,PD))}var Xte=H.annotate({expected:\"a string that will be decoded as a number\"}).pipe(J(wu,ol)),ere=H.annotate({expected:\"a string that will be decoded as a finite number\"}).pipe(J(Ul,ol)),tre=Q(BC).pipe(J(Nl,Oy)),$B=H.check(AB()),rre=H.annotate({expected:\"a string that will be decoded as a trimmed string\"}).pipe(J($B,lD())),nre=H.annotate({expected:\"a base64 encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,TD)),ore=H.annotate({expected:\"a base64 (URL) encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,vD)),sre=H.annotate({expected:\"a hex encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,kD)),are=H.annotate({expected:\"a URI component encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,OD)),lv=st([Ul,cB,H]),ire=ve({issues:Be(ve({message:H,path:Pl(Be(st([lv,ve({key:lv})])))}))}),cre=Jn([0,1]).pipe(J(Gm,Ge({decode:e=>e===1,encode:e=>e?1:0}))),KB=H.annotate({expected:\"a base64 encoded string that will be decoded as Uint8Array\",format:\"byte\",contentEncoding:\"base64\"}),Ll=Au(globalThis.Uint8Array,{representation:{id:\"effect/schema/Uint8Array\",payload:null},toCode:()=>({runtime:\"Schema.Uint8Array\",Type:\"globalThis.Uint8Array\"}),expected:\"Uint8Array\",toCodecJson:()=>ke()(KB,fC)}),ure=KB.pipe(J(Ll,fC)),fre=H.annotate({expected:\"a base64 (URL) encoded string that will be decoded as a Uint8Array\"}).pipe(J(Ll,{decode:V2(),encode:Ay()})),BB=H.annotate({expected:\"a hex encoded string that will be decoded as a Uint8Array\"}).pipe(J(Ll,{decode:Y2(),encode:Cy()})),jB=mt({decode:(e,t)=>{let r=$F(e);return ge(r)?F(new fe({expected:\"a valid BigDecimal string\"},e,t)):g(r.value)},encode:e=>g(ya(e))}),lre=Zm({order:Bf,formatter:e=>ya(e)}),pre=Ym({order:Bf,formatter:e=>ya(e)}),dre=Qm({order:Bf,formatter:e=>ya(e)}),mre=Xm({order:Bf,formatter:e=>ya(e)}),hre=eh({order:Bf,formatter:e=>ya(e)}),HB=H.annotate({expected:\"a string that will be decoded as a BigDecimal\"}),zB=je(gw,{representation:{id:\"effect/schema/BigDecimal\",payload:null},toCode:()=>({runtime:\"Schema.BigDecimal\",Type:\"BigDecimal.BigDecimal\",importDeclarations:['import * as BigDecimal from \"effect/BigDecimal\"']}),expected:\"BigDecimal\",toCodecJson:()=>ke()(HB,jB),toFormatter:()=>e=>ya(e)}),xre=HB.pipe(J(zB,jB)),$l=je(VF,{representation:{id:\"effect/schema/ByteSize\",payload:null},toCode:()=>({runtime:\"Schema.ByteSize\",Type:\"ByteSize.ByteSize\",importDeclarations:['import * as ByteSize from \"effect/ByteSize\"']}),expected:\"ByteSize\",toCodecJson:()=>ke()(Nl.check(vB(globalThis.BigInt(0))),Ge({decode:GF,encode:Lg})),toCodecStringTree:()=>ke()(WB,cC)}),WB=H.annotate({expected:\"a string that will be decoded as a ByteSize\"}),gre=WB.pipe(J($l,cC)),yre=Nl.pipe(J($l,mD)),Sre=wu.pipe(J($l,hD));function pv(e,t){let r=yn()([e,t],([n,o])=>(s,a,i)=>{if(!YI(s))return F(new _t(a,s,i));switch(s._tag){case\"Fail\":return Sr(St(n)(s.error,i),{onSuccess:Af,onFailure:c=>mn(a,\"error\",c,s,i)});case\"Die\":return Sr(St(o)(s.defect,i),{onSuccess:Cf,onFailure:c=>mn(a,\"defect\",c,s,i)});case\"Interrupt\":return g(s)}},{representation:{id:\"effect/schema/CauseReason\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.CauseReason(${n[0].runtime}, ${n[1].runtime})`,Type:`Cause.Failure<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Cause from \"effect/Cause\"']}),expected:\"Cause.Failure\",toCodec:([n,o])=>ke()(st([ve({_tag:zt(\"Fail\"),error:n}),ve({_tag:zt(\"Die\"),defect:o}),ve({_tag:zt(\"Interrupt\"),fiberId:NS(Ul)})]),Ge({decode:s=>{switch(s._tag){case\"Fail\":return Af(s.error);case\"Die\":return Cf(s.defect);case\"Interrupt\":return XI(s.fiberId)}},encode:s=>{switch(s._tag){case\"Fail\":return{_tag:\"Fail\",error:s.error};case\"Die\":return{_tag:\"Die\",defect:s.defect};case\"Interrupt\":return{_tag:\"Interrupt\",fiberId:s.fiberId}}}}))});return Q(r.ast,{error:e,defect:t})}function dv(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(pv(n,o));return(a,i,c)=>id(a)?Sr(St(s)(a.reasons,c),{onSuccess:gs,onFailure:u=>mn(i,\"reasons\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/Cause\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.Cause(${n[0].runtime}, ${n[1].runtime})`,Type:`Cause.Cause<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Cause from \"effect/Cause\"']}),expected:\"Cause\",toCodec:([n,o])=>ke()(Be(pv(n,o)),Ge({decode:gs,encode:({reasons:s})=>s}))});return Q(r.ast,{error:e,defect:t})}function BK(e){return ke()(e,Ge({decode:Cw,encode:wt}))}function bre(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>Kg(o)?Sr(St(n)(wt(o),a),{onSuccess:Cw,onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/Chunk\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.Chunk(${r[0].runtime})`,Type:`Chunk.Chunk<${r[0].Type}>`}),expected:\"Chunk\",toCodec:([r])=>BK(Be(r)),toCodecArbitrary:({constraint:r,typeParameters:[n]})=>BK(MS(Be(n),r?.minLength,r?.maxLength)),toEquivalence:([r])=>ww(r)});return Q(t.ast,{value:e})}function qB(){return Rt((e,t)=>Zt(dA(e),{onNone:()=>F(new fe({message:\"Invalid DateTime input\"},e,t)),onSome:r=>g(mA(r))}))}var Ere=Ge({decode:e=>xA(e),encode:e=>e.offset}),JB=mt({decode:(e,t)=>Zt(OU(e),{onNone:()=>F(new fe({expected:\"a valid IANA time zone\"},e,t)),onSome:g}),encode:e=>g(e.id)}),GB=mt({decode:(e,t)=>Zt(_U(e),{onNone:()=>F(new fe({expected:\"a valid time zone\"},e,t)),onSome:g}),encode:e=>g(Zd(e))}),VB=mt({decode:(e,t)=>Zt(dA(e),{onNone:()=>F(new fe({expected:\"a valid UTC DateTime string\"},e,t)),onSome:r=>g(mA(r))}),encode:e=>g(RU(e))}),ZB=mt({decode:(e,t)=>Zt(kU(e),{onNone:()=>F(new fe({expected:\"a valid Zoned DateTime string\"},e,t)),onSome:g}),encode:e=>g(yA(e))}),YB=-864e13,QB=864e13,Ire=YB+840*60*1e3,wre=QB-840*60*1e3,Are=-720*60*1e3,Cre=840*60*1e3,XB=[\"UTC\",\"Europe/London\",\"America/New_York\",\"Asia/Tokyo\",\"Australia/Sydney\"];function ej(e,t,r){let n=Math.max(t,e?.minimum===void 0?t:e.minimum.epochMilliseconds+(e.exclusiveMinimum===!0?1:0)),o=Math.min(r,e?.maximum===void 0?r:e.maximum.epochMilliseconds-(e.exclusiveMaximum===!0?1:0));return n<=o?[n,o]:[t,r]}function kv(e,t){return en.check(Ls({minimum:e,maximum:t}))}function tj(){return st([kv(Are,Cre),Jn(XB)])}var Kl=je(e=>lA(e)&&CU(e),{representation:{id:\"effect/schema/DateTimeUtc\",payload:null},toCode:()=>({runtime:\"Schema.DateTimeUtc\",Type:\"DateTime.Utc\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.Utc\",toCodecArbitrary:({constraint:e})=>{let[t,r]=ej(e,YB,QB);return Hi()(kv(t,r),le(Vd))},toCodecJson:()=>ke()(H,VB),toFormatter:()=>e=>e.toString()}),Tre=Dl.pipe(J(Kl,{decode:qB(),encode:le(cy)})),vre=H.annotate({expected:\"a string that will be decoded as a DateTime.Utc\"}).pipe(J(Kl,VB)),kre=mt({decode:(e,t)=>mr(p2(e),{onFailure:()=>F(new fe({expected:\"an HTTP date (RFC 9110 \\xA75.6.7)\"},e,t)),onSuccess:g}),encode:e=>g(zA(e))}),Ore=H.annotate({expected:\"an HTTP date string\"}).pipe(J(Kl,kre)),_re=en.pipe(J(Kl,{decode:qB(),encode:le(gA)})),Rre=je(wU,{representation:{id:\"effect/schema/TimeZoneOffset\",payload:null},toCode:()=>({runtime:\"Schema.TimeZoneOffset\",Type:\"DateTime.TimeZone.Offset\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone.Offset\",toCodecJson:()=>ke()(en,Ere),toFormatter:()=>e=>Zd(e)}),rj=H.annotate({expected:\"an IANA time zone identifier\"}),nj=je(AU,{representation:{id:\"effect/schema/TimeZoneNamed\",payload:null},toCode:()=>({runtime:\"Schema.TimeZoneNamed\",Type:\"DateTime.TimeZone.Named\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone.Named\",toCodecArbitrary:()=>Hi()(Jn(XB),le(hA)),toCodecJson:()=>ke()(rj,JB),toFormatter:()=>e=>Zd(e)}),Pre=rj.pipe(J(nj,JB)),oj=H.annotate({expected:\"a time zone string (IANA identifier or offset like +03:00)\"}),sj=je(IU,{representation:{id:\"effect/schema/TimeZone\",payload:null},toCode:()=>({runtime:\"Schema.TimeZone\",Type:\"DateTime.TimeZone\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone\",toCodecArbitrary:()=>Hi()(tj(),le(e=>typeof e==\"number\"?xA(e):hA(e))),toCodecJson:()=>ke()(oj,GB),toFormatter:()=>e=>Zd(e)}),Mre=oj.pipe(J(sj,GB)),aj=H.annotate({expected:\"a zoned DateTime string (e.g. 2024-01-01T00:00:00.000+00:00[Europe/London])\"}),ij=je(e=>lA(e)&&TU(e),{representation:{id:\"effect/schema/DateTimeZoned\",payload:null},toCode:()=>({runtime:\"Schema.DateTimeZoned\",Type:\"DateTime.Zoned\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.Zoned\",toCodecArbitrary:({constraint:e})=>{let[t,r]=ej(e,Ire,wre);return Hi()(ve({epochMilliseconds:kv(t,r),timeZone:tj()}),le(({epochMilliseconds:n,timeZone:o})=>vU(n,{timeZone:o})))},toCodecJson:()=>ke()(aj,ZB),toFormatter:()=>e=>yA(e),toEquivalence:()=>pA}),Fre=aj.pipe(J(ij,ZB)),bn=(e,t,r,n)=>H.pipe(J(e,mt({decode:(o,s)=>{let a=t(o);return rt(a)?g(a.success):F(new fe({message:a.failure.message},o,s))},encode:o=>g(r(o))}))).annotate({identifier:n}),Cu=je(Al,{identifier:\"MacAddress\"}),Bl=bn(Cu,oK,RT,\"MacAddressFromString\"),rh=je(Ir,{identifier:\"Ipv4Address\"}),Ov=bn(rh,bu,wr,\"Ipv4AddressFromString\"),$S=je(go,{identifier:\"Ipv6Address\"}),cj=bn($S,Eu,wr,\"Ipv6AddressFromString\"),Wi=je(vT,{identifier:\"IpAddress\"}),Tu=bn(Wi,$i,wr,\"IpAddressFromString\"),ht=(e,t,r,n)=>dB(t,{expected:r})(e).annotate({identifier:n}),Nre=ht(Wi,Cl,\"a multicast address\",\"IpMulticastAddress\"),Ure=ht(Tu,Cl,\"a multicast address\",\"IpMulticastAddressFromString\"),Dre=ht(Cu,Cl,\"a multicast address\",\"MacMulticastAddress\"),Lre=ht(Bl,Cl,\"a multicast address\",\"MacMulticastAddressFromString\"),$re=ht(Wi,NT,\"a unicast address\",\"IpUnicastAddress\"),Kre=ht(Tu,NT,\"a unicast address\",\"IpUnicastAddressFromString\"),Bre=ht(Cu,xS,\"a unicast address\",\"MacUnicastAddress\"),jre=ht(Bl,xS,\"a unicast address\",\"MacUnicastAddressFromString\"),Hre=ht(rh,yS,\"a broadcast address\",\"Ipv4BroadcastAddress\"),zre=ht(Ov,yS,\"a broadcast address\",\"Ipv4BroadcastAddressFromString\"),Wre=ht(Cu,hS,\"a broadcast address\",\"MacBroadcastAddress\"),qre=ht(Bl,hS,\"a broadcast address\",\"MacBroadcastAddressFromString\"),Jre=ht(Wi,FT,\"a loopback address\",\"IpLoopbackAddress\"),Gre=ht(Tu,FT,\"a loopback address\",\"IpLoopbackAddressFromString\"),Vre=ht(Wi,UT,\"a link-local address\",\"IpLinkLocalAddress\"),Zre=ht(Tu,UT,\"a link-local address\",\"IpLinkLocalAddressFromString\"),Yre=ht(Wi,gS,\"an unspecified address\",\"IpUnspecifiedAddress\"),Qre=ht(Tu,gS,\"an unspecified address\",\"IpUnspecifiedAddressFromString\"),Xre=ht(rh,DT,\"a private address\",\"Ipv4PrivateAddress\"),ene=ht(Ov,DT,\"a private address\",\"Ipv4PrivateAddressFromString\"),tne=ht($S,LT,\"a unique-local address\",\"Ipv6UniqueLocalAddress\"),rne=ht(cj,LT,\"a unique-local address\",\"Ipv6UniqueLocalAddressFromString\"),nne=ht(Cu,PT,\"a locally administered address\",\"MacLocallyAdministeredAddress\"),one=ht(Bl,PT,\"a locally administered address\",\"MacLocallyAdministeredAddressFromString\"),sne=ht(Cu,MT,\"a universally administered address\",\"MacUniversallyAdministeredAddress\"),ane=ht(Bl,MT,\"a universally administered address\",\"MacUniversallyAdministeredAddressFromString\"),uj=je(gK,{identifier:\"Ipv4Interface\"}),ine=bn(uj,IS,jm,\"Ipv4InterfaceFromString\"),fj=je(yK,{identifier:\"Ipv6Interface\"}),cne=bn(fj,wS,jm,\"Ipv6InterfaceFromString\"),lj=je(Km,{identifier:\"IpInterface\"}),une=bn(lj,AS,jm,\"IpInterfaceFromString\"),pj=je(bK,{identifier:\"Ipv4Network\"}),fne=bn(pj,IK,zm,\"Ipv4NetworkFromString\"),dj=je(EK,{identifier:\"Ipv6Network\"}),lne=bn(dj,wK,zm,\"Ipv6NetworkFromString\"),mj=je(Hm,{identifier:\"IpNetwork\"}),pne=bn(mj,AK,zm,\"IpNetworkFromString\"),dne=je(Nm,{identifier:\"InetAddressV4\"}),mne=je(Um,{identifier:\"InetAddressV6\"}),hj=je(kT,{identifier:\"InetAddress\"}),hne=bn(hj,$T,SS,\"InetAddressFromString\"),xj=je(dS,{identifier:\"UnixPathAddress\"}),xne=H.pipe(J(xj,Ge({decode:aK,encode:e=>e.path}))).annotate({identifier:\"UnixPathAddressFromString\"}),gne=je(rK,{identifier:\"SocketAddress\"}),Ua=H.check(Ne(Pa,{expected:\"a normalized domain name\"})).pipe(US(\"~effect/net/Host/DomainName\")).annotate({identifier:\"DomainName\"}),gj=bn(Ua,bS,e=>e,\"DomainNameFromString\"),_v=H.check(Ne(OT,{expected:\"a canonical scoped IPv6 literal\"})).pipe(US(\"~effect/net/NetAddress/ScopedIpv6Literal\")).annotate({identifier:\"ScopedIpv6Literal\"}),yj=bn(_v,Dm,e=>e,\"ScopedIpv6LiteralFromString\"),yne=st([Wi,_v,Ua]).annotate({identifier:\"Host\"}),Sne=st([Tu,yj,gj]).annotate({identifier:\"HostFromString\"}),Sj=je(jT,{identifier:\"HostPort\"}),bne=bn(Sj,uK,HT,\"HostPortFromString\"),Ene=en.check(Ls({minimum:0,maximum:65535},{expected:\"a port number\"})),Ine=mt({decode:(e,t)=>Zt(K_(e),{onNone:()=>F(new fe({expected:\"a valid Duration string\"},e,t)),onSome:g}),encode:e=>g(globalThis.String(e))}),wne=mt({decode:e=>g(On(e)),encode:(e,t)=>Zt(B_(e),{onNone:()=>F(new fe({expected:\"a Duration representable as a bigint\"},e,t)),onSome:r=>g(r)})}),Ane=Ge({decode:e=>na(e),encode:e=>Nr(e)}),Cne=mt({decode:(e,t)=>Zt(J_(e),{onNone:()=>F(new fe({expected:\"an ISO 8601 duration without years or months\"},e,t)),onSome:g}),encode:(e,t)=>Zt(q_(e),{onNone:()=>F(new fe({expected:\"a finite Duration\"},e,t)),onSome:g})}),vu=je(Fp,{representation:{id:\"effect/schema/Duration\",payload:null},toCode:()=>({runtime:\"Schema.Duration\",Type:\"Duration.Duration\",importDeclarations:['import * as Duration from \"effect/Duration\"']}),expected:\"Duration\",toCodecJson:()=>ke()(st([ve({_tag:zt(\"Infinity\")}),ve({_tag:zt(\"NegativeInfinity\")}),ve({_tag:zt(\"Nanos\"),value:Nl}),ve({_tag:zt(\"Millis\"),value:en})]),Ge({decode:e=>{switch(e._tag){case\"Infinity\":return ra;case\"NegativeInfinity\":return af;case\"Nanos\":return On(e.value);case\"Millis\":return na(e.value)}},encode:e=>{switch(e.value._tag){case\"Infinity\":return{_tag:\"Infinity\"};case\"NegativeInfinity\":return{_tag:\"NegativeInfinity\"};case\"Nanos\":return{_tag:\"Nanos\",value:e.value.nanos};case\"Millis\":return{_tag:\"Millis\",value:e.value.millis}}}}))}),Tne=H.annotate({expected:\"a string that will be decoded as a Duration\"}),Rv=Tne.pipe(J(vu,Ine)),vne=Nl.pipe(J(vu,wne)),kne=wu.pipe(J(vu,Ane)),One=H.annotate({expected:\"an ISO 8601 duration string that will be decoded as a Duration\"}).pipe(J(vu,Cne)),_ne=Jn(qT),bj=(e,t)=>H.pipe(J(e,mt({decode:(r,n)=>{let o=t(r);return ae(o)?F(new fe({message:o.failure.message},r,n)):wr(o.success)===r?g(o.success):F(new fe({message:\"expected a canonical address\"},r,n))},encode:r=>g(wr(r))}))),uv=en.check(Ls({minimum:0,maximum:255})),kl=en.check(Ls({minimum:0,maximum:65535})),Ej=en.check(Ls({minimum:0,maximum:4294967295})),vS=Ej.pipe(J(vu,Ge({decode:cf,encode:hs}))),So=(e,t)=>je(r=>JT(r)&&r._tag===e,{identifier:`Dns${e.charAt(0)}${e.slice(1).toLowerCase()}Record`,toCodecJson:()=>{let r=Vm(e,t);return ke()(r,mt({decode:(n,o)=>{let{_tag:s,...a}=n,i=mK(e,a);return rt(i)?g(i.success):F(new fe({message:i.failure.message},n,o))},encode:n=>g({...n})}))}}),Ij=So(\"A\",{address:bj(rh,bu)}),wj=So(\"AAAA\",{address:bj($S,Eu)}),Aj=So(\"CAA\",{critical:Gm,tag:H.check(zi(/^[a-z0-9]+$/i)),value:H}),Cj=So(\"CNAME\",{target:Ua}),Tj=So(\"MX\",{exchange:Ua,priority:kl}),vj=So(\"NAPTR\",{order:kl,preference:kl,flags:H,service:H,regexp:H,replacement:Ua}),kj=So(\"NS\",{host:Ua}),Oj=So(\"PTR\",{host:th}),_j=So(\"SOA\",{primary:Ua,admin:th,serial:Ej,refresh:vS,retry:vS,expire:vS,minimum:vS}),Rj=So(\"SRV\",{target:Ua,port:kl,priority:kl,weight:kl}),Pj=So(\"TLSA\",{certUsage:uv,selector:uv,matchingType:uv,data:BB}),Mj=So(\"TXT\",{chunks:FS(H)}),Rne=st([Ij,wj,Aj,Cj,Tj,vj,kj,Oj,_j,Rj,Pj,Mj]).annotate({identifier:\"DnsRecord\"}),Pne=(e,t)=>e===t||e.name===t.name&&e.hash?.name===t.hash?.name&&e.saltLength===t.saltLength,jK=e=>`Digest.${e.name.toLowerCase().replace(\"-\",\"\")}`,Mne=(e,t)=>{if(t.modulusLength===void 0||t.hash===void 0||t._tag===void 0){let o=`${e}.${t.name}`;return t.hash===void 0?o:`{ ...${o}, hash: ${jK(t.hash)} }`}let r=t._tag.charAt(0).toLowerCase()+t._tag.slice(1),n=t.saltLength===void 0?\"\":`, saltLength: ${t.saltLength}`;return`${e}.${r}({ hash: ${jK(t.hash)}, modulusLength: ${t.modulusLength}${n} })`},Fne=e=>{let t={name:e.name};return e.hash!==void 0&&(t.hash=e.hash.name),e.modulusLength!==void 0&&(t.modulusLength=e.modulusLength),e.saltLength!==void 0&&(t.saltLength=e.saltLength),t},$s=(e,t,r,n,o)=>{let s=Mne(t,o),a=cu(()=>`Cannot serialize ${t}.${r} values as JSON, use Schema.${e}FromFormat to read and write keys`);return je(i=>n(i)&&Pne(i.algorithm,o),{expected:`${t}.${r} for ${o.name}`,representation:{id:`effect/crypto/${e}`,payload:Fne(o)},toCode:()=>({runtime:`Schema.${e}(${s})`,Type:`${t}.${r}`,importDeclarations:[`import * as ${t} from \"effect/crypto/${t}\"`,...s.includes(\"Digest.\")?['import * as Digest from \"effect/crypto/Digest\"']:[]]}),toCodecJson:()=>ke()(Fl,{decode:a,encode:a}),toCodecArbitrary:()=>ke()(iB,{decode:a,encode:a}),toFormatter:()=>i=>globalThis.String(i),toEquivalence:()=>(i,c)=>i===c})},kS=(e,t,r)=>new fe({message:e.message,cause:e},t,r),Fj=(e,t,r)=>F(new iu({message:`Schema.${e} only decodes, pass { allowEncode: true } to encode the key`},t,r)),qi=(e,t,r,n)=>Ll.pipe(J(t,mt({decode:(o,s)=>Do(r(o),a=>kS(a,o,s)),encode:(o,s)=>n===void 0?Fj(e,o,s):Do(n(o),a=>kS(a,o,s))}))),Ar=rs(H),Nne=ve({kty:Ar,crv:Ar,alg:Ar,use:Ar,key_ops:rs(Be(H)),ext:rs(Gm),k:Ar,x:Ar,y:Ar,d:Ar,n:Ar,e:Ar,p:Ar,q:Ar,dp:Ar,dq:Ar,qi:Ar,oth:rs(Be(ve({r:Ar,d:Ar,t:Ar})))}),Une=e=>e._tag===\"jwk\"?Nne:e.pem?H:Ll,Ks=(e,t,r,n,o)=>{let s=o&&r._tag!==\"pkcs1\"&&r._tag!==\"sec1\";return Une(r).pipe(J(t,mt({decode:(a,i)=>C(Pf(()=>Promise.resolve()),()=>Do(n(a),c=>kS(c,a,i))),encode:(a,i)=>s?Do(EU(r,a),c=>kS(c,a,i)):Fj(e,a,i)})))},Pv=e=>$s(\"MacKey\",\"Mac\",\"Key\",Yw,e),Dne=(e,t)=>qi(\"MacKeyFromBytes\",Pv(e),r=>Qw(e,r),t?.allowEncode===!0?Xw:void 0),Lne=(e,t,r)=>Ks(\"MacKeyFromFormat\",Pv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Mv=e=>$s(\"AeadKey\",\"Aead\",\"Key\",Nw,e),$ne=(e,t)=>qi(\"AeadKeyFromBytes\",Mv(e),r=>Uw(e,r),t?.allowEncode===!0?Dw:void 0),Kne=(e,t,r)=>Ks(\"AeadKeyFromFormat\",Mv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Fv=e=>$s(\"CipherKey\",\"Cipher\",\"Key\",$w,e),Bne=(e,t)=>qi(\"CipherKeyFromBytes\",Fv(e),r=>Kw(e,r),t?.allowEncode===!0?Bw:void 0),jne=(e,t,r)=>Ks(\"CipherKeyFromFormat\",Fv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Nv=e=>$s(\"SignaturePublicKey\",\"Signature\",\"PublicKey\",iU,e),Hne=e=>qi(\"SignaturePublicKeyFromBytes\",Nv(e),t=>uU(e,t),cA),zne=(e,t)=>Ks(\"SignaturePublicKeyFromFormat\",Nv(t),e,r=>ay(e,t,r),!0),Uv=e=>$s(\"SignaturePrivateKey\",\"Signature\",\"PrivateKey\",aA,e),Wne=(e,t)=>qi(\"SignaturePrivateKeyFromBytes\",Uv(e),r=>cU(e,r),t?.allowEncode===!0?cA:void 0),qne=(e,t,r)=>Ks(\"SignaturePrivateKeyFromFormat\",Uv(t),e,n=>iy(e,t,n),r?.allowEncode===!0),Dv=e=>$s(\"KeyAgreementPublicKey\",\"KeyAgreement\",\"PublicKey\",FN,e),Jne=e=>qi(\"KeyAgreementPublicKeyFromBytes\",Dv(e),t=>UN(e,t),Jw),Gne=(e,t)=>Ks(\"KeyAgreementPublicKeyFromFormat\",Dv(t),e,r=>ay(e,t,r),!0),Lv=e=>$s(\"KeyAgreementPrivateKey\",\"KeyAgreement\",\"PrivateKey\",Ww,e),Vne=(e,t)=>qi(\"KeyAgreementPrivateKeyFromBytes\",Lv(e),r=>NN(e,r),t?.allowEncode===!0?Jw:void 0),Zne=(e,t,r)=>Ks(\"KeyAgreementPrivateKeyFromFormat\",Lv(t),e,n=>iy(e,t,n),r?.allowEncode===!0),$v=e=>$s(\"KeyWrapKey\",\"KeyWrap\",\"Key\",eA,e),Yne=(e,t)=>qi(\"KeyWrapKeyFromBytes\",$v(e),r=>oA(e,r),t?.allowEncode===!0?sA:void 0),Qne=(e,t,r)=>Ks(\"KeyWrapKeyFromFormat\",$v(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Nj=e=>$s(\"KeyWrapPublicKey\",\"KeyWrap\",\"PublicKey\",tU,e),Xne=(e,t)=>Ks(\"KeyWrapPublicKeyFromFormat\",Nj(t),e,r=>ay(e,t,r),!0),Uj=e=>$s(\"KeyWrapPrivateKey\",\"KeyWrap\",\"PrivateKey\",tA,e),eoe=(e,t,r)=>Ks(\"KeyWrapPrivateKeyFromFormat\",Uj(t),e,n=>iy(e,t,n),r?.allowEncode===!0);function toe(e,t,r){let n=yn()([e,t,r],([o,s,a])=>{let i=dv(s,a);return(c,u,f)=>{if(!fd(c))return F(new _t(u,c,f));switch(c._tag){case\"Success\":return Sr(St(o)(c.value,f),{onSuccess:Gr,onFailure:p=>mn(u,\"value\",p,c,f)});case\"Failure\":return Sr(St(i)(c.cause,f),{onSuccess:Fn,onFailure:p=>mn(u,\"cause\",p,c,f)})}}},{representation:{id:\"effect/schema/Exit\",payload:null},toCode:({typeParameters:o})=>({runtime:`Schema.Exit(${o[0].runtime}, ${o[1].runtime}, ${o[2].runtime})`,Type:`Exit.Exit<${o[0].Type}, ${o[1].Type}, ${o[2].Type}>`,importDeclarations:['import * as Exit from \"effect/Exit\"']}),expected:\"Exit\",toCodec:([o,s,a])=>ke()(st([ve({_tag:zt(\"Success\"),value:o}),ve({_tag:zt(\"Failure\"),cause:dv(s,a)})]),Ge({decode:i=>i._tag===\"Success\"?Gr(i.value):Fn(i.cause),encode:i=>ut(i)?{_tag:\"Success\",value:i.value}:{_tag:\"Failure\",cause:i.cause}}))});return Q(n.ast,{value:e,error:t,defect:r})}function HK(e,t,r){return ve({type:zt(e),nodes:Be(ve({index:ts,data:t})),edges:Be(ve({index:ts,source:ts,target:ts,data:r}))})}function zK(e,t){let r=-1,n=new Set;for(let o=0;o{let o=om(r),s=om(n);if(o.type!==s.type||o.nodes.length!==s.nodes.length||o.edges.length!==s.edges.length)return!1;for(let a=0;a{if(n===null)return gy({type:e,nodes:[],edges:[]});let o=n.nodes.map((s,a)=>({index:a,data:s}));return gy({type:e,nodes:o,edges:n.edges.map(([s,a,i],c)=>({index:c,source:s%o.length,target:a%o.length,data:i}))})}))}function soe(e,t,r){let n=yn()([t,r],([o,s])=>{let a=HK(e,o,s);return(i,c,u)=>!VA(i)||i.mutable||i.type!==e?F(new _t(c,i,u)):C(St(a)(om(i),u),f=>zK(f,u))},{representation:{id:\"effect/schema/Graph\",payload:e},toCode:({typeParameters:o})=>({runtime:`Schema.Graph(${K(e)}, ${o[0].runtime}, ${o[1].runtime})`,Type:`Graph.Graph<${o[0].Type}, ${o[1].Type}, ${K(e)}>`,importDeclarations:['import * as Graph from \"effect/Graph\"']}),expected:`an immutable ${e} Graph`,toCodec:([o,s])=>ke()(HK(e,o,s),mt({decode:zK,encode:(a,i)=>roe(a,e,i)})),toCodecArbitrary:({typeParameters:[o,s]})=>ooe(e,o,s),toEquivalence:([o,s])=>noe(o,s)});return Q(n.ast,{type:e,node:t,edge:r})}function WK(e){return ke()(e,Ge({decode:kA,encode:em}))}function aoe(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(Ds([n,o]));return(a,i,c)=>BU(a)?Sr(St(s)(em(a),c),{onSuccess:kA,onFailure:u=>mn(i,\"entries\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/HashMap\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.HashMap(${n[0].runtime}, ${n[1].runtime})`,Type:`HashMap.HashMap<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as HashMap from \"effect/HashMap\"']}),expected:\"HashMap\",toCodec:([n,o])=>WK(Be(Ds([n,o]))),toCodecArbitrary:({constraint:n,typeParameters:[o,s]})=>WK(MS(Be(Ds([o,s])).check(RB()),n?.minSize,n?.maxSize)),toEquivalence:([n,o])=>_h(n,o)});return Q(r.ast,{key:e,value:t})}function qK(e){return ke()(e,Ge({decode:RA,encode:wt}))}function ioe(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>qU(o)?Sr(St(n)(wt(o),a),{onSuccess:RA,onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/HashSet\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.HashSet(${r[0].runtime})`,Type:`HashSet.HashSet<${r[0].Type}>`}),expected:\"HashSet\",toCodec:([r])=>qK(Be(r)),toCodecArbitrary:({constraint:r,typeParameters:[n]})=>qK(MS(Be(n).check(Tv()),r?.minSize,r?.maxSize)),toEquivalence:([r])=>hp(r)});return Q(t.ast,{value:e})}function ku(e){let t=yn()([e],([r])=>(n,o,s)=>tf(n)?ge(n)?li:Sr(St(r)(n.value,s),{onSuccess:_,onFailure:a=>mn(o,\"value\",a,n,s)}):F(new _t(o,n,s)),{representation:{id:\"effect/schema/Option\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.Option(${r[0].runtime})`,Type:`Option.Option<${r[0].Type}>`,importDeclarations:['import * as Option from \"effect/Option\"']}),expected:\"Option\",toCodec:([r])=>ke()(st([ve({_tag:zt(\"Some\"),value:r}),ve({_tag:zt(\"None\")})]),Ge({decode:n=>n._tag===\"None\"?v():_(n.value),encode:n=>Ce(n)?{_tag:\"Some\",value:n.value}:{_tag:\"None\"}}))});return Q(t.ast,{value:e})}function coe(e){return yv(e).pipe(J(ku(Sn(e)),ED()))}function uoe(e){return NS(e).pipe(J(ku(Sn(e)),ID()))}function foe(e,t){return lB(e).pipe(J(ku(Sn(e)),wD(t)))}var Dj=je(YU,{representation:{id:\"effect/http/Cookie\",payload:null},toCode:()=>({runtime:\"Schema.Cookie\",Type:\"Cookies.Cookie\",importDeclarations:['import * as Cookies from \"effect/http/Cookies\"']}),expected:\"Cookie\"}),Lj=je(ZU,{representation:{id:\"effect/http/Cookies\",payload:null},toCode:()=>({runtime:\"Schema.Cookies\",Type:\"Cookies.Cookies\",importDeclarations:['import * as Cookies from \"effect/http/Cookies\"']}),expected:\"Cookies\",toCodecJson:()=>ke()(Be(H),Ge({decode:QU,encode:n2})),toCodecIso:()=>ke()(Na(H,Dj),Ge({decode:DA,encode:e=>e.cookies}))}),loe=Lj.pipe(J(Na(H,H),Ge({decode:r2,encode:e=>LA(globalThis.Object.entries(e).map(([t,r])=>t2(t,r)))}))),poe=je(c2,{representation:{id:\"effect/http/Headers\",payload:null},toCode:()=>({runtime:\"Schema.Headers\",Type:\"Headers.Headers\",importDeclarations:['import * as Headers from \"effect/http/Headers\"']}),expected:\"Headers\",toEquivalence:()=>HA,toCodec:()=>ke()(Na(H,H),Ge({decode:u2,encode:e=>({...e})}))}),$j=st([ve({_tag:Fa(\"Duration\"),duration:vu.check(Ne(e=>sn(e)&&!hx(e),{expected:\"a finite, non-negative duration\"}))}),ve({_tag:Fa(\"DateTime\"),dateTime:Kl})]),doe=mt({decode:(e,t)=>mr(d2(e),{onFailure:()=>F(new fe({expected:\"whole non-negative seconds or an HTTP date (RFC 9110 \\xA710.2.3)\"},e,t)),onSuccess:g}),encode:e=>g(m2(e))}),moe=H.annotate({expected:\"a Retry-After header value\"}).pipe(J($j,doe)),Kv=je(qA,{representation:{id:\"effect/http/UrlParams\",payload:null},toCode:()=>({runtime:\"Schema.UrlParams\",Type:\"UrlParams.UrlParams\",importDeclarations:['import * as UrlParams from \"effect/http/UrlParams\"']}),expected:\"UrlParams\",toEquivalence:()=>JA,toCodec:()=>ke()(Be(Ds([H,H])),Ge({decode:xy,encode:e=>e.params.map(([t,r])=>[t,nm(r)])}))}),hoe=(e,t)=>Kv.pipe(J(vv(Fl,t),mt({decode:r=>Zt(b2(r,e),{onNone:()=>F(new Ot([e],new Ni(void 0))),onSome:g}),encode:r=>g(xy([[e,r]]))}))),xoe=Kv.pipe(J(Na(H,st([H,FS(H)])),Ge({decode:E2,encode:y2})));function goe(e){return rs(e).pipe(J(ku(Sn(e)),AD()))}function yoe(e){return Pl(e).pipe(J(ku(Sn(e)),CD()))}function Soe(e,t){let r=t===void 0?\"omit\":t.onNoneEncoding,n=r===null?null:void 0;return Pl(yv(e)).pipe(J(ku(Sn(e)),ky({decode:o=>o.pipe(hc(kh),_),encode:r===\"omit\"?mc:o=>_(Tp(mc(o),()=>n))})))}function KS(e,t){let r=typeof t?.label==\"string\"?t.label:void 0,n=t?.disallowJsonEncode===!0,o=r!==void 0?n?{label:r,disallowJsonEncode:!0}:{label:r}:n?{disallowJsonEncode:!0}:void 0,s=r!==void 0?St(zt(r)):void 0,a=yn()([e],([i])=>(c,u,f)=>{if(Qf(c)){let p=s!==void 0?Lf(s(c.label,f),d=>new Ot([\"label\"],d)):ie;return Ct(p,()=>Sr(St(i)(Mi(c),f),{onSuccess:d=>Ta(d,{label:c.label}),onFailure:()=>new Ht(u,[new Ot([\"value\"],new fe(void 0,c,f))],c,f)}))}return F(new _t(u,c,f))},{representation:{id:\"effect/schema/Redacted\",payload:o??null},toCode:({typeParameters:i})=>({runtime:o!==void 0?`Schema.Redacted(${i[0].runtime}, ${K(o)})`:`Schema.Redacted(${i[0].runtime})`,Type:`Redacted.Redacted<${i[0].Type}>`,importDeclarations:['import * as Redacted from \"effect/Redacted\"']}),expected:\"Redacted\",toCodecJson:([i])=>ke()(i,{decode:le(c=>Ta(c,{label:r})),encode:n?cu(c=>\"Cannot serialize Redacted\"+(Ce(c)&&typeof c.value.label==\"string\"?` with label: \"${c.value.label}\"`:\"\")):le(Mi)}),toEquivalence:([i])=>a2(i)});return Q(a.ast,{value:e})}function boe(e,t){return J(KS(Sn(e),{label:t?.label,disallowJsonEncode:t?.disallowEncode}),{decode:le(r=>Ta(r,{label:t?.label})),encode:t?.disallowEncode?cu(r=>\"Cannot encode Redacted\"+(Ce(r)&&typeof r.value.label==\"string\"?` with label: \"${r.value.label}\"`:\"\")):le(Mi)})(e)}function Eoe(e,t){let r=yn()([e,t],([n,o])=>(s,a,i)=>{if(!y_(s))return F(new _t(a,s,i));switch(s._tag){case\"Success\":return Sr(ZC(n)(s.success,i),{onSuccess:j,onFailure:c=>mn(a,\"success\",c,s,i)});case\"Failure\":return Sr(ZC(o)(s.failure,i),{onSuccess:q,onFailure:c=>mn(a,\"failure\",c,s,i)})}},{representation:{id:\"effect/schema/Result\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.Result(${n[0].runtime}, ${n[1].runtime})`,Type:`Result.Result<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Result from \"effect/Result\"']}),expected:\"Result\",toCodec:([n,o])=>ke()(st([ve({_tag:zt(\"Success\"),success:n}),ve({_tag:zt(\"Failure\"),failure:o})]),Ge({decode:s=>s._tag===\"Success\"?j(s.success):q(s.failure),encode:s=>rt(s)?{_tag:\"Success\",success:s.success}:{_tag:\"Failure\",failure:s.failure}}))});return Q(r.ast,{success:e,failure:t})}var Kj=(e,t)=>mt({decode:(r,n)=>Lf(jc(e(r)),o=>new fe({message:o.message},r,n)),encode:r=>g(t(r))}),Bj=ve({major:ts,minor:ts,patch:ts,prerelease:Be(st([ts,H.check(zi(/^[0-9]*[A-Za-z-][0-9A-Za-z-]*$/))]))}),jj=Kj(OK,Iu),Hj=H.annotate({expected:\"a string that will be decoded as a SemVer\"}),zj=je(rv,{representation:{id:\"effect/schema/SemVer\",payload:null},toCode:()=>({runtime:\"Schema.SemVer\",Type:\"SemVer.SemVer\",importDeclarations:['import * as SemVer from \"effect/SemVer\"']}),expected:\"SemVer\",toCodecArbitrary:()=>Hi()(ve({...Bj.fields,build:Be(H.check(zi(/^[0-9A-Za-z-]+$/)))}),le(nv)),toCodecJson:()=>ke()(Hj,jj),toFormatter:()=>Iu}),Ioe=Hj.pipe(J(zj,jj)),Wj=Kj(cv,ji),qj=H.annotate({expected:\"a string that will be decoded as a SemVer range\"}),Jj=je(iv,{representation:{id:\"effect/schema/SemVerRange\",payload:null},toCode:()=>({runtime:\"Schema.SemVerRange\",Type:\"SemVerRange.SemVerRange\",importDeclarations:['import * as SemVerRange from \"effect/SemVerRange\"']}),expected:\"SemVerRange\",toCodecArbitrary:()=>Hi()(Be(Be(ve({operator:Jn([\"\",\"=\",\"<\",\"<=\",\">\",\">=\",\"~\",\"^\"]),version:Bj})).check(wv(1))),le(e=>PK(e.map(t=>t.map(({operator:r,version:n})=>`${r}${Iu(nv(n))}`).join(\" \")).join(\" || \")))),toCodecJson:()=>ke()(qj,Wj),toFormatter:()=>ji}),woe=qj.pipe(J(Jj,Wj)),Aoe=globalThis.Symbol.for(\"immer-draftable\"),mv={};function Bv(e,t,r,n,o){let s=Toe(r,t,n),a=Gj(t),i=class extends e{constructor(...[c,u]){let p=u?.[\"~payload\"],d=p?.token===mv?p.value:r.make(c??{},u);super(d,{...u,disableChecks:!0,\"~payload\":{token:mv,value:d}})}static[qm]=qm;get[a](){return a}static[Aoe]=!0;static identifier=t;static fields=r.fields;static get ast(){return s(this).ast}static pipe(){return te(this,arguments)}static rebuild(c){return s(this).rebuild(c)}static make(c,u){return zL(Mt(s(this).ast),c??{},u,f=>jv(this,f))}static makeOption(c,u){return Gy(s(this))(c??{},u)}static makeEffect(c,u){return s(this).makeEffect(c??{},u)}static annotate(c){return this.rebuild(Go(this.ast,c))}static annotateKey(c){return this.rebuild(Tm(this.ast,c))}static check(...c){return this.rebuild(Us(this.ast,c))}static extend(c){return(u,f)=>{let p=nh(u)?u:ve(u),d={...r.fields,...p.fields},m=Ny(d,r.ast.checks,{identifier:c});return Bv(this,c,gv(Us(m,p.ast.checks),d),f,o)}}static mapFields(c,u){return r.mapFields(c,u)}};return o!==void 0&&Object.assign(i.prototype,o(t)),i}function jv(e,t){return new e(t,{\"~payload\":{token:mv,value:t}})}function Coe(e){return new Ke(le(t=>jv(e,t)),hn())}function Gj(e){return`~effect/Schema/Class/${e}`}function Toe(e,t,r){let n;return o=>{if(n!==void 0)return n;let s=Gj(t),a=u=>u instanceof o||A(u,s),i=Coe(o),c=Q(new fl([e.ast],()=>(u,f,p)=>a(u)?g(u):F(new _t(f,u,p)),{identifier:t,[Sy]:([u])=>({isConstructed:a,link:new Tt(u,i)}),toCodec:([u])=>new Tt(u.ast,i),toEquivalence:([u])=>u,toFormatter:([u])=>f=>`${o.identifier}(${u(f)})`,[sm]:il(e.ast),...r}));return n=J(c,i)(e)}}function nh(e){return RS(e)}var Vj=e=>(t,r)=>{let n=nh(t)?t:ve(t);return Bv(xx,e,n,r,o=>({toString(){return`${o}(${K({...this})})`}}))},voe=e=>(t,r,n)=>{let o=nh(r)?r.mapFields(s=>({_tag:Fa(t),...s}),{unsafePreserveChecks:!0}):Vm(t,r);return Vj(e??t)(o,n)},Zj=e=>(t,r)=>{let n=nh(t)?t:ve(t);return Bv(Ip,e,n,r,s=>({name:s}))},koe=e=>(t,r,n)=>{let o=nh(r)?r.mapFields(s=>({_tag:Fa(t),...s}),{unsafePreserveChecks:!0}):Vm(t,r);return Zj(e??t)(o,n)};function Ooe(e){return t=>t.annotate({toFormatter:e})}function _oe(e,t){return H$(e.ast,t)}function Roe(e){return t=>t.annotate({toEquivalence:e})}function Poe(e){return gT(e.ast)}function Moe(e,t){return Pm(e.ast,t)}function Foe(e,t){let r=Pm(gl(e.ast),t);return cS(r,t)}var Noe=tS,Uoe=rS,oh=nS,Doe=p$,Loe=x$;function $oe(e,t){return L$(e,t)}function Koe(e){return Z$(e)}function Boe(e){return Y$(e)}function joe(e){return Q$(e)}function Hoe(e,t){return r=>Q(Go(r.ast,{toCodecIso:()=>new Tt(e.ast,vy(t))}),{schema:r})}function zoe(e){return D$(e)}function Woe(e){let t=pB(()=>r),r=st([e,Be(t),Na(H,t)]);return r}var BS=Q(Go(cl,{toCode:()=>({runtime:\"Schema.Json\",Type:\"Schema.Json\"})})),qoe=Na(H,BS),Joe=ve({message:H,name:rs(H),stack:rs(H),cause:rs(BS)}),Goe=Q(Go(EL,{toCode:()=>({runtime:\"Schema.MutableJson\",Type:\"Schema.MutableJson\"})}));function Voe(e){return va(e.ast)}function Zoe(e){return e.ast.context?.annotations}var tn=HI,Yj=MM;var Qj=\"~effect/MutableRef\",Yoe={[Qj]:Qj,...kr,toJSON(){return{_id:\"MutableRef\",current:qt(this.current)}}},jl=e=>{let t=Object.create(Yoe);return t.current=e,t};var Xj=e=>e.current;var HS=l(2,(e,t)=>(e.current=t,e));var Qoe=\"~effect/PubSub\";var Xoe=\"~effect/PubSub/Subscription\",JS=e=>Y(()=>sse(e.atomicPubSub(),new Map,oo(),tn(!1),jl(!1),e.strategy(),jl(v()))),GS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new zS}),VS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new WS}),ZS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new ek}),YS=e=>JS({atomicPubSub:()=>eH(e),strategy:()=>new WS}),tk=e=>{let t=typeof e==\"number\"?{capacity:e}:e;if(ase(t.capacity),t.capacity===1/0)return eH(t);let r=t.replay&&t.replay>0?new qS(Math.ceil(t.replay)):void 0;return t.capacity===1?new Gv(r):L1(t.capacity)===t.capacity?new qv(t.capacity,r):new zv(t.capacity,r)},eH=e=>{let t=e?.replay;return new Zv(t&&t>0?new qS(Math.ceil(t)):void 0)};var sh=e=>ma(Un(t=>(HS(e.shutdownFlag,!0),Xe(e.scope,ld(t.id)).pipe(Zr(e.strategy.shutdown),Cg(e.shutdownHook.open),pi)))),QS=l(2,(e,t)=>Y(()=>ese(e,t))),ese=l(2,(e,t)=>{if(e.shutdownFlag.current||Ce(e.ended.current))return!1;if(HS(e.ended,_(t)),e.strategy instanceof zS)for(let[n,o,s]of yi(e.strategy.publishers))s&&ys(o,Gr(!1));let r=Gr(t);for(let n of e.subscribers.values())for(let o of n){let s;for(;(s=Gc(o))!==br;)ys(s,r)}return e.subscribers.clear(),!0});var XS=l(2,(e,t)=>L(()=>e.shutdownFlag.current||Ce(e.ended.current)?g(!1):e.pubsub.publish(t)?(e.strategy.completeSubscribersUnsafe(e.pubsub,e.subscribers),g(!0)):e.strategy.handleSurplus(e.pubsub,e.subscribers,[t],e.shutdownFlag,e.ended)));var tH=l(2,(e,t)=>L(()=>{if(e.shutdownFlag.current||Ce(e.ended.current))return g(!1);let r=e.pubsub.publishAll(t);return e.strategy.completeSubscribersUnsafe(e.pubsub,e.subscribers),r.length===0?g(!0):e.strategy.handleSurplus(e.pubsub,e.subscribers,r,e.shutdownFlag,e.ended)})),ah=e=>ma(Od(t=>{let r=Me(t,Vr),n=tr(e.scope),o=ose(e.pubsub,e.subscribers,e.strategy,e.ended);return xr(n,tse(o)).pipe(Zr(bs(r,s=>Xe(n,s))),jt(o))})),tse=e=>ma(Un(t=>(HS(e.shutdownFlag,!0),ui(yi(e.pollers),r=>u0(r,t.id),{discard:!0,concurrency:\"unbounded\"}).pipe(Yr(()=>Y(()=>{e.subscribers.delete(e.subscription),e.subscription.unsubscribe(),e.replayWindow.close(),e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers)})),Cg(e.shutdownHook.open),pi)))),eb=e=>L(()=>{if(e.shutdownFlag.current)return io;if(e.replayWindow.remaining>0){let r=e.replayWindow.take();return g(r)}let t=e.pollers.length===0?e.subscription.poll():br;return t===br?nH(e):(e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),g(t))}),rH=e=>L(function t(r){if(e.shutdownFlag.current)return io;let n=e.pollers.length===0?e.subscription.pollUpTo(Number.POSITIVE_INFINITY):[];return r&&(n=r.concat(n)),e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),e.replayWindow.remaining>0?g(e.replayWindow.takeAll().concat(n)):Mr(n)?g(n):C(nH(e),o=>t([o]))}),nH=e=>Mf(t=>{if(e.shutdownFlag.current)return t(io);if(Ce(e.ended.current)){let o=e.pollers.length===0?e.subscription.poll():br;return o!==br?(e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),t(g(o))):t(g(e.ended.current.value))}let r=Mc(),n=e.subscribers.get(e.subscription);return n||(n=new Set,e.subscribers.set(e.subscription,n)),n.add(e.pollers),Bo(e.pollers,r),e.strategy.completePollersUnsafe(e.pubsub,e.subscribers,e.subscription,e.pollers),r.effect?t(r.effect):(r.resumes=[t],Y(()=>bF(e.pollers,r)))});var Ft=Symbol.for(\"effect/PubSub/AbsentValue\"),rse=(e,t,r)=>{e.has(t)||e.set(t,new Set),e.get(t).add(r)},nse=(e,t,r)=>{if(!e.has(t))return;let n=e.get(t);n.delete(r),n.size===0&&e.delete(t)},ose=(e,t,r,n)=>new Qv(e,t,e.subscribe(),xa(),tn(!1),jl(!1),r,e.replayWindow(),n),zv=class{array;replayIndices;publisherIndex=0;subscribers;subscriberCount=0;subscribersIndex=0;capacity;replayBuffer;constructor(t,r){this.capacity=t,this.replayBuffer=r,this.array=Array.from({length:t}),this.replayIndices=r?Array.from({length:t}):[],this.subscribers=Array.from({length:t})}replayWindow(){return this.replayBuffer?new Hl(this.replayBuffer):tb}isEmpty(){return this.publisherIndex===this.subscribersIndex}isFull(){return this.publisherIndex===this.subscribersIndex+this.capacity}size(){return this.publisherIndex-this.subscribersIndex}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);if(this.subscriberCount!==0){let n=this.publisherIndex%this.capacity;this.array[n]=t,r!==void 0&&(this.replayIndices[n]=r),this.subscribers[n]=this.subscriberCount,this.publisherIndex+=1}return!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t),n=r.length,o=this.publisherIndex-this.subscribersIndex,s=this.capacity-o,a=Math.min(n,s);if(a===0)return r;let i=0,c=this.publisherIndex+a;for(;this.publisherIndex!==c;){let u=r[i++],f=this.publisherIndex%this.capacity;this.array[f]=u;let p=this.replayBuffer?.offer(u);p!==void 0&&(this.replayIndices[f]=p),this.subscribers[f]=this.subscriberCount,this.publisherIndex+=1}return r.slice(i)}slide(){if(this.subscribersIndex!==this.publisherIndex){let t=this.subscribersIndex%this.capacity,r=this.array[t];this.array[t]=Ft,this.subscribers[t]=0,this.subscribersIndex+=1,this.replayBuffer?.slide(r,this.replayIndices[t])}}subscribe(){return this.subscriberCount+=1,new Wv(this,this.publisherIndex,!1)}},Wv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.publisherIndex===this.subscriberIndex||this.self.publisherIndex===this.self.subscribersIndex}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;if(this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex),this.subscriberIndex!==this.self.publisherIndex){let t=this.subscriberIndex%this.self.capacity,r=this.self.array[t];return this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1,r}return br}pollUpTo(t){if(t=It(t),this.unsubscribed)return[];this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);let r=this.self.publisherIndex-this.subscriberIndex,n=Math.min(t,r);if(n<=0)return[];let o=[],s=this.subscriberIndex+n;for(;this.subscriberIndex!==s;){let a=this.subscriberIndex%this.self.capacity,i=this.self.array[a];this.self.subscribers[a]-=1,this.self.subscribers[a]===0&&(this.self.array[a]=Ft,this.self.subscribersIndex+=1),o.push(i),this.subscriberIndex+=1}return o}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.subscriberCount-=1,this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);this.subscriberIndex!==this.self.publisherIndex;){let t=this.subscriberIndex%this.self.capacity;this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1}}},qv=class{array;replayIndices;mask;publisherIndex=0;subscribers;subscriberCount=0;subscribersIndex=0;capacity;replayBuffer;constructor(t,r){this.capacity=t,this.replayBuffer=r,this.array=Array.from({length:t}),this.replayIndices=r?Array.from({length:t}):[],this.mask=t-1,this.subscribers=Array.from({length:t})}replayWindow(){return this.replayBuffer?new Hl(this.replayBuffer):tb}isEmpty(){return this.publisherIndex===this.subscribersIndex}isFull(){return this.publisherIndex===this.subscribersIndex+this.capacity}size(){return this.publisherIndex-this.subscribersIndex}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);if(this.subscriberCount!==0){let n=this.publisherIndex&this.mask;this.array[n]=t,r!==void 0&&(this.replayIndices[n]=r),this.subscribers[n]=this.subscriberCount,this.publisherIndex+=1}return!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t),n=r.length,o=this.publisherIndex-this.subscribersIndex,s=this.capacity-o,a=Math.min(n,s);if(a===0)return r;let i=0,c=this.publisherIndex+a;for(;this.publisherIndex!==c;){let u=r[i++],f=this.publisherIndex&this.mask;this.array[f]=u;let p=this.replayBuffer?.offer(u);p!==void 0&&(this.replayIndices[f]=p),this.subscribers[f]=this.subscriberCount,this.publisherIndex+=1}return r.slice(i)}slide(){if(this.subscribersIndex!==this.publisherIndex){let t=this.subscribersIndex&this.mask,r=this.array[t];this.array[t]=Ft,this.subscribers[t]=0,this.subscribersIndex+=1,this.replayBuffer?.slide(r,this.replayIndices[t])}}subscribe(){return this.subscriberCount+=1,new Jv(this,this.publisherIndex,!1)}},Jv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.publisherIndex===this.subscriberIndex||this.self.publisherIndex===this.self.subscribersIndex}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;if(this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex),this.subscriberIndex!==this.self.publisherIndex){let t=this.subscriberIndex&this.self.mask,r=this.self.array[t];return this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1,r}return br}pollUpTo(t){if(t=It(t),this.unsubscribed)return[];this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);let r=this.self.publisherIndex-this.subscriberIndex,n=Math.min(t,r);if(n<=0)return[];let o=[],s=this.subscriberIndex+n;for(;this.subscriberIndex!==s;){let a=this.subscriberIndex&this.self.mask,i=this.self.array[a];this.self.subscribers[a]-=1,this.self.subscribers[a]===0&&(this.self.array[a]=Ft,this.self.subscribersIndex+=1),o.push(i),this.subscriberIndex+=1}return o}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.subscriberCount-=1,this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);this.subscriberIndex!==this.self.publisherIndex;){let t=this.subscriberIndex&this.self.mask;this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1}}},Gv=class{publisherIndex=0;subscriberCount=0;subscribers=0;value=Ft;replayIndex=0;capacity=1;replayBuffer;constructor(t){this.replayBuffer=t}replayWindow(){return this.replayBuffer?new Hl(this.replayBuffer):tb}pipe(){return te(this,arguments)}isEmpty(){return this.subscribers===0}isFull(){return!this.isEmpty()}size(){return this.isEmpty()?0:1}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);return this.subscriberCount!==0&&(this.value=t,r!==void 0&&(this.replayIndex=r),this.subscribers=this.subscriberCount,this.publisherIndex+=1),!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t);return r.length===0?r:this.publish(r[0])?r.slice(1):r}slide(){if(this.isFull()){let t=this.value;this.subscribers=0,this.value=Ft,this.replayBuffer?.slide(t,this.replayIndex)}}subscribe(){return this.subscriberCount+=1,new Vv(this,this.publisherIndex,!1)}},Vv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.subscribers===0||this.subscriberIndex===this.self.publisherIndex}size(){return this.isEmpty()?0:1}poll(){if(this.isEmpty())return br;let t=this.self.value;return this.self.subscribers-=1,this.self.subscribers===0&&(this.self.value=Ft),this.subscriberIndex=this.self.publisherIndex,t}pollUpTo(t){return It(t)<1||this.isEmpty()?[]:[this.poll()]}unsubscribe(){this.unsubscribed||(this.unsubscribed=!0,this.self.subscriberCount-=1,this.self.subscribers!==0&&this.subscriberIndex!==this.self.publisherIndex&&(this.self.subscribers-=1,this.self.subscribers===0&&(this.self.value=Ft)))}},Zv=class{publisherHead={value:Ft,replayIndex:void 0,subscribers:0,next:null};publisherTail=this.publisherHead;publisherIndex=0;subscribersIndex=0;capacity=Number.MAX_SAFE_INTEGER;replayBuffer;constructor(t){this.replayBuffer=t}replayWindow(){return this.replayBuffer?new Hl(this.replayBuffer):tb}isEmpty(){return this.publisherHead===this.publisherTail}isFull(){return!1}size(){return this.publisherIndex-this.subscribersIndex}publish(t){let r=this.replayBuffer?.offer(t),n=this.publisherTail.subscribers;if(n!==0){let o={value:t,replayIndex:r,subscribers:n,next:null};this.publisherTail.next=o,this.publisherTail=this.publisherTail.next,this.publisherIndex+=1}return!0}publishAll(t){if(this.publisherTail.subscribers!==0)for(let r of t)this.publish(r);else this.replayBuffer&&this.replayBuffer.offerAll(t);return[]}slide(){if(this.publisherHead!==this.publisherTail){let t=this.publisherHead.next,r=t.value;this.publisherHead=this.publisherHead.next,this.publisherHead.value=Ft,this.subscribersIndex+=1,this.replayBuffer?.slide(r,t.replayIndex)}}subscribe(){return this.publisherTail.subscribers+=1,new Yv(this,this.publisherTail,this.publisherIndex,!1)}},Yv=class{self;subscriberHead;subscriberIndex;unsubscribed;constructor(t,r,n,o){this.self=t,this.subscriberHead=r,this.subscriberIndex=n,this.unsubscribed=o}isEmpty(){if(this.unsubscribed)return!0;let t=!0,r=!0;for(;r;)this.subscriberHead===this.self.publisherTail?r=!1:this.subscriberHead.next.value!==Ft?(t=!1,r=!1):(this.subscriberHead=this.subscriberHead.next,this.subscriberIndex+=1);return t}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;let t=!0,r=br;for(;t;)if(this.subscriberHead===this.self.publisherTail)t=!1;else{let n=this.subscriberHead.next.value;n!==Ft&&(r=n,this.subscriberHead.subscribers-=1,this.subscriberHead.subscribers===0&&(this.self.publisherHead=this.self.publisherHead.next,this.self.publisherHead.value=Ft,this.self.subscribersIndex+=1),t=!1),this.subscriberHead=this.subscriberHead.next,this.subscriberIndex+=1}return r}pollUpTo(t){t=It(t);let r=[],n=0;for(;n!==t;){let o=this.poll();o===br?n=t:(r.push(o),n+=1)}return r}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.publisherTail.subscribers-=1;this.subscriberHead!==this.self.publisherTail;)this.subscriberHead.next.value!==Ft&&(this.subscriberHead.subscribers-=1,this.subscriberHead.subscribers===0&&(this.self.publisherHead=this.self.publisherHead.next,this.self.publisherHead.value=Ft,this.self.subscribersIndex+=1)),this.subscriberHead=this.subscriberHead.next}},Qv=class{[Xoe]={_A:D};pubsub;subscribers;subscription;pollers;shutdownHook;shutdownFlag;strategy;replayWindow;ended;constructor(t,r,n,o,s,a,i,c,u){this.pubsub=t,this.subscribers=r,this.subscription=n,this.pollers=o,this.shutdownHook=s,this.shutdownFlag=a,this.strategy=i,this.replayWindow=c,this.ended=u}pipe(){return te(this,arguments)}},Xv=class{[Qoe]={_A:D};pubsub;subscribers;scope;shutdownHook;shutdownFlag;strategy;ended;constructor(t,r,n,o,s,a,i){this.pubsub=t,this.subscribers=r,this.scope=n,this.shutdownHook=o,this.shutdownFlag=s,this.strategy=a,this.ended=i}pipe(){return te(this,arguments)}},sse=(e,t,r,n,o,s,a)=>new Xv(e,t,r,n,o,s,a),ase=e=>{if(e<=0||e!==1/0&&!Number.isInteger(e))throw new Error(`Cannot construct PubSub with capacity of ${e}`)},zS=class{publishers=xa();get shutdown(){return Un(t=>ui(yi(this.publishers),([r,n,o])=>o?u0(n,t.id):ie,{concurrency:\"unbounded\",discard:!0}))}handleSurplus(t,r,n,o,s){return Mf(a=>{if(Ce(s.current))return a(g(!1));let i=Mc();return this.offerUnsafe(n,i),this.onPubSubEmptySpaceUnsafe(t,r),this.completeSubscribersUnsafe(t,r),Xj(o)?(this.removeUnsafe(i),a(io)):i.effect?a(i.effect):(i.resumes=[a],Y(()=>this.removeUnsafe(i)))})}onPubSubEmptySpaceUnsafe(t,r){let n=!0;for(;n&&!t.isFull();){let o=Gc(this.publishers);if(o===br)n=!1;else{let[s,a,i]=o,c=t.publish(s);c||rw(this.publishers,o),this.completeSubscribersUnsafe(t,r),c&&i&&ys(a,Gr(!0))}}}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}offerUnsafe(t,r){let n=t[Symbol.iterator](),o=n.next();if(!o.done)for(;;){let s=o.value;if(o=n.next(),o.done){Bo(this.publishers,[s,r,!0]);break}Bo(this.publishers,[s,r,!1])}}removeUnsafe(t){nw(this.publishers,([r,n])=>n!==t)}},WS=class{get shutdown(){return ie}handleSurplus(t,r,n,o){return g(!1)}onPubSubEmptySpaceUnsafe(t,r){}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}},ek=class{get shutdown(){return ie}handleSurplus(t,r,n,o,s){return Y(()=>Ce(s.current)?!1:(this.slidingPublishUnsafe(t,n),this.completeSubscribersUnsafe(t,r),!0))}onPubSubEmptySpaceUnsafe(t,r){}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}slidingPublishUnsafe(t,r){let n=r[Symbol.iterator](),o=n.next();if(!o.done&&t.capacity>0){let s=o.value,a=!0;for(;a;){t.slide();let i=t.publish(s);i&&(o=n.next())&&!o.done?s=o.value:i&&(a=!1)}}}},rk=(e,t,r,n,o)=>{let s=!0;for(;s&&!n.isEmpty();){let a=Gc(o);if(a===br)nse(r,n,o),o.length===0?s=!1:rse(r,n,o);else{let i=n.poll();i===br?rw(o,a):(ys(a,Gr(i)),e.onPubSubEmptySpaceUnsafe(t,r))}}},nk=(e,t,r)=>{for(let[n,o]of r)for(let s of o)e.completePollersUnsafe(t,r,n,s)},qS=class{capacity;head={value:Ft,index:0,next:null};tail=this.head;slideValues=[];size=0;index=0;publisherIndex=0;constructor(t){this.capacity=t}slide(t,r){this.slideValues[this.index%this.capacity]={value:t,index:r},this.index++}offer(t){let r=this.publisherIndex++;if(this.tail.value=t,this.tail.index=r,this.tail.next={value:Ft,index:0,next:null},this.tail=this.tail.next,this.size===this.capacity){let n=this.head;this.head=n.next,n.next=null,n.value=Ft}else this.size+=1;return r}offerAll(t){for(let r of t)this.offer(r)}},Hl=class{buffer;values;index=0;remaining;slideIndex;newestIndex=-1;constructor(t){this.buffer=t,this.remaining=t.size,this.slideIndex=t.index,this.values=new Array(this.remaining);let r=t.head;for(let n=0;nthis.newestIndex&&(this.index=(this.index+1)%this.values.length,this.values[(this.index+this.remaining-1)%this.values.length]=s.value,this.newestIndex=s.index)}this.slideIndex=this.buffer.index}take(){if(this.remaining===0)return;this.sync();let t=this.values[this.index];return this.values[this.index]=Ft,this.index=(this.index+1)%this.values.length,this.remaining--,this.remaining===0&&this.close(),t}takeN(t){t=It(t);let r=Math.min(t,this.remaining),n=new Array(r);for(let o=0;o{},takeN:()=>[],takeAll:()=>[],close:()=>{}};var sk=e=>fd(e)?ut(e)?ue(e.value):e:g(e);var iH=\"~effect/Channel\",Rr=e=>A(e,iH),ise={[iH]:{_Env:D,_InErr:D,_InElem:D,_OutErr:D,_OutElem:D},pipe(){return te(this,arguments)}},Ue=e=>{let t=Object.create(ise);return t.transform=(r,n)=>nt(e(r,n),o=>g($e(o))),t},rn=(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>t(o,n))),Cr=e=>Ue((t,r)=>e),ns=e=>Ue(_e(function*(t,r){let n=tr(r),o=a=>Xe(n,bd(a)),s=yield*Lo(e(t,r,n),o);return Lo(s,o)})),we=e=>e.transform,ih=4096,cse=(e,t,r)=>uo({capacity:r?.bufferSize,strategy:r?.strategy}).pipe(Yr(n=>xr(e,fo(n))),Yr(n=>Ss(t(n),e).pipe(nt(o=>cr(n,o)),rr(e,{startImmediately:!0}))));var cH=(e,t)=>Ue((r,n)=>W(cse(n,e,t),Zc)),rb=e=>Ue((t,r)=>L(()=>we(e())(t,r))),use=(e,t,r)=>ns(_e(function*(n,o,s){let a=v();yield*bs(s,c=>Ce(a)?r(a.value,c):ie);let i=yield*ma(W(e,c=>(a=_(c),c)));return yield*we(t(i))(n,o)}));var uH=e=>Cr(Y(()=>{let t=e();return L(()=>{let r=t.next();return r.done?ue(r.value):g(r.value)})})),ak=e=>Cr(Y(()=>{let t=0;return L(()=>t>=e.length?ue():g(e[t++]))}));var ik=(e,t=ih)=>{let r=Xn(t);return Cr(Y(()=>{let n=e(),o=v();return L(()=>{if(o._tag===\"Some\")return ue(o.value);let s=[];for(;s.lengthik(()=>e[Symbol.iterator](),t),nb=e=>ob(g(e));var lH=e=>ob(Y(e)),Ou=Cr(g(ue())),pH=Cr(g(Bc)),Ji=e=>Cr(g(F(e))),dH=e=>Cr(Ig(e)),ch=e=>Cr($e(e)),mH=e=>Cr(da(e)),ck=e=>ch(Rc(e)),ob=e=>Cr(Y(()=>{let t=!1;return L(()=>t?ue():(t=!0,e))}));var hH=e=>Cr(C(e,()=>ue())),uk=e=>Cr(g(C(e,sk)));var xH=e=>Cr(g(Zc(e)));var fk=e=>Cr(g(V0(rH(e),()=>ue())));var gH=e=>_u(W(ah(e),fk)),yH=e=>_u(W(ah(e),t=>uk(eb(t))));var SH=e=>Ue((t,r)=>fse({scope:r,readable:e.evaluate(),onError:e.onError,releaseLockOnEnd:e.releaseLockOnEnd}));var fse=e=>{let t=e.readable.getReader(),r=e.exit??jl(void 0),n=L(()=>r.current?r.current:As(fi({try:()=>t.read(),catch:e.onError}),{onFailure:o=>r.current??$e(o),onSuccess:({done:o,value:s})=>r.current?r.current:o?ue():g(Oe(s))}));return jt(xr(e.scope,e.releaseLockOnEnd?Y(()=>t.releaseLock()):Pf(()=>t.cancel().catch(o=>t.closed.then(()=>Promise.reject(o),zr))).pipe(hi(Y(()=>t.releaseLock())))),n)},lse=(e,t)=>Ue(_e(function*(r,n){let o=e[Symbol.asyncIterator](),s=!1;return o.return&&(yield*xr(n,L(()=>s?Y(()=>{o.return().catch(zr)}):Pf(()=>o.return())))),C(fi({try:()=>{let a=o.next();return s=!0,a.finally(()=>{s=!1})},catch:t}),a=>a.done?ue(a.value):g(a.value))})),bH=(e,t)=>os(lse(e,t),Oe),os=l(2,(e,t)=>rn(e,r=>Y(()=>{let n=0;return W(r,o=>t(o,n++))})));var EH=l(2,(e,t)=>rn(e,r=>g(At(r,n=>C(t(n),ue))))),IH=e=>e===void 0||e!==\"unbounded\"&&e<=1,sb=l(e=>Rr(e[0]),(e,t,r)=>IH(r?.concurrency)?wH(e,t):pse(e,t,r)),wH=(e,t)=>Ue((r,n)=>{let o=0;return W(we(e)(r,n),C(s=>t(s,o++)))}),pse=(e,t,r)=>ns(_e(function*(n,o,s){let a=0,i=yield*we(e)(n,o),c=r.concurrency===\"unbounded\"?Number.MAX_SAFE_INTEGER:Math.min(r.concurrency,Number.MAX_SAFE_INTEGER),u=yield*Fd(0);yield*xr(s,fo(u));let f=co(yield*Hc()),p=gi(s);if(r.unordered){let d=Ug(c),m=gt(d.release(1)),h=As({onFailure:y=>C(cr(u,y),m),onSuccess:y=>C(Ln(u,y),m)});yield*d.take(1).pipe(C(()=>i),C(y=>{let S=a++;return p(f(h(L(()=>t(y,S))))),ie}),ir({disableYield:!0}),nt(y=>d.withPermits(c-1)(cr(u,y))),rr(s))}else{let d=yield*Fd(c-2);yield*xr(s,fo(d)),yield*ga(d).pipe(K0,C(y=>Ln(u,y)),ir({disableYield:!0}),nt(y=>cr(u,y)),rr(s));let m,h=y=>{y._tag!==\"Success\"&&(m=y.cause,Si(u,y.cause))};yield*i.pipe(C(y=>{if(m)return $e(m);let S=a++,b=f(L(()=>t(y,S)));return p(b),b.addObserver(h),Ln(d,xi(b))}),ir({disableYield:!0}),nt(y=>Ln(d,Fn(y)).pipe(Zr(cr(d,y)))),rr(s))}return ga(u)}));var lk=l(e=>Rr(e[0]),(e,t,r)=>IH(r?.concurrency)?dse(e,t):mse(e,t,r)),dse=(e,t)=>Ue((r,n)=>W(we(e)(r,n),o=>{let s,a,i=C(o,u=>(a??=tr(n),Ct(we(t(u))(r,a),f=>(s=c(f),s)))),c=At(u=>{if(s=void 0,a.state._tag===\"Empty\")return i;let f=Xe(a,Bt);return a=void 0,C(f,()=>i)});return L(()=>s??i)})),mse=(e,t,r)=>e.pipe(os(t),cb(r)),AH=l(2,(e,t)=>Ue((r,n)=>Y(()=>{let o,s=tr(n),a=C(we(e)(r,s),i=>(o=At(i,c=>Xe(s,Bt).pipe(C(()=>we(t(c))(r,n)),C(u=>(o=u,u)))),o));return L(()=>o??a)})));var pk=l(4,(e,t,r,n)=>Ue(_e(function*(o,s){let a=yield*we(e)(o,s),i=yield*we(t)(o,s),c=r();return L(()=>{let u=n(c,a,i);return W(u,([f,p])=>(c=p,f))})}))),CH=l(2,(e,t)=>Ue((r,n)=>Y(()=>{let o,s=tr(n),a=C(we(e)(r,s),i=>{let c=i.pipe(Yr(()=>(o=i,ie)),At(u=>Xe(s,Gr(u)).pipe(Zr(we(t(u))(r,n)),C(f=>(o=f,f)))));return o=c,c});return L(()=>o??a)}))),TH=e=>lk(e,D),jr=e=>rn(e,t=>{let r,n=0,o=L(function s(){if(r===void 0)return C(t,i=>{switch(i.length){case 0:return s();case 1:return g(i[0]);default:return r=i,g(i[n++])}});let a=r[n++];return n>=r.length&&(r=void 0,n=0),g(a)});return g(o)}),vH=e=>wH(e,sk),kH=e=>rn(e,t=>g(ir(t,{disableYield:!0}))),OH=l(2,(e,t)=>Fo(typeof t==\"function\"?t(D):t).pipe(W(r=>{let n=gr.defaultValue();return dk(db(e,gr,Y(()=>n)),o=>no(o)?$e(o.cause):r(o.value).pipe(W(s=>{n=s}),At(()=>ue(o.value))))}),_u)),dk=(e,t)=>Ue((r,n)=>Y(()=>{let o,s=()=>{let a=tr(n);return C(we(e)(r,a),i=>(o=nt(i,c=>{let u=bd(c);return Xe(a,u).pipe(C(()=>t(u,n)),C(s))}),o))};return L(()=>o??s())})),_H=e=>dk(e,t=>no(t)?$e(t.cause):ie),RH=l(2,(e,t)=>rn(e,(r,n)=>W(Id(t),o=>Yr(r,o)))),PH=l(2,(e,t)=>Ue((r,n)=>W(we(e)(r,n),o=>C(o,function s(a){return t(a)?g(a):C(o,s)}))));var MH=l(2,(e,t)=>rn(e,r=>g(C(r,function n(o){let s=[];for(let a=0;arn(e,r=>g(C(r,function n(o){let s=[];for(let a=0;arn(e,r=>{let n=C(r,o=>z0(o,t));return g(C(n,function o(s){return yt(s)?g(s):C(n,o)}))})),UH=l(2,(e,t)=>rn(e,r=>g(C(r,function n(o){return C(W0(o,t),s=>yt(s)?g(s):C(r,n))})))),zl=l(e=>Rr(e[0]),(e,t,r,n)=>Ue((o,s)=>W(we(e)(o,s),a=>{let i=t(),c,u=0,f,p=As(a,{onFailure(m){f=m;let h=n?.onHalt&&n.onHalt(i);return h&&h.length>0?g([i,h]):$e(m)},onSuccess(m){let h=r(i,m);return v_(h)?g(h):h}});return L(function m(){if(c===void 0)return f?$e(f):C(p,([y,S])=>(i=y,S.length===0?m():S.length===1?g(S[0]):(c=S,m())));let h=c[u++];return u>=c.length&&(c=void 0,u=0),g(h)})})));var DH=l(3,(e,t,r)=>Ue((n,o)=>W(we(e)(n,o),s=>{let a=t,i=!0;return L(()=>i?(i=!1,g(a)):W(C(s,c=>r(a,c)),c=>(a=c,a)))}))),Wl=l(2,(e,t)=>Ue((r,n)=>{let o=tr(n);return W(we(e)(r,o),s=>{let a=s.pipe(nt(i=>{if(Is(i))return $e(i);let c=o;return o=tr(n),Xe(c,Fn(i)).pipe(Zr(we(t(i))(r,o)),C(u=>(a=u,u)))}));return L(()=>a)})})),LH=l(2,(e,t)=>ib(e,cd,t)),ab=l(2,(e,t)=>Wl(e,r=>hH(C(t(r),n=>$e(r))))),$H=l(3,(e,t,r)=>Wl(e,n=>t(n)?r(n):ch(n))),ib=l(3,(e,t,r)=>Wl(e,n=>{let o=t(n);return ae(o)?ch(o.failure):r(o.success,n)})),Da=l(2,(e,t)=>ib(e,cn,r=>t(r)));var KH=l(2,(e,t)=>rn(e,r=>g(Ag(r,n=>Pc(n)?ie:pi(t(n)))))),BH=l(e=>Rr(e[0]),(e,t,r,n)=>Da(e,o=>t(o)?r(o):n?n(o):Ji(o))),jH=l(e=>Rr(e[0]),(e,t,r,n)=>Da(e,o=>{let s=t(o);return ae(s)?n?n(s.failure):Ji(s.failure):r(s.success)}));var HH=l(e=>Rr(e[0]),(e,t,r,n,o)=>Da(e,s=>{if(Wt(s,t)&&A(s,\"reason\")){let a=s.reason;return Wt(a,r)?n(a,s):o?o(a,s):Ji(s)}return Ji(s)})),zH=l(e=>Rr(e[0]),(e,t,r,n)=>{let o;return Da(e,s=>{if(Wt(s,t)&&A(s,\"reason\")&&A(s.reason,\"_tag\")&&hg(s.reason._tag)){let a=s.reason;return o??=new Set(Object.keys(r)),o.has(a._tag)?r[a._tag](a,s):n?n(a,s):Ji(s)}return Ji(s)})});var WH=l(2,(e,t)=>rn(e,r=>g(Do(r,n=>Pc(n)?n:t(n))))),qH=e=>Da(e,ck),JH=l(e=>Rr(e[0]),(e,t)=>{if(!t?.log)return Da(e,()=>Ou);let r=Xp(t.log);return Da(ab(e,n=>t0(n)?r(n):ie),()=>Ou)}),sH=e=>Wl(e,()=>Ou),GH=l(e=>Rr(e[0]),(e,t)=>{if(!t?.log)return sH(e);let r=Xp(t.log);return sH(ab(e,n=>r(n)))}),VH=l(2,(e,t)=>rb(()=>{let r,n=gr.defaultValue(),o=db(e,gr,Y(()=>n)),s=yk(o,()=>(r=void 0,ie)),a=typeof t==\"function\"?t(D):t;return dk(s,(i,c)=>{if(ut(i))return ue(i.value);let u=cn(i.cause);return ae(u)?$e(u.failure):kt(function*(){r||(r=yield*Fo(a)),n=yield*r(u.success)}).pipe(At(()=>F(u.success)),Ss(c))})})),ZH=l(e=>Rr(e[0]),(e,t,r)=>e.pipe(os(t),cb({...r,concurrency:r?.concurrency??1,switch:!0}))),cb=l(2,(e,{bufferSize:t=16,concurrency:r,switch:n=!1})=>ns(_e(function*(o,s,a){let i=r===\"unbounded\"?Number.MAX_SAFE_INTEGER:Math.max(1,r),c=n?void 0:Ug(i),u=yield*Yj(!0),f=new Map,p=yield*Fd(t);yield*xr(a,fo(p));let d=yield*we(e)(o,s);return yield*kt(function*(){for(;;){let m;c&&(f.size=i;){let[x,w]=I_(f);f.delete(x),f.size===0&&(yield*u.open),yield*Ko(x),yield*di(Xe(w,ld()))}let b=yield*S.pipe(Yr(()=>kd),C(x=>Ln(p,x)),ir({disableYield:!0}),Lo(_e(function*(x){let w=bd(x),I=yield*so(Xe(y,w));if(!f.has(b))return;let T=pd([w,I]);no(T)&&(yield*cr(p,T.cause)),f.delete(b),c&&(yield*c.release(1)),f.size===0&&(yield*u.open)})),Uf);u.closeUnsafe(),f.set(b,y)}}).pipe(nt(m=>{let h=Sd(m);return rt(h)?u.whenOpen(cr(p,m)):cr(p,m)}),rr(a)),ga(p)}))),ub=l(e=>Rr(e[0])&&Rr(e[1]),(e,t,r)=>ns(_e(function*(n,o,s){let a=r?.haltStrategy??\"both\",i=yield*Fd(0);yield*xr(s,fo(i));let c=0;function u(p,d){if(c++,!Is(d))return cr(i,d);switch(a){case\"both\":return c===2?cr(i,d):ie;case\"left\":case\"right\":return p===a?cr(i,d):ie;case\"either\":return cr(i,d)}}let f=(p,d,m)=>we(d)(n,m).pipe(C(h=>h.pipe(C(y=>Ln(i,y)),ir)),Lo(h=>_d(bd(h),y=>Xe(m,y)).pipe(As({onFailure:y=>u(p,y),onSuccess:()=>u(p,h)}))),rr(s));return yield*f(\"left\",e,tr(s)),yield*f(\"right\",t,tr(s)),ga(i)}))),YH=l(2,(e,t)=>ub(e,hH(t),{haltStrategy:\"left\"})),QH=()=>Ue((e,t)=>Y(()=>{let r=\"\",n=!1,o=v();function s(c){let u=[];function f(p){r.length===0?u.push(p):(u.push(r+p),r=\"\")}for(let p=0;po._tag===\"Some\"?ue(o.value):Uc(e,{onSuccess:i,onFailure:$e,onDone:c=>{if(o=_(c),r.length>0){let u=r;return r=\"\",n=!1,g([u])}return ue(c)}}));function i(c){let u=s(c);return u!==null?g(u):a}return a})),XH=(e,t)=>Ue((r,n)=>Y(()=>{let o=new TextDecoder(e,t),s={stream:!0},a=r.pipe(W(kn(i=>o.decode(i,s))),At(i=>{a=ue(i);let c=o.decode();return c.length>0?g(Oe(c)):a}));return L(()=>a)}));var fb=l(2,(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>we(t)(o,n)))),mk=l(2,(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>W(we(t)(hk(o),n),xk)))),ez=e=>e._tag===\"Die\"&&Pc(e.defect)&&id(e.defect.value),tz=e=>e.reasons.some(ez),hk=e=>nt(e,t=>Is(t)?$e(t):yr(o0(t))),hse=e=>tz(e)?gs(e.reasons.flatMap(t=>ez(t)?t.defect.value.reasons:[t])):e,xk=e=>$o(t=>nt(t(e),r=>$e(hse(r)))),_u=e=>Ue((t,r)=>{let n;return g(L(()=>n||e.pipe(Ss(r),C(o=>we(o)(t,r)),C(o=>n=o))))}),rz=e=>ns((t,r,n)=>W(Ss(we(e)(t,r),n),Ss(n)));var nz=l(2,(e,t)=>Ue(_e(function*(r,n){let o=yield*we(e)(r,n),s=yield*uo({capacity:t.capacity===\"unbounded\"?void 0:t.capacity,strategy:t.capacity===\"unbounded\"?void 0:t.strategy});return yield*xr(n,fo(s)),yield*o.pipe(C(a=>Ln(s,a)),ir({disableYield:!0}),Lo(a=>cr(s,a)),rr(n)),ga(s)}))),oz=l(2,(e,t)=>Ue(_e(function*(r,n){let o=yield*we(e)(r,n),s=yield*uo({capacity:t.capacity===\"unbounded\"?void 0:t.capacity,strategy:t.capacity===\"unbounded\"?void 0:t.strategy});return yield*xr(n,fo(s)),yield*o.pipe(C(a=>Vc(s,a)),ir({disableYield:!0}),Lo(a=>cr(s,a)),rr(n)),Zc(s)}))),gk=l(2,(e,t)=>ub(e,Cr(g(C(t,ue))),{haltStrategy:\"either\"})),sz=l(2,(e,t)=>ns(_e(function*(r,n,o){let s=yield*we(e)(r,n),a=yield*rr(t,o,{startImmediately:!0});return L(()=>{let i=a.pollUnsafe();return i===void 0?s:c0(i,{onFailure:$e,onSuccess:ue})})}))),az=l(2,(e,t)=>uh(e,r=>no(r)?t(r.cause):ie)),uh=l(2,(e,t)=>ns((r,n,o)=>bs(o,t).pipe(Zr(we(e)(r,n))))),iz=l(2,(e,t)=>_u(jt(t,e))),yk=l(2,(e,t)=>rn(e,r=>Y(()=>{let n=!0,o=Yr(r,s=>(n=!1,t(s)));return L(()=>n?o:r)}))),cz=l(2,(e,t)=>rn(e,r=>g(At(r,n=>C(t,()=>ue(n)))))),uz=l(2,(e,t)=>uh(e,r=>t)),Ru=(e,t,r)=>L(()=>{let n=oo(),o=we(e)(ue(),n);return At(C(o,t),r||g).pipe(Dn(s=>Xe(n,s)))});var lb=l(2,(e,t)=>Ue((r,n)=>W(ao(we(e)(r,n),t),ao(t)))),pb=l(3,(e,t,r)=>Ue((n,o)=>W(Cs(we(e)(n,o),t,r),Cs(t,r)))),db=l(3,(e,t,r)=>Ue((n,o)=>C(r,s=>we(pb(e,t,s))(n,o)))),fz=l(e=>Rr(e[0]),(e,t,r)=>kp(t)?lb(e,t):Ue((n,o)=>C(r?.local?hd(t,md(),o):cg(t,o),s=>W(ao(we(e)(n,o),s),ao(s))))),lz=l(2,(e,t)=>Ue((r,n)=>Od(o=>{let s=t(o);return we(lb(e,s))(r,n)})));var Sk=function(){let e=Rr(arguments[0]),t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return aH(n,t,r)}return n=>aH(n,t,r)},aH=(e,t,r)=>use(Z0(t,r),n=>pb(e,Ic,n),(n,o)=>Un(s=>{let a=s.getRef(Dr),i=s.getRef(u1);return tg(n,o,a,i)}));var pz=e=>Ru(e,t=>ir(t,{disableYield:!0})),Gi=l(2,(e,t)=>Ru(e,r=>ir(C(r,t),{disableYield:!0}))),dz=l(2,(e,t)=>Ru(e,r=>r.pipe(C(t),C(n=>n?ie:ue()),ir({disableYield:!0})))),bk=e=>W(Pu(e,()=>({bytes:0,arrays:[]}),(t,r)=>{for(let n=0;n{let n=new Uint8Array(r),o=0;for(let s=0;sL(()=>{let t=v();return Ru(e,r=>r.pipe(wg,C(n=>(t=n,ue()))),()=>g(t))}),hz=e=>L(()=>{let t=Symbol(),r=t;return Ru(e,n=>ir(C(n,o=>(r=o,ie)),{disableYield:!0}),()=>r===t?li:$0(r))}),Pu=l(3,(e,t,r)=>L(()=>{let n=t();return Ru(e,o=>No({while:Cn,body:()=>o,step:s=>{n=r(n,s)}}),()=>g(n))})),xz=l(3,(e,t,r)=>L(()=>{let n=t();return Ru(e,o=>No({while:Cn,body:gt(o.pipe(C(s=>r(n,s)),W(s=>{n=s}))),step:zr}),()=>g(n))})),Ek=_e(function*(e){let t=Ug(1),r=yield*Hc(),n=Me(r,Vr);return(yield*we(e)(ue(),n)).pipe(ao(r),t.withPermits(1))},nt(e=>g($e(e)))),Bs=(e,t)=>we(e)(ue(),t);var Ik=l(e=>Rr(e[0]),(e,t)=>$o(r=>Gi(e,n=>Vc(t,n)).pipe(r,so,C(n=>(ut(n)?Nd(t):Si(t,n.cause),ie)))));var gz=l(e=>Rr(e[0]),_e(function*(e,t){let r=yield*zc,n=yield*uo({capacity:typeof t.capacity==\"number\"?t.capacity:void 0,strategy:typeof t.capacity==\"number\"?t.strategy:void 0});return yield*xr(r,fo(n)),yield*rr(Ik(e,n),r),n}));var yz=e=>Wc(e.capacity===\"unbounded\"?YS(e):e.strategy===\"dropping\"?VS(e):e.strategy===\"sliding\"?ZS(e):GS(e),sh),Sz=l(2,_e(function*(e,t){let r=yield*yz(t);return yield*Df(wk(e,r,{shutdownOnEnd:t.shutdownOnEnd!==!1})),r})),wk=l(e=>Rr(e[0]),(e,t,r)=>Gi(e,n=>tH(t,n)).pipe(r?.shutdownOnEnd===!0?hi(sh(t)):D)),bz=l(2,_e(function*(e,t){let r=yield*yz(t);return yield*Gi(e,n=>XS(r,n)).pipe(Dn(n=>QS(r,n)),Df),r}));var nn={};An(nn,{Array:()=>Sue,Boolean:()=>Eue,ByteSize:()=>wue,ConfigError:()=>Vl,Date:()=>kue,Duration:()=>Iue,Finite:()=>hue,Int:()=>xue,Literal:()=>gue,Literals:()=>yue,LogLevel:()=>Cue,NonEmptyString:()=>due,Number:()=>mue,Port:()=>Aue,Record:()=>bue,Redacted:()=>Tue,String:()=>pue,URL:()=>vue,all:()=>BW,fail:()=>fue,flatMap:()=>tue,isConfig:()=>$W,map:()=>KW,mapEffect:()=>rue,nested:()=>Oue,option:()=>oue,orElse:()=>nue,schema:()=>Tr,succeed:()=>lue,unwrap:()=>HW,withDefault:()=>jW});var Gl={};An(Gl,{ConfigProvider:()=>Du,SourceError:()=>gb,constantCase:()=>$ce,fromDir:()=>Xce,fromDotEnv:()=>Qce,fromDotEnvContents:()=>NW,fromEnv:()=>FW,fromEnvRecord:()=>qk,fromUnknown:()=>Hce,layer:()=>Bce,layerAdd:()=>jce,make:()=>Sb,makeArray:()=>zk,makeRecord:()=>yb,makeValue:()=>gh,mapInput:()=>Wk,nested:()=>Kce,orElse:()=>jk});var xse=\"~effect/Stream\",gse={_R:D,_E:D,_A:D},Ez=function(e){this.channel=e};Ez.prototype={[xse]:gse,pipe(){return te(this,arguments)}};var Iz=e=>new Ez(e);var Sse=\"~effect/Sink\";var bse={_A:D,_In:D,_L:D,_E:D,_R:D},Ese={[Sse]:bse,pipe(){return te(this,arguments)}};var Ise=e=>{let t=Object.create(Ese);return t.transform=e,t},wz=e=>Ue((t,r)=>g(C(e.transform(t,r),ue)));var Az=e=>{let t=It(e);return Ise(r=>{let n=[];if(t===0)return g([n]);let o;return r.pipe(C(s=>{if(n.length+s.length<=t){for(let a=0;ag([n,o])))})};var Hs={};An(Hs,{DefaultChunkSize:()=>Lz,Do:()=>fce,TypeId:()=>Dz,accumulate:()=>Jie,aggregate:()=>$ie,aggregateWithin:()=>Nk,as:()=>rae,bind:()=>pce,bindEffect:()=>dce,bindTo:()=>mce,broadcast:()=>hW,broadcastN:()=>Kie,buffer:()=>qae,bufferArray:()=>Jae,callback:()=>Bz,catch:()=>xh,catchCause:()=>tW,catchCauseFilter:()=>nie,catchCauseIf:()=>rie,catchDefect:()=>Gae,catchFilter:()=>Mk,catchIf:()=>nW,catchReason:()=>Xae,catchReasons:()=>eie,catchTag:()=>Yae,catchTags:()=>Qae,changes:()=>Gie,changesWith:()=>xW,changesWithEffect:()=>Vie,chunks:()=>fW,collect:()=>qie,combine:()=>Iie,combineArray:()=>wie,concat:()=>Fu,cross:()=>Tae,crossWith:()=>Qz,debounce:()=>Oie,decodeText:()=>Zie,die:()=>zz,drain:()=>lae,drainFork:()=>pae,drop:()=>Fk,dropRight:()=>Sie,dropUntil:()=>xie,dropUntilEffect:()=>gie,dropWhile:()=>cW,dropWhileEffect:()=>uW,dropWhileFilter:()=>yie,empty:()=>$a,encodeText:()=>Yie,ensuring:()=>sce,fail:()=>ql,failCause:()=>Hz,failCauseSync:()=>Lse,failSync:()=>Dse,filter:()=>Lae,filterEffect:()=>Kae,filterMap:()=>$ae,filterMapEffect:()=>Bae,flatMap:()=>Jl,flatten:()=>Vz,flattenArray:()=>fae,flattenEffect:()=>oae,flattenIterable:()=>yae,flattenTake:()=>Sae,forever:()=>gae,fromArray:()=>dh,fromArrayEffect:()=>jse,fromArrays:()=>Hse,fromAsyncIterable:()=>Jse,fromChannel:()=>k,fromEffect:()=>mb,fromEffectDrain:()=>$z,fromEffectRepeat:()=>Kz,fromEffectSchedule:()=>Mse,fromEventListener:()=>Zse,fromIterable:()=>Nu,fromIterableEffect:()=>Kse,fromIterableEffectRepeat:()=>Bse,fromIteratorSucceed:()=>$se,fromPubSub:()=>Wse,fromPubSubTake:()=>Wz,fromPull:()=>js,fromQueue:()=>zse,fromReadableStream:()=>qse,fromSchedule:()=>Gse,fromSubscription:()=>Vse,groupAdjacentBy:()=>Die,groupBy:()=>Nie,groupByKey:()=>Uie,grouped:()=>Mie,groupedWithin:()=>Fie,haltWhen:()=>rce,ignore:()=>iie,ignoreCause:()=>cie,interleave:()=>ece,interleaveWith:()=>yW,interruptWhen:()=>tce,intersperse:()=>gW,intersperseAffixes:()=>Xie,isStream:()=>Re,iterate:()=>Qse,let:()=>lce,limitBytes:()=>pie,make:()=>Nse,map:()=>Gn,mapAccum:()=>Aie,mapAccumArray:()=>Uu,mapAccumArrayEffect:()=>Tie,mapAccumEffect:()=>Cie,mapArray:()=>Jz,mapArrayEffect:()=>sae,mapBoth:()=>nae,mapEffect:()=>mh,mapError:()=>oW,merge:()=>Ok,mergeAll:()=>Cae,mergeEffect:()=>hb,mergeLeft:()=>wae,mergeResult:()=>Iae,mergeRight:()=>Aae,mkArrayBuffer:()=>vce,mkString:()=>Tce,mkUint8Array:()=>kce,never:()=>eae,onEnd:()=>oce,onError:()=>nce,onExit:()=>SW,onFirst:()=>EW,onStart:()=>bW,orDie:()=>aie,orElseIfEmpty:()=>oie,orElseSucceed:()=>sie,paginate:()=>Yse,partition:()=>Hae,partitionEffect:()=>jae,partitionQueue:()=>Rk,peel:()=>Wae,pipeThrough:()=>Wie,pipeThroughChannel:()=>Hie,pipeThroughChannelOrFail:()=>zie,prepend:()=>Eae,provide:()=>IW,provideContext:()=>ace,provideService:()=>ice,provideServiceEffect:()=>Uk,race:()=>Dae,raceAll:()=>eW,range:()=>Xse,rechunk:()=>lW,repeat:()=>dae,repeatElements:()=>xae,result:()=>aae,retry:()=>uie,run:()=>hce,runCollect:()=>AW,runCount:()=>xce,runDrain:()=>xb,runFold:()=>yce,runFoldEffect:()=>Sce,runForEach:()=>Ice,runForEachArray:()=>Ace,runForEachWhile:()=>wce,runHead:()=>bce,runIntoPubSub:()=>Mce,runIntoQueue:()=>Uce,runLast:()=>Ece,runSum:()=>gce,scan:()=>vie,scanEffect:()=>kie,schedule:()=>mae,scoped:()=>tae,service:()=>Rse,serviceOption:()=>Pse,share:()=>jie,sliding:()=>bie,slidingSize:()=>pW,split:()=>Eie,splitLines:()=>Qie,succeed:()=>Mu,suspend:()=>En,switchMap:()=>uae,sync:()=>Use,take:()=>lie,takeRight:()=>die,takeUntil:()=>sW,takeUntilEffect:()=>aW,takeWhile:()=>iW,takeWhileEffect:()=>hie,takeWhileFilter:()=>mie,tap:()=>Gz,tapBoth:()=>iae,tapCause:()=>rW,tapDefect:()=>Zae,tapError:()=>Pk,tapErrorTag:()=>Vae,tapSink:()=>cae,throttle:()=>Pie,throttleEffect:()=>dW,tick:()=>Fse,timeout:()=>hae,timeoutOrElse:()=>Zz,toAsyncIterable:()=>Pce,toAsyncIterableEffect:()=>Rce,toAsyncIterableWith:()=>$k,toChannel:()=>bo,toPubSub:()=>Fce,toPubSubTake:()=>CW,toPull:()=>Cce,toQueue:()=>Nce,toReadableStream:()=>Oce,toReadableStreamEffect:()=>_ce,toReadableStreamWith:()=>Lk,transduce:()=>Lie,transformPull:()=>or,transformPullBracket:()=>kk,unfold:()=>qz,unwrap:()=>Vi,unwrapReason:()=>tie,updateContext:()=>wW,updateService:()=>cce,when:()=>zae,withExecutionPlan:()=>fie,withSpan:()=>uce,zip:()=>vae,zipFlatten:()=>_ae,zipLatest:()=>Nae,zipLatestAll:()=>_k,zipLatestWith:()=>Uae,zipLeft:()=>kae,zipRight:()=>Oae,zipWith:()=>hh,zipWithArray:()=>Xz,zipWithIndex:()=>Rae,zipWithNext:()=>Pae,zipWithPrevious:()=>Mae,zipWithPreviousAndNext:()=>Fae});var Tz=\"~effect/RcMap\",wse=e=>({[Tz]:Tz,lookup:e.lookup,context:e.context,scope:e.scope,idleTimeToLive:e.idleTimeToLive,capacity:e.capacity,state:{_tag:\"Open\",map:$c()},pipe(){return te(this,arguments)}}),vz=e=>Un(t=>{let r=t.context,n=Me(r,Vr),o=wse({lookup:e.lookup,context:r,scope:n,idleTimeToLive:typeof e.idleTimeToLive==\"function\"?gO(e.idleTimeToLive,ct):gt(ct(e.idleTimeToLive??ta)),capacity:Math.max(e.capacity??Number.POSITIVE_INFINITY,0)});return jt(bs(n,()=>{if(o.state._tag===\"Closed\")return ie;let s=o.state.map;return o.state={_tag:\"Closed\"},ui(s,([,a])=>so(fh(a))).pipe(Yr(()=>Y(()=>{Sg(s)})),C(pd))}),o)}),Ck=l(2,(e,t)=>$o(r=>{if(e.state._tag===\"Closed\")return io;let n=e.state,o=Kf(),s=Nn(n.map,t),a;if(s._tag===\"Some\")a=s.value,a.refCount++;else{if(Number.isFinite(e.capacity)&&Q1(e.state.map)>=e.capacity)return F(new s0(`RcMap attempted to exceed capacity of ${e.capacity}`));{a={deferred:Mc(),scope:oo(),idleTimeToLive:e.idleTimeToLive(t),finalizer:void 0,fiber:void 0,expiresAt:0,refCount:1},a.finalizer=Cse(e,t,a),Kc(n.map,t,a);let c=new Map(e.context.mapUnsafe);o.context.mapUnsafe.forEach((f,p)=>{c.set(p,f)}),c.set(Vr.key,a.scope);let u=Xs(c);L(()=>e.lookup(t)).pipe(co(u),gi(a.scope)).addObserver(f=>{i0(f)&&Ase(e,t,a,u),ys(a.deferred,f)})}}let i=ds(o.context,Vr);return xr(i,a.finalizer).pipe(Zr(r(og(a.deferred))))}));var Ase=(e,t,r,n)=>{if(e.state._tag===\"Closed\")return;let o=Nn(e.state.map,t);o._tag===\"None\"||o.value!==r||(ci(e.state.map,t),!(r.refCount>0)&&fh(r).pipe(di({log:\"Unhandled\",message:\"Unhandled error in RcMap finalizer\"}),co(n),gi(e.scope)))},fh=e=>e.fiber?Ko(e.fiber).pipe(Zr(Xe(e.scope,Bt))):Xe(e.scope,Bt),Cse=(e,t,r)=>Un(n=>{if(r.refCount--,r.refCount>0)return ie;if(e.state._tag===\"Closed\")return fh(r);let o=Nn(e.state.map,t);if(o._tag===\"None\"||o.value!==r)return fh(r);if(Sc(r.idleTimeToLive))return ci(e.state.map,t),fh(r);if(!sn(r.idleTimeToLive))return ie;let s=n.getRef(Tf);return r.expiresAt=s.currentTimeMillisUnsafe()+Nr(r.idleTimeToLive),r.fiber?ie:(r.fiber=$o(function a(i){let c=s.currentTimeMillisUnsafe(),u=r.expiresAt-c;if(u<=0){if(e.state._tag===\"Closed\"||r.refCount>0)return ie;let f=Nn(e.state.map,t);return f._tag===\"None\"||f.value!==r?ie:(ci(e.state.map,t),di(Xe(r.scope,Bt),{log:\"Unhandled\",message:\"Unhandled error in RcMap finalizer\"}))}return C(i(s.sleep(na(u))),()=>a(i))}).pipe(hi(Y(()=>{r.fiber=void 0})),co(n.context),gi(e.scope)),ie)});var Tk=l(2,(e,t)=>qc(r=>{if(e.state._tag===\"Closed\")return ie;let n=Nn(e.state.map,t);if(n._tag===\"None\"||Sc(n.value.idleTimeToLive))return ie;let o=n.value;return o.expiresAt=r.currentTimeMillisUnsafe()+Nr(o.idleTimeToLive),ie}));var Tse=\"~effect/RcRef\",lh={_tag:\"Empty\"},vse={_tag:\"Closed\"},kse={_A:D,_E:D},vk=class{[Tse]=kse;pipe(){return te(this,arguments)}state=lh;acquire;context;scope;idleTimeToLive;constructor(t,r,n,o){this.acquire=t,this.context=r,this.scope=n,this.idleTimeToLive=o}},_z=e=>Un(t=>{let r=t.context,n=Me(r,Vr),o=new vk(e.acquire,r,n,e.idleTimeToLive!==void 0?ct(e.idleTimeToLive):void 0);return jt(bs(n,()=>{let s=o.state;return o.state=vse,s._tag===\"Acquired\"?Xe(s.scope,Bt):s._tag===\"Acquiring\"?Ko(s.fiber):ie}),o)}),Ose=(e,t)=>{switch(e.state._tag){case\"Closed\":return io;case\"Acquired\":{let r=e.state;return r.refCount++,r.fiber?jt(Ko(r.fiber),r):g(r)}case\"Acquiring\":{let r=e.state;return r.awaiters++,Oz(e,r,t)}case\"Empty\":{let r={_tag:\"Acquiring\",fiber:void 0,awaiters:1,acquired:void 0};e.state=r;let n=oo(),o=ao(e.acquire,dr(e.context,Vr,n)).pipe(C(s=>{if(e.state!==r)return io;let a={_tag:\"Acquired\",value:s,scope:n,fiber:void 0,refCount:r.awaiters,invalidated:!1};return e.state=a,r.acquired=a,g(a)}),Dn(s=>ut(s)?ie:(e.state===r&&(e.state=lh),Xe(n,s))));return r.fiber=co(Kf().context)(o),Oz(e,r,t)}}},Oz=(e,t,r)=>Dn(r(xi(t.fiber)),n=>{let o=t.acquired;return o!==void 0?no(n)?Pz(e,o):ie:--t.awaiters>0||e.state!==t?ie:(e.state=lh,Ko(t.fiber))}),Rz=e=>{let t=e;return $o(r=>C(zc,n=>C(Ose(t,r),o=>jt(bs(n,()=>Pz(t,o)),o.value))))},Pz=(e,t)=>{if(t.refCount--,t.refCount>0)return ie;let r=e.idleTimeToLive;return r===void 0||t.invalidated?(e.state===t&&(e.state=lh),Xe(t.scope,Bt)):sn(r)?(t.fiber=$o(n=>C(n(mi(r)),()=>e.state===t&&t.refCount===0?(e.state=lh,di(Xe(t.scope,Bt),{log:\"Unhandled\",message:\"Unhandled error in RcRef finalizer\"})):ie)).pipe(hi(Y(()=>{t.fiber=void 0})),co(e.context),gi(e.scope)),ie):ie};var Mz=_z,Fz=Rz;var Dz=\"~effect/Stream\",Re=e=>A(e,Dz),Lz=ih,k=Iz,mb=e=>k(ob(W(e,Oe))),Rse=e=>mb(J0(e)),Pse=e=>mb(G0(e)),$z=e=>js(g(C(e,()=>ue()))),Kz=e=>js(g(W(e,Oe))),Mse=(e,t)=>js(kt(function*(){let r=yield*Fo(t),n=yield*Cs(e,gr,gr.defaultValue()),o=!0,s=L(()=>r(n)).pipe(C(a=>Cs(e,gr,a)),W(a=>(n=a,Oe(a))));return L(()=>o?(o=!1,g(Oe(n))):s)})),Fse=e=>js(Y(()=>{let t=!0,r=g(Oe(void 0)),n=j0(r,e);return L(()=>t?(t=!1,r):n)})),js=e=>k(Cr(e)),or=(e,t)=>k(Ue((r,n)=>C(Bs(e.channel,n),o=>t(o,n)))),kk=(e,t)=>k(ns((r,n,o)=>C(Bs(e.channel,n),s=>t(s,n,o)))),bo=e=>e.channel,Bz=(e,t)=>k(cH(e,t)),$a=k(Ou),Mu=e=>k(nb(Oe(e))),Nse=(...e)=>dh(e),Use=e=>k(lH(()=>Oe(e()))),En=e=>{let t=k(rb(()=>e().channel));return jz.set(t,e),t},jz=new WeakMap,ql=e=>k(Ji(e)),Dse=e=>k(dH(e)),Hz=e=>k(ch(e)),zz=e=>k(ck(e)),Lse=e=>k(mH(e)),$se=(e,t)=>k(ik(()=>e,t)),Nu=(e,t)=>Array.isArray(e)&&t?.chunkSize===void 0?dh(e):k(fH(e,t?.chunkSize)),Kse=e=>Vi(W(e,Nu)),Bse=e=>Jl(Kz(e),Nu),dh=e=>yt(e)?k(nb(e)):$a,jse=e=>Vi(W(e,dh)),Hse=(...e)=>k(ak(ix(e,yt))),zse=e=>k(xH(e)),Wse=e=>k(gH(e)),Wz=e=>k(yH(e)),qse=e=>k(SH(e)),Jse=(e,t)=>k(bH(e,t)),Gse=e=>js(W(Id(e),t=>At(W(t(void 0),Oe),()=>ue()))),Vse=e=>k(fk(e)),Zse=(e,t,r)=>Bz(n=>{let o=typeof r==\"object\"&&r.once;function s(a){Pg(n,a),o&&Nd(n)}return Wc(Y(()=>e.addEventListener(t,s,r)),()=>Y(()=>e.removeEventListener(t,s,r)))},{bufferSize:typeof r==\"object\"?r.bufferSize:void 0}),qz=(e,t)=>js(Y(()=>{let r=e;return C(L(()=>t(r)),n=>n===void 0?ue():(r=n[1],g(Oe(n[0]))))})),Yse=(e,t)=>js(Y(()=>{let r=e,n=!1;return L(function o(){return n?ue():C(t(r),([s,a])=>(ge(a)?n=!0:r=a.value,yt(s)?g(s):o()))})})),Qse=(e,t)=>qz(e,r=>g([r,t(r)])),Xse=(e,t,r=ih)=>e>t?$a:js(Y(()=>{let n=Xn(r),o=e,s=!1;return L(()=>{if(s)return ue();let a=t-o+1;if(a>n){let c=dE(o,o+n-1);return o+=n,g(c)}let i=dE(o,o+a-1);return s=!0,g(i)})})),eae=k(pH),Vi=e=>k(_u(W(e,bo))),tae=e=>k(rz(e.channel)),Gn=l(2,(e,t)=>En(()=>{let r=0;return k(os(e.channel,kn(n=>t(n,r++))))})),rae=l(2,(e,t)=>Gn(e,()=>t)),nae=l(2,(e,t)=>e.pipe(Gn(t.onElement),oW(t.onError))),Jz=l(2,(e,t)=>k(os(e.channel,t))),mh=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,sb(t,r),os(Oe),k)),oae=l(e=>Re(e[0]),(e,t)=>mh(e,D,t)),sae=l(2,(e,t)=>k(sb(e.channel,t))),aae=e=>e.pipe(Gn(j),xh(t=>Mu(q(t)))),Gz=l(e=>Re(e[0]),(e,t,r)=>mh(e,n=>jt(t(n),n),r)),iae=l(2,(e,t)=>e.pipe(Pk(t.onError),Gz(t.onElement,{concurrency:t.concurrency}))),cae=l(2,(e,t)=>kk(e,_e(function*(r,n,o){let s=tn(),a=tn(),i,c,u=!1,f=!1,p=s.whenOpen(L(()=>{if(i){let m=i;return i=void 0,f||s.closeUnsafe(),jt(a.open,m)}return ue()}));yield*L(()=>t.transform(p,o)).pipe(m=>_d(m,h=>(u=!0,no(h)&&(c=h.cause),a.open),!0),rr(o));let d=r.pipe(C(m=>c?$e(c):u?g(m):(i=m,a.closeUnsafe(),s.openUnsafe(),jt(a.await,m))),At(()=>c?$e(c):u?ue():(f=!0,a.closeUnsafe(),s.openUnsafe(),C(a.await,()=>c?$e(c):ue()))));return L(()=>c?$e(c):u?r:d)}))),Jl=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,lk(n=>t(n).channel,r),k)),uae=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,ZH(n=>t(n).channel,r),k)),Vz=l(e=>Re(e[0]),(e,t)=>Jl(e,D,t)),fae=e=>k(jr(e.channel)),lae=e=>k(kH(e.channel)),pae=l(2,(e,t)=>hb(e,xb(t))),dae=l(2,(e,t)=>k(OH(e.channel,t))),mae=l(2,(e,t)=>e.channel.pipe(jr,RH(t),os(Oe),k)),hae=l(2,(e,t)=>Zz(e,{duration:t,orElse:()=>$a})),Zz=l(2,(e,t)=>{let r=ct(t.duration);if(!sn(r))return e;if(Sc(r))return En(t.orElse);let n=Symbol();return tW(En(()=>{let s=Kf().getRef(Tf),a=Nr(r),i,c=tn(!1);return Ok(or(e,(u,f)=>L(()=>(i=s.currentTimeMillisUnsafe()+a,c.openUnsafe(),u)).pipe(W(p=>(c.closeUnsafe(),i=void 0,p)),g)),$z(kt(function*(){for(;;)if(yield*c.await,!(i===void 0||(yield*mi(i-s.currentTimeMillisUnsafe()),i===void 0)||i-s.currentTimeMillisUnsafe()>0))return yield*yr(n)})),{haltStrategy:\"left\"})}),o=>o.reasons.find(a=>a._tag===\"Die\"&&a.defect===n)?t.orElse():Hz(o))}),xae=l(2,(e,t)=>k(Ue((r,n)=>W(we(jr(e.channel))(r,n),o=>{let s,a=kt(function*(){let i=yield*o,c=Oe(i);return s=(yield*Id(t))(i).pipe(jt(c),At(f=>(s=void 0,a))),c});return L(()=>s??a)})))),gae=e=>k(_H(e.channel)),yae=e=>Jl(e,Nu),Sae=e=>e.channel.pipe(jr,vH,k),Fu=l(2,(e,t)=>{let r=k(TH(uH(()=>bae(e,t))));return Yz.set(r,[e,t]),r}),Yz=new WeakMap;function*bae(e,t){let r=[t,e];for(;r.length>0;){let n=r.pop(),o=Yz.get(n);if(o!==void 0){r.push(o[1],o[0]);continue}let s=jz.get(n);if(s===void 0){yield n.channel;continue}try{r.push(s())}catch(a){r.push(zz(a))}yield Ou}}var Eae=l(2,(e,t)=>Fu(Nu(t),e)),Ok=l(e=>Re(e[0])&&Re(e[1]),(e,t,r)=>k(ub(bo(e),bo(t),r))),hb=l(2,(e,t)=>e.channel.pipe(YH(t),k)),Iae=l(2,(e,t)=>Ok(Gn(e,j),Gn(t,q))),wae=l(2,(e,t)=>hb(e,xb(t))),Aae=l(2,(e,t)=>hb(t,xb(e))),Cae=l(2,(e,t)=>Vz(Nu(e),t)),Tae=l(2,(e,t)=>Qz(e,t,(r,n)=>[r,n])),Qz=l(3,(e,t,r)=>Jl(e,n=>Gn(t,o=>r(n,o)))),hh=l(3,(e,t,r)=>En(()=>{let n=0,o=0;return Xz(e,t,(s,a)=>{let i=Math.min(s.length-n,a.length-o),c=ox(i,p=>r(s[n+p],a[o+p]));n+=i,o+=i;let u=n===s.length,f=o===a.length;return u&&(n=0),f&&(o=0),[c,u?[]:s,f?[]:a]})})),Xz=l(3,(e,t,r)=>k(ns(_e(function*(n,o){let s=yield*Bs(e.channel,o),a=yield*Bs(t.channel,o),i=kt(function*(){let p=yield*rr(s,o),d=yield*rr(a,o);return yield*xF([p,d])}),c,u;return kt(function*(){let[p,d]=c?[c,u??(yield*a)]:u?[yield*s,u]:yield*i,[m,h,y]=r(p,d);return c=yt(h)?h:void 0,u=yt(y)?y:void 0,m})})))),vae=l(2,(e,t)=>hh(e,t,(r,n)=>[r,n])),kae=l(2,(e,t)=>hh(e,t,r=>r)),Oae=l(2,(e,t)=>hh(e,t,(r,n)=>n)),_ae=l(2,(e,t)=>hh(e,t,(r,n)=>[...r,n])),Rae=e=>Gn(e,(t,r)=>[t,r]),Pae=e=>Uu(e,v,(t,r)=>{let n=0;t._tag===\"None\"&&(n=1,t=_(r[0]));let o=Qt();for(;nUu(e,v,(t,r)=>{let n=Qt();for(let o=0;oUu(e,()=>({prev:v(),current:v()}),(t,r)=>{let n=0,o;t.current._tag===\"None\"?(n=1,o=r[0],t.current=_(o)):o=t.current.value;let s=Qt();for(;nk(rb(()=>{let t=[],r=new Set,n=tn(),o=tn();return cb(ak(e.map((s,a)=>s.channel.pipe(jr,sb(i=>(t[a]=i,r.has(a)?g(Oe(t.slice())):(r.add(a),r.sizer.has(a)?ie:o.open)))),{concurrency:\"unbounded\",bufferSize:0}).pipe(gk(o.await))})),Nae=l(2,(e,t)=>_k(e,t)),Uae=l(3,(e,t,r)=>Gn(_k(e,t),([n,o])=>r(n,o))),eW=(...e)=>k(Ue((t,r)=>Y(()=>{let n,o=H0(e.map(s=>{let a=tr(r);return Bs(s.channel,a).pipe(C(i=>B0(g(i),i)),Dn(i=>i._tag===\"Success\"?n?Xe(a,i):(n=i.value[0],ie):Xe(a,i)),W(([,i])=>i))}));return L(()=>n??o)}))),Dae=l(2,(e,t)=>eW(e,t)),Lae=l(2,(e,t)=>k(MH(bo(e),t))),$ae=l(2,(e,t)=>k(FH(bo(e),t))),Kae=l(2,(e,t)=>k(NH(bo(e),t))),Bae=l(2,(e,t)=>k(UH(bo(e),t))),Rk=l(e=>Re(e[0]),_e(function*(e,t,r){let n=yield*zc,o=yield*Bs(e.channel,n),s=r?.capacity===\"unbounded\"?void 0:r?.capacity??Lz,a=yield*uo({capacity:s}),i=yield*uo({capacity:s});return yield*kt(function*(){for(;;){let c=yield*o,u=[],f=[];for(let d=0;d0){let d=Mg(a,f);d.length>0&&(p=yield*Uf(Vc(a,d)))}if(u.length>0){let d=Mg(i,u);d.length>0&&(yield*Vc(i,d))}p&&(yield*xi(p))}}).pipe(Lo(c=>(Si(a,c),Si(i,c),ie)),rr(n)),[a,i]})),ph=e=>k(Ue((t,r)=>jt(xr(r,fo(e)),Zc(e)))),jae=l(e=>Re(e[0]),(e,t,r)=>W(Rk(mh(e,n=>t(n),r),n=>n,r),([n,o])=>[ph(n),ph(o)])),Hae=l(e=>Re(e[0]),(e,t,r)=>W(Rk(e,t,{capacity:r?.capacity??16}),([n,o])=>[ph(n),ph(o)])),zae=l(2,(e,t)=>t.pipe(W(r=>r?e:$a),Vi)),Wae=l(2,_e(function*(e,t){let r,n=yield*Ek(e.channel),o=nt(n,c=>(r=c,$e(c))),[s,a]=yield*vg(c=>Dk(t,o,c)),i=r?$a:js(g(n));return a&&(i=Fu(dh(a),i)),[s,i]})),qae=l(2,(e,t)=>k(oz(e.channel,t))),Jae=l(2,(e,t)=>k(nz(e.channel,t))),tW=l(2,(e,t)=>e.channel.pipe(Wl(r=>t(r).channel),k)),Gae=l(2,(e,t)=>e.channel.pipe(LH(r=>t(r).channel),k)),rW=l(2,(e,t)=>e.channel.pipe(ab(t),k)),xh=l(2,(e,t)=>k(Da(e.channel,r=>t(r).channel)));var Pk=l(2,(e,t)=>e.channel.pipe(KH(t),k)),Vae=l(3,(e,t,r)=>{let n=Array.isArray(t)?o=>A(o,\"_tag\")&&t.includes(o._tag):Wt(t);return Pk(e,o=>n(o)?r(o):ie)}),Zae=l(2,(e,t)=>rW(e,r=>{let n=cd(r);return rt(n)?t(n.success):ie})),nW=l(e=>Re(e[0]),(e,t,r,n)=>k(BH(bo(e),t,o=>r(o).channel,n&&(o=>n(o).channel)))),Mk=l(e=>Re(e[0]),(e,t,r,n)=>k(jH(bo(e),t,o=>r(o).channel,n&&(o=>n(o).channel)))),Yae=l(e=>Re(e[0]),(e,t,r,n)=>{let o=Array.isArray(t)?s=>A(s,\"_tag\")&&t.includes(s._tag):Wt(t);return nW(e,o,r,n)}),Qae=l(e=>Re(e[0]),(e,t,r)=>{let n;return Mk(e,o=>(n??=Object.keys(t),A(o,\"_tag\")&&hg(o._tag)&&n.includes(o._tag)?j(o):q(o)),o=>t[o._tag](o),r)}),Xae=l(e=>Re(e[0]),(e,t,r,n,o)=>k(HH(bo(e),t,r,(s,a)=>n(s,a).channel,o&&((s,a)=>o(s,a).channel)))),eie=l(e=>Re(e[0]),(e,t,r,n)=>{let o=Object.create(null);for(let a of Object.keys(r)){let i=r[a];o[a]=(c,u)=>i(c,u).channel}let s=n&&((a,i)=>n(a,i).channel);return k(zH(e.channel,t,o,s))}),tie=l(2,(e,t)=>Mk(e,r=>Wt(r,t)&&A(r,\"reason\")?j(r.reason):q(r),ql)),oW=l(2,(e,t)=>k(WH(e.channel,t))),rie=l(3,(e,t,r)=>k($H(e.channel,t,n=>r(n).channel))),nie=l(3,(e,t,r)=>k(ib(e.channel,t,(n,o)=>r(n,o).channel))),oie=l(2,(e,t)=>k(CH(e.channel,r=>bo(t())))),sie=l(2,(e,t)=>xh(e,r=>Mu(t(r)))),aie=e=>k(qH(e.channel)),iie=l(e=>Re(e[0]),(e,t)=>k(JH(e.channel,t))),cie=l(e=>Re(e[0]),(e,t)=>k(GH(e.channel,t))),uie=l(2,(e,t)=>k(VH(e.channel,t))),Uz=(e,t)=>Vi(W(Fo(t),r=>{let n=gr.defaultValue(),o=()=>xh(Uk(e,gr,Y(()=>n)),s=>Vi(At(W(r(s),a=>(n=a,Vi(jt(kd,o())))),()=>g(ql(s)))));return o()})),fie=l(e=>Re(e[0]),(e,t,r)=>En(()=>{let n=r?.preventFallbackOnPartialStream??!1,o=0,s={attempt:0,stepIndex:0},a=Uk(gg,Y(()=>(s={attempt:s.attempt+1,stepIndex:o},s))),i=r?.onEvent===void 0?void 0:M0(r.onEvent,()=>s),c,u=i===void 0?D:d=>SW(bW(d,W(i.begin,m=>{c=m})),m=>L(()=>{if(c===void 0)return ie;let h=c;return c=void 0,i.end(h,m)})),f=v(),p=En(()=>{let d=t.steps[o];if(!d)return ql(sE(f));let m=a(u(IW(e,d.provide))),h=!1;if(Ce(f)){let y=f.value,S=!1,b=m;m=En(()=>S?b:(S=!0,ql(y))),m=Uz(m,vd(d,!1))}else{let y=vd(d,!0);m=y?Uz(m,y):m}return xh(n?EW(m,y=>(h=!0,ie)):m,y=>(o++,n&&h?ql(y):(f=_(y),p)))});return p})),lie=l(2,(e,t)=>{let r=It(t);return r===0?$a:sW(e,(n,o)=>o===r-1)}),pie=l(3,(e,t,r)=>En(()=>{let n=Dg(t),o=BigInt(0),s=!1;return Fu(iW(e,a=>{let i=o+BigInt(a.length);return i>n?(s=!0,!1):(o=i,!0)}),En(()=>s?r():$a))})),die=l(2,(e,t)=>{let r=It(t);return r===0?$a:Uu(e,xa,(n,o)=>(Md(n,o),n.length>r&&Og(n,n.length-r),[n,La]),{onHalt(n){return yi(n)}})}),sW=l(e=>Re(e[0]),(e,t,r)=>or(e,(n,o)=>Y(()=>{let s=0,a=!1;return C(L(()=>a?ue():n),c=>{let u=c.findIndex(f=>t(f,s++));if(u>=0){a=!0;let f=c.slice(0,r?.excludeLast?u:u+1);return yt(f)?g(f):ue()}return g(c)})}))),aW=l(e=>Re(e[0]),(e,t,r)=>or(e,(n,o)=>Y(()=>{let s=0,a=!1;return kt(function*(){if(a)return yield*ue();let i=yield*n;for(let c=0;cor(e,(r,n)=>Y(()=>{let o=0,s=!1,a=C(L(()=>s?ue():r),i=>{let c=[];for(let u=0;uor(e,(r,n)=>Y(()=>{let o=!1,s=C(L(()=>o?ue():r),a=>{let i=[];for(let c=0;caW(e,(r,n)=>W(t(r,n),o=>!o),{excludeLast:!0})),Fk=l(2,(e,t)=>{let r=It(t);return r===0?e:or(e,(n,o)=>Y(()=>{let s=0,a=n.pipe(C(i=>s>=r?g(i):(s+=i.length,s<=r?a:g(i.slice(r-s)))));return a}))}),xie=l(2,(e,t)=>Fk(cW(e,(r,n)=>!t(r,n)),1)),gie=l(2,(e,t)=>Fk(uW(e,(r,n)=>W(t(r,n),o=>!o)),1)),cW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=0,a=C(r,i=>{let c=i.findIndex(u=>!t(u,s++));return c===-1?a:(o=!1,g(i.slice(c)))});return L(()=>o?a:r)}))),yie=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=C(r,a=>{let i=a.findIndex(c=>ae(t(c)));return i===-1?s:(o=!1,g(a.slice(i)))});return L(()=>o?s:r)}))),uW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=0,a=kt(function*(){for(;;){let i=yield*r;for(let c=0;co?a:r)}))),Sie=l(2,(e,t)=>{let r=It(t);return r===0?e:or(e,(n,o)=>Y(()=>{let s=xa(),a=C(n,i=>{Md(s,i);let c=s.length-r,u=Jc(s,c);return Mr(u)?g(u):a});return a}))}),fW=e=>e.channel.pipe(os(Oe),k),lW=l(2,(e,t)=>(t=Xn(t),or(e,(r,n)=>Y(()=>{let o=Qt(),s=0,a,i;return L(function c(){if(i)return $e(i);if(a===void 0)return C(r,u=>{if(o.length===0&&u.length===t)return g(u);if(o.length+u.length{if(o.length===0)return $e(c);let u=o;return i=c,o=[],g(u)}))})))),bie=l(2,(e,t)=>pW(e,t,1)),pW=l(3,(e,t,r)=>{let n=Xn(t),o=Xn(r);return or(e,(s,a)=>Y(()=>{let i=null,c=xa(),u=!1,f=0,p=As(s,{onSuccess(d){if(Md(c,d),f>0){let h=c.length;Og(c,f),f=Math.max(0,f-h)}if(c.length=n;)if(n===o)m.push(Jc(c,n));else{m.push(SF(c,n));let h=c.length;Og(c,o),f=Math.max(0,o-h)}return g(m)},onFailure(d){return c.length===0||u&&c.length<=n-o?$e(d):(i=d,g(Oe(yi(c))))}});return L(()=>i?$e(i):p)}))}),Eie=l(2,(e,t)=>Uu(e,Qt,(r,n)=>{let o=Qt();for(let s=0;spk(jr(e.channel),jr(t.channel),r,n).pipe(os(Oe),k)),wie=l(4,(e,t,r,n)=>k(pk(e.channel,t.channel,r,n))),Aie=l(e=>Re(e[0]),(e,t,r,n)=>k(zl(e.channel,t,(o,s)=>{let a=Qt();for(let i=0;iRe(e[0]),(e,t,r,n)=>k(zl(e.channel,t,(o,s)=>{let[a,i]=r(o,s);return o=a,[o,yt(i)?Oe(i):La]},n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0))),La=Qt(),Cie=l(e=>Re(e[0]),(e,t,r,n)=>e.channel.pipe(jr,zl(t,(o,s)=>W(r(o,s),([a,i])=>[a,yt(i)?Oe(i):Qt()]),n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0),k)),Tie=l(e=>Re(e[0]),(e,t,r,n)=>e.channel.pipe(zl(t,(o,s)=>W(r(o,s),([a,i])=>[a,yt(i)?Oe(i):La]),n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0),k)),vie=l(3,(e,t,r)=>En(()=>{let n=t();return Fu(Mu(n),k(zl(e.channel,()=>n,(o,s)=>{let a=Qt();for(let i=0;iEn(()=>e.channel.pipe(jr,DH(t(),r),os(Oe),k))),Oie=l(2,(e,t)=>or(e,_e(function*(r,n){let o=yield*Tf,s=Nr(ct(t)),a,i,c=1/0,u=tn(),f=tn(),p=tn();yield*r.pipe(u.whenOpen,C(m=>(f.openUnsafe(),a=m,c=o.currentTimeMillisUnsafe()+s,ie)),ir({disableYield:!0}),Lo(m=>(i=m,c=o.currentTimeMillisUnsafe(),f.openUnsafe(),p.openUnsafe(),ie)),rr(n));let d=L(function m(){let h=o.currentTimeMillisUnsafe(),y=c{if(o.currentTimeMillisUnsafe(){if(i){if(a){let m=g(Oe(ax(a)));return a=void 0,m}return $e(i)}return u.openUnsafe(),f.whenOpen(d)})}))),dW=l(2,(e,t)=>{let r=t.burst??0;return t.strategy===\"enforce\"?_ie(e,t.cost,t.units,t.duration,r):Rie(e,t.cost,t.units,t.duration,r)}),_ie=(e,t,r,n,o)=>or(e,s=>qc(a=>{let i=Nr(ct(n)),c=r+o<0?Number.POSITIVE_INFINITY:r+o,u=r,f=a.currentTimeMillisUnsafe();return g(C(s,function p(d){return C(t(d),m=>{let h=a.currentTimeMillisUnsafe(),S=(h-f)/i,b=u+S*r,x=b<0?c:Math.min(b,c);return m<=x?(u=x-m,f=h,g(d)):C(s,p)})}))})),Rie=(e,t,r,n,o)=>or(e,s=>qc(a=>{let i=Nr(ct(n)),c=r+o<0?Number.POSITIVE_INFINITY:r+o,u=r,f=a.monotonicTimeNanosUnsafe();return g(C(s,p=>C(t(p),d=>{let m=a.monotonicTimeNanosUnsafe(),y=Number(m-f)/1e6/i,S=u+y*r,x=Math.min(S,c)-d;if(x>=0)return u=x,f=m,g(p);let w=-x/r,I=Math.max(0,w*i);return I>0?C(mi(I),()=>(u=x,f=m,g(p))):(u=x,f=m,g(p))})))})),Pie=l(2,(e,t)=>dW(e,{...t,cost:r=>g(t.cost(r))})),Mie=l(2,(e,t)=>fW(lW(e,t))),Fie=l(3,(e,t,r)=>Nk(e,Az(Xn(t)),O0(r))),Nie=l(e=>Re(e[0]),(e,t,r)=>mW(e,_e(function*(n,o,s){for(let a=0;aRe(e[0]),(e,t,r)=>En(()=>{let n=$c();return mW(e,_e(function*(o,s,a){for(let i=0;ikk(e,_e(function*(n,o,s){let a=yield*EF();yield*xr(o,fo(a));let i=$c(),c=yield*vz({lookup:u=>Wc(uo({capacity:r?.bufferSize??4096}).pipe(Yr(f=>(Kc(i,u,f),Ln(a,[u,ph(f)])))),f=>(ci(i,u),aw(f))),idleTimeToLive:r?.idleTimeToLive??ra}).pipe(Ss(s));return yield*No({while:Cn,body:gt(C(n,u=>t(u,c,i))),step:zr}).pipe(nt(u=>{for(let[,f]of i)Nd(f);return cr(a,u)}),rr(o)),Zc(a)})),Die=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o,s,a=Qt(),i=r.pipe(C(u=>{for(let f=0;fc?$e(c):i),u=>{if(c=u,s===void 0)return $e(u);let f=Oe([o,s]);return s=void 0,g(f)})}))),Lie=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o,s,a=L(()=>{if(s!==void 0){let c=s;return s=void 0,g(c)}return r}).pipe(Uo(c=>(o=la(c),ue()))),i=W(L(()=>t.transform(a,n)),([c,u])=>(s=u,Oe(c)));return L(()=>o||i)}))),$ie=l(2,(e,t)=>Nk(e,t,Ad)),Nk=l(3,(e,t,r)=>k(ns(_e(function*(n,o,s){let a=yield*Bs(e.channel,o),i=tn(!1),c=Symbol(),u=yield*uo({capacity:0});yield*a.pipe(i.whenOpen,C(T=>(i.closeUnsafe(),Ln(u,T))),ir,nt(T=>cr(u,T)),rr(s));let f=yield*Tf,p=yield*Lc(r),d=tn(!1),m=f.currentTimeMillisUnsafe(),h=0,y=v(),S,b=T=>(d.openUnsafe()&&(h=f.currentTimeMillisUnsafe()),g(T)),x=d.await.pipe(C(()=>p(m,y)),C(([,T])=>mi(T)),C(()=>Ln(u,c)),At(()=>aw(u)),C(()=>Bc)),w=L(()=>{if(S!==void 0){let T=S;return S=void 0,b(T)}return u.state._tag===\"Open\"&&i.openUnsafe(),C(ga(u),T=>T===c?ue():b(T))}),I=C(([T,P])=>{if(d.isOpen())m+=f.currentTimeMillisUnsafe()-h;else if(u.state._tag===\"Done\")return ue();return y=_(T),S=P,g(Oe(T))});return L(()=>{if(u.state._tag===\"Done\"&&S===void 0)return u.state.exit;d.closeUnsafe();let T=I(L(()=>Dk(t,w,s)));return u.state._tag===\"Open\"?Nf(T,x):T})})))),Kie=l(2,_e(function*(e,t){let r=It(t.n),n=yield*Bie(t),o=new Array(r),s=yield*Vr;for(let a=0;aXe(i,u)),k)}return yield*Gi(e.channel,a=>XS(n,a)).pipe(Dn(a=>QS(n,a)),Df),o})),Bie=e=>Wc(e.capacity===\"unbounded\"?YS(e):e.strategy===\"dropping\"?VS(e):e.strategy===\"sliding\"?ZS(e):GS(e),sh),hW=l(2,(e,t)=>W(CW(e,t),Wz)),jie=l(2,(e,t)=>W(Mz({acquire:hW(e,t),idleTimeToLive:t.idleTimeToLive}),r=>Vi(Fz(r)))),Hie=l(2,(e,t)=>k(fb(e.channel,t))),zie=l(2,(e,t)=>k(mk(e.channel,t))),Wie=l(2,(e,t)=>e.channel.pipe(mk(wz(t)),AH(([r,n])=>n?nb(n):Ou),k)),qie=e=>mb(AW(e)),Jie=e=>Uu(e,Qt,(t,r)=>{let n=mE(t,r);return[n,[n]]}),Gie=e=>xW(e,Z),xW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s;return C(r,function a(i){let c=[],u=0;for(o&&(o=!1,s=i[0],u=1,c.push(s));uor(e,(r,n)=>Y(()=>{let o=!0,s;return C(r,_e(function*a(i){let c=[],u=0;for(o&&(o=!1,s=i[0],u=1,c.push(s));uRe(e[0]),(e,t)=>e.channel.pipe(fb(XH(t?.encoding)),k)),Yie=e=>En(()=>{let t=new TextEncoder;return Gn(e,r=>t.encode(r))}),Qie=e=>e.channel.pipe(fb(QH()),k),gW=l(2,(e,t)=>Jz(e,(r,n)=>{let o=n===0?[]:[t],s=r.length-1;for(let a=0;aMu(t.start).pipe(Fu(gW(e,t.middle)),Fu(Mu(t.end)))),ece=l(2,(e,t)=>yW(e,t,Nu(E_([!0,!1])))),yW=l(3,(e,t,r)=>k(Ue(_e(function*(n,o){let s=yield*we(jr(r.channel))(n,o),a=Symbol(),i=!1,c=!1,u=(yield*we(jr(e.channel))(n,o)).pipe(At(()=>(i=!0,g(a)))),f=(yield*we(jr(t.channel))(n,o)).pipe(At(()=>(c=!0,g(a))));return kt(function*(){for(;;){if(i&&c)return yield*ue();let p=yield*s;if(p&&i||!p&&c)continue;let d=yield*p?u:f;if(d!==a)return Oe(d)}})})))),tce=l(2,(e,t)=>k(gk(e.channel,t))),rce=l(2,(e,t)=>k(sz(e.channel,t))),SW=l(2,(e,t)=>k(uh(e.channel,t))),nce=l(2,(e,t)=>k(az(e.channel,t))),bW=l(2,(e,t)=>k(iz(e.channel,t))),EW=l(2,(e,t)=>k(yk(e.channel,r=>t(r[0])))),oce=l(2,(e,t)=>k(cz(e.channel,t))),sce=l(2,(e,t)=>k(uz(e.channel,t))),IW=l(e=>Re(e[0]),(e,t,r)=>k(fz(e.channel,t,r))),ace=l(2,(e,t)=>k(lb(e.channel,t))),ice=l(3,(e,t,r)=>k(pb(e.channel,t,r))),Uk=l(3,(e,t,r)=>k(db(e.channel,t,r))),wW=l(2,(e,t)=>k(lz(e.channel,t))),cce=l(3,(e,t,r)=>wW(e,n=>dr(n,t,r(Me(n,t))))),uce=function(){let e=Re(arguments[0]),t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return k(Sk(n.channel,t,r))}return n=>k(Sk(n.channel,t,r))},fce=Mu({}),lce=l(3,(e,t,r)=>Gn(e,n=>({...n,[t]:r(n)})));var pce=l(e=>Re(e[0]),(e,t,r,n)=>Jl(e,o=>Gn(r(o),s=>({...o,[t]:s})),n)),dce=l(e=>Re(e[0]),(e,t,r,n)=>mh(e,o=>W(r(o),s=>({...o,[t]:s})),n)),mce=l(2,(e,t)=>Gn(e,r=>({[t]:r}))),hce=l(2,(e,t)=>vg(r=>Bs(e.channel,r).pipe(C(n=>Dk(t,n,r)),W(([n])=>n)))),Dk=(e,t,r)=>xk(e.transform(hk(t),r)),AW=e=>Pu(e.channel,()=>[],(t,r)=>{for(let n=0;nPu(e.channel,()=>0,(t,r)=>t+r.length),gce=e=>Pu(e.channel,()=>0,(t,r)=>{for(let n=0;nPu(e.channel,t,(n,o)=>{for(let s=0;sxz(e.channel,t,(n,o)=>{let s=0,a=n;return W(No({while:()=>sr(a,o[s]),step(i){a=i,s++}}),()=>a)})),bce=e=>W(mz(e.channel),Vt(k_(0))),Ece=e=>W(hz(e.channel),Vt(ax)),Ice=l(2,(e,t)=>Gi(e.channel,r=>{let n=0;return No({while:()=>nt(r[n++]),step:zr})})),wce=l(2,(e,t)=>dz(e.channel,r=>{let n=!1,o=0;return W(No({while:()=>!n&&ot(r[o]),step(s){o++,s||(n=!0)}}),()=>!n)})),Ace=l(2,(e,t)=>Gi(e.channel,t)),xb=e=>pz(e.channel),Cce=e=>Ek(e.channel),Tce=e=>Pu(e.channel,()=>\"\",(t,r)=>t+r.join(\"\")),vce=e=>W(bk(e.channel),t=>t.buffer),kce=e=>bk(e.channel),Lk=l(e=>Re(e[0]),(e,t,r)=>{let n,o,s=!1,a=tn(!1),i=r?.signal,c=()=>o.interruptUnsafe();return new ReadableStream({start(u){o=Rd(ao(Gi(rn(e.channel,f=>g(a.whenOpen(f))),f=>Y(()=>{a.closeUnsafe();for(let p=0;p{i?.removeEventListener(\"abort\",c),!s&&(f._tag===\"Failure\"&&i?.aborted!==!0?u.error(rg(f.cause)):u.close())}),i!==void 0&&o.pollUnsafe()===void 0&&(i.aborted?c():i.addEventListener(\"abort\",c,{once:!0}))},pull(){return new Promise(u=>{n=u,a.openUnsafe()})},cancel(){if(o)return s=!0,Y0(pi(Ko(o)))}},r?.strategy)}),Oce=l(e=>Re(e[0]),(e,t)=>Lk(e,Pr(),t)),_ce=l(e=>Re(e[0]),(e,t)=>W(Hc(),r=>Lk(e,r,t))),$k=l(2,(e,t)=>({[Symbol.asyncIterator](){let r=Q0(t),n=co(t),o=oo(),s,a,i,c,u=p=>{if(c)return c;let d=i;return c=r(jt(Zr(d?Ko(d):ie,Xe(o,p)),{done:!0,value:void 0})),c},f=async p=>{try{await u(p)}catch(d){await r(X0(\"Suppressed error while closing Stream async iterator\",d))}};return{async next(){if(c)return c;if(a){let m=a.next();if(!m.done)return m;a=void 0}let p=n(s??C(Bs(e.channel,o),m=>(s=m,m)));i=p;let d=await r(hF(p));if(i===p&&(i=void 0),ut(d))return a=d.value[Symbol.iterator](),a.next();if(Is(d.cause))return u(Bt);if(c&&e0(d.cause))return c;throw await f(d),rg(d.cause)},return(){return u(Bt)},async throw(p){throw await f(a0(p)),p}}}})),Rce=e=>W(Hc(),t=>$k(e,t)),Pce=e=>$k(e,Pr()),Mce=l(e=>Re(e[0]),(e,t,r)=>wk(e.channel,t,r)),Fce=l(2,(e,t)=>Sz(e.channel,t)),CW=l(2,(e,t)=>bz(e.channel,t)),Nce=l(2,(e,t)=>gz(e.channel,t)),Uce=l(2,(e,t)=>Ik(e.channel,t));var Kk=Et(\"effect/FileSystem\");var vW=Et(\"effect/Path\");function gh(e){return{_tag:\"Value\",value:e}}function yb(e,t){return{_tag:\"Record\",keys:e,value:t}}function zk(e,t){return{_tag:\"Array\",length:e,value:t}}var gb=class extends Ut(\"SourceError\"){},Du=Te(\"effect/ConfigProvider\",{defaultValue:()=>FW()}),Dce={...kr,toJSON(){return{_id:\"ConfigProvider\"}}},Lce=e=>e;function OW(e,t){let r=Object.create(Dce);return r.load=e,r.mapInput=t,r}function _W(e,t){return OW(r=>e(t(r)),r=>_W(e,n=>r(t(n))))}function RW(e,t){return OW(r=>C(e.load(r),n=>n!==void 0?g(n):t.load(r)),r=>RW(e.mapInput(r),t.mapInput(r)))}function Sb(e){return _W(e,Lce)}var jk=l(2,(e,t)=>RW(e,t)),Wk=l(2,(e,t)=>e.mapInput(t)),$ce=Wk(e=>e.map(t=>typeof t==\"number\"?t:B1(t))),Kce=l(2,(e,t)=>{let r=typeof t==\"string\"?[t]:t;return Wk(e,n=>[...r,...n])}),Bce=e=>ws(e)?pa(Du)(e):x1(Du)(e),jce=(e,t)=>pa(Du)(kt(function*(){let r=yield*Du,n=ws(e)?yield*e:e;return t?.asPrimary?jk(n,r):jk(r,n)}));function Hce(e,t){let r=t?.preserveEmptyStrings===!0;return Sb(n=>g(zce(e,n,r)))}function zce(e,t,r){let n=e;for(let o of t){if(n==null)return;if(Array.isArray(n)){if(typeof o!=\"number\"||!Number.isInteger(o)||o<0||o>=n.length)return;n=n[o];continue}if(fr(n)){if(typeof o!=\"string\"||!Object.hasOwn(n,o))return;n=n[o];continue}return}return Wce(n,r)}function Wce(e,t){if(e!=null)return typeof e==\"string\"?PW(e,t):typeof e==\"number\"||typeof e==\"boolean\"||typeof e==\"bigint\"?gh(String(e)):Array.isArray(e)?zk(e.length):fr(e)?yb(new Set(Object.keys(e))):gh(K(e))}function PW(e,t){let r=MW(e,t);return r===void 0?void 0:gh(r)}function MW(e,t){return e===\"\"&&!t?void 0:e}function qk(e,t){let r=t?.preserveEmptyStrings===!0,n=qce(e);return Sb(o=>g(Jce(n,e,o,r)))}function FW(e){let t=e?.env??{...globalThis.process?.env,...import.meta?.env};return qk(t,{preserveEmptyStrings:e?.preserveEmptyStrings})}function qce(e){let t={};for(let[r,n]of Object.entries(e)){if(n===void 0)continue;let o=r.split(\"_\"),s=t;for(let a of o){let i=s.children??=Object.create(null);s=i[a]??={}}}return t}function Jce(e,t,r,n){let o=r.map(String).join(\"_\"),s=MW(Object.hasOwn(t,o)?t[o]:void 0,n),a=Gce(e,r),i=a?.children?Object.keys(a.children):[];if(i.length===0)return s===void 0?void 0:gh(s);if(i.every(nf)){let u=Math.max(...i.map(f=>parseInt(f,10)))+1;return zk(u,s)}return yb(new Set(i),s)}function Gce(e,t){if(t.length===0)return e;let r=e;for(let n of t)if(r=r?.children?.[String(n)],!r)return;return r}function NW(e,t){let r=Zce(e);return t?.expandVariables&&(r=Yce(r)),qk(r,{preserveEmptyStrings:t?.preserveEmptyStrings})}var Vce=/(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg;function Zce(e){let t=Object.create(null);e=e.replace(/\\r\\n?/gm,`\n`);let r;for(;(r=Vce.exec(e))!=null;){let n=r[1],o=r[2]||\"\";o=o.trim();let s=o[0];o=o.replace(/^(['\"`])([\\s\\S]*)\\1$/gm,\"$2\"),s==='\"'&&(o=o.replace(/\\\\n/g,`\n`),o=o.replace(/\\\\r/g,\"\\r\")),t[n]=o}return t}function Yce(e){let t=Object.create(null);for(let r of Object.keys(e))t[r]=Hk(e[r],e,new Set([r])).replace(/\\\\\\$/g,\"$\");return t}function Hk(e,t,r){let n=/\\${?(\\w+)/g,o=\"\",s=0,a;for(;(a=n.exec(e))!=null;){if(a.index>0&&e[a.index-1]===\"\\\\\")continue;let[,i]=a,c=n.lastIndex,u=\"\";if(e.startsWith(\":-\",c)){c+=2;let p=c,d=0;for(;c{let a=t.join(n,...s.map(String)),i=r.readFileString(a).pipe(W(u=>PW(u.trim(),o))),c=r.readDirectory(a).pipe(W(u=>yb(new Set(u.map(f=>t.basename(f))))));return i.pipe(Uo(u=>c.pipe(Uo(f=>Bk(u)&&Bk(f)?g(void 0):F(Bk(u)?f:u)))),Do(u=>new gb({message:`Failed to read file at ${t.join(n,...s.map(String))}`,cause:u})))})}),Bk=e=>e.reason._tag===\"NotFound\";var UW=[\"All\",\"Fatal\",\"Error\",\"Warn\",\"Info\",\"Debug\",\"Trace\",\"None\"];var Gk=\"~effect/Config\",$W=e=>A(e,Gk),Vl=class{_tag=\"ConfigError\";name=\"ConfigError\";cause;constructor(t){this.cause=t}get message(){return this.cause.toString()}toString(){return`ConfigError(${this.message})`}},eue={...Lh({label:\"Config\",evaluate(e){return this.parse(e.getRef(Du))}}),[Gk]:Gk,toJSON(){return{_id:\"Config\"}}};function zs(e){let t=Object.create(eue);return t.evaluator=e,t.parse=r=>Ct(e(r,[]),jc),t}var ss=(e,t,r)=>e.evaluator(t,r),KW=l(2,(e,t)=>zs((r,n)=>W(ss(e,r,n),sr(t)))),tue=l(2,(e,t)=>zs((r,n)=>C(ss(e,r,n),mr({onSuccess:o=>ss(t(o),r,n),onFailure:o=>g(q(o))})))),rue=l(2,(e,t)=>zs((r,n)=>C(ss(e,r,n),o=>rt(o)?fn(t(o.success),j):g(q(o.failure))))),nue=l(2,(e,t)=>zs((r,n)=>As(ss(e,r,n),{onFailure:o=>{let s=r0(o);return Ce(s)&&o.reasons.every(ai)?ss(t(s.value),r,n):$e(o)},onSuccess:o=>ae(o)?ss(t(o.failure),r,n):g(o)})));function BW(e){let t=globalThis.Array.isArray(e)?e:Symbol.iterator in e?[...e]:e;return zs((r,n)=>globalThis.Array.isArray(t)?fn(Eg(t.map(o=>ss(o,r,n))),pE):fn(Eg(gc(t,o=>ss(o,r,n))),pE))}var jW=l(2,(e,t)=>zs((r,n)=>fn(ss(e,r,n),o=>ae(o)?j(t):o))),oue=e=>e.pipe(KW(_),jW(v())),HW=e=>$W(e)?e:BW(gc(e,t=>HW(t))),sue=e=>Wt(e,\"SourceError\"),aue=()=>\"\",zW=e=>t=>nt(t,r=>$e(gs(r.reasons.map(e)))),WW=(e,t)=>e.load(t).pipe(zW(r=>ai(r)?Cf(r.error).annotate(ng(r)):r),fn(r=>({provider:e,path:t,node:r,toString:aue}))),LW=(e,t)=>WW(e.provider,[...e.path,t]),Jk=(e,t)=>Oa(Jo,e,new Ke(Rt(r=>t(r)),hn())),qW=e=>{switch(e._tag){case\"Union\":return e.types.every(qW);case\"Objects\":case\"Arrays\":case\"Suspend\":return!1;default:return!0}},Vk=(e,t)=>{switch(e._tag){case\"Objects\":return t?._tag===\"Record\";case\"Arrays\":return t?._tag===\"Array\";case\"Union\":return e.types.some(r=>Vk(r,t));case\"Suspend\":return Vk(e.thunk(),t);default:return t?.value!==void 0}},iue=on(e=>{let t=new WeakSet,r=dl(n=>{switch(t.add(n),n._tag){case\"Objects\":{let o=_e(function*(s){if(s.node?._tag!==\"Record\")return;let a=s.node,i=new Set;for(let u of n.propertySignatures)typeof u.name==\"string\"&&i.add(u.name);if(n.indexSignatures.length>0){let u={};for(let f of a.keys)B(u,f,void 0);for(let f of n.indexSignatures)for(let p of Ms(u,f.parameter))typeof p==\"string\"&&i.add(p)}let c={};for(let u of i){let f=yield*LW(s,u);f.node!==void 0&&B(c,u,f)}return c});return Jk(n.recur(r,s=>s),o)}case\"Arrays\":{let o=_e(function*(s){if(s.node?._tag!==\"Array\")return;let a=[];for(let i=0;ig(o.node?.value))});return r(e)});function Tr(e,t){let r=oh(e),n=gn(r.ast),o=St(Q(iue(r.ast))),s=typeof t==\"string\"?[t]:t??[];return zs((a,i)=>{let c=[...i,...s];return WW(a,c).pipe(Ct(u=>o(u).pipe(fn(j),$f(f=>{let p=new Vl(new Ma(c.length>0?new Ot(c,f):f));return Vk(n,u.node)?F(p):g(q(p))}))),zW(u=>QI(u)&&sue(u.defect)?Af(new Vl(u.defect)).annotate(ng(u)):u))})}var cue=en.check(Ls({minimum:1,maximum:65535})),uue=Jn(UW),JW=e=>Wr(e)||globalThis.Array.isArray(e);function fue(e){return zs(()=>F(new Vl(e)))}function lue(e){return zs(()=>g(j(e)))}function pue(e){return Tr(H,e)}function due(e){return Tr(th,e)}function mue(e){return Tr(wu,e)}function hue(e){return Tr(Ul,e)}function xue(e){return Tr(en,e)}function gue(e,t){return Tr(zt(e),t)}function yue(e,t){return Tr(Jn(e),t)}function Sue(e,t,r){let n=JW(t),o=n?r:t,s=Be(e),a=o?.separator??\",\",i=H.pipe(J(oh(s),{decode:q2(o),encode:Iy(hn({strict:!1}),le(c=>c.join(a)))}));return Tr(st([i,s]),n?t:void 0)}function bue(e,t,r,n){let o=JW(r),s=Na(e,t),a=pD(o?n:r),i=H.pipe(J(oh(s),{decode:a.decode,encode:Iy(hn({strict:!1}),a.encode)}));return Tr(st([s,i]),o?r:void 0)}function Eue(e){return Tr(Sv,e)}function Iue(e){return Tr(Rv,e)}function wue(e){return Tr($l,e)}function Aue(e){return Tr(cue,e)}function Cue(e){return Tr(uue,e)}function Tue(e){return Tr(KS(H),e)}function vue(e){return Tr(LS,e)}function kue(e){return Tr(Dl,e)}var Oue=l(2,(e,t)=>zs((r,n)=>ss(e,r,[...n,t])));var Lu={};An(Lu,{Console:()=>GW,assert:()=>_ue,clear:()=>Rue,consoleWith:()=>ur,count:()=>Pue,countReset:()=>Mue,debug:()=>Fue,dir:()=>Nue,dirxml:()=>Uue,error:()=>Due,group:()=>Lue,info:()=>$ue,log:()=>Kue,table:()=>Bue,time:()=>jue,timeLog:()=>Hue,trace:()=>zue,warn:()=>Wue,withGroup:()=>que,withTime:()=>Jue});var GW=qI,ur=e=>se(t=>e(t.getRef(GW))),_ue=(e,...t)=>ur(r=>X(()=>{r.assert(e,...t)})),Rue=ur(e=>X(()=>{e.clear()})),Pue=e=>ur(t=>X(()=>{t.count(e)})),Mue=e=>ur(t=>X(()=>{t.countReset(e)})),Fue=(...e)=>ur(t=>X(()=>{t.debug(...e)})),Nue=(e,t)=>ur(r=>X(()=>{r.dir(e,t)})),Uue=(...e)=>ur(t=>X(()=>{t.dirxml(...e)})),Due=(...e)=>ur(t=>X(()=>{t.error(...e)})),Lue=e=>ur(t=>kc(X(()=>{e?.collapsed?t.groupCollapsed(e.label):t.group(e?.label)}),()=>X(()=>{t.groupEnd()}))),$ue=(...e)=>ur(t=>X(()=>{t.info(...e)})),Kue=(...e)=>ur(t=>X(()=>{t.log(...e)})),Bue=(e,t)=>ur(r=>X(()=>{r.table(e,t)})),jue=e=>ur(t=>kc(X(()=>{t.time(e)}),()=>X(()=>{t.timeEnd(e)}))),Hue=(e,...t)=>ur(r=>X(()=>{r.timeLog(e,...t)})),zue=(...e)=>ur(t=>X(()=>{t.trace(...e)})),Wue=(...e)=>ur(t=>X(()=>{t.warn(...e)})),que=l(e=>de(e[0]),(e,t)=>ur(r=>nd(X(()=>{t?.collapsed?r.groupCollapsed(t.label):r.group(t?.label)}),()=>e,()=>X(()=>{r.groupEnd()})))),Jue=l(e=>de(e[0]),(e,t)=>ur(r=>nd(X(()=>{r.time(t)}),()=>e,()=>X(()=>{r.timeEnd(t)}))));var In={OK:200,Unauthorized:401,NotFound:404,InternalServerError:500,ServiceUnavailable:503},Zk={[In.OK]:\"OK\",[In.Unauthorized]:\"Unauthorized\",[In.NotFound]:\"Not Found\",[In.InternalServerError]:\"Internal Server Error\",[In.ServiceUnavailable]:\"Service Unavailable\"},Gue=e=>{let t=e.startsWith(\"/\"),r=[];for(let o of e.split(\"/\"))if(!(o===\"\"||o===\".\")){if(o===\"..\"){r.length>0&&r.at(-1)!==\"..\"?r.pop():t||r.push(\"..\");continue}r.push(o)}let n=r.join(\"/\");return t?`/${n}`:n||\".\"},Zi=(...e)=>Gue(e.filter(Boolean).join(\"/\")),Zl=e=>{if(e.length===0)return\".\";let t=e.length;for(;t>1&&e[t-1]===\"/\";)t-=1;let r=e.slice(0,t),n=r.lastIndexOf(\"/\");return n<0?\".\":n===0?\"/\":r.slice(0,n)},VW=e=>{if(!e.startsWith(\"/\"))throw new TypeError(\"Path must be absolute\");let t=new URL(\"file:///\");return t.pathname=e.replace(/%/g,\"%25\").replace(/\\\\/g,\"%5C\"),t};var Vue=/^[A-Za-z0-9_-]+$/u,ZW=/[*?[{]/u,bb=(e,t)=>t===e||t.startsWith(`${e.replace(/\\/+$/u,\"\")}/`),Yl=class extends an.TaggedError(\"FunctionFileSystemError\"){},Eo=(e,t)=>e.lstat(t).pipe($.catch(()=>$.undefined)),$u=(e,t,r)=>$.all([e.realPath(t),e.realPath(r)],{concurrency:2}).pipe($.map(([n,o])=>bb(n,o)),$.orElseSucceed(()=>!1)),YW=(e,t,r)=>$.gen(function*(){let n=yield*Eo(e,r);if(n===void 0)return!0;if(n.isSymbolicLink||!(yield*$u(e,t,r)))return!1;if(!n.isDirectory)return!0;let o=yield*e.readDirectory(r).pipe($.catch(()=>$.undefined));if(o===void 0)return!1;for(let s of o)if(!(yield*YW(e,t,Zi(r,s))))return!1;return!0}),yh=(e,t)=>t.length===0?\"\":t.startsWith(\"/\")?t:Zi(e,t),Yk=[\"deno.json\",\"deno.jsonc\"],QW=e=>Yk.includes(e.slice(e.lastIndexOf(\"/\")+1)),Zue=(e,t,r)=>$.gen(function*(){let n=Zl(Zi(r));for(;bb(t,n);){for(let s of Yk){let a=Zi(n,s),i=yield*Eo(e,a);if(i!==void 0)return i.isFile&&!i.isSymbolicLink?a:void 0}let o=Zl(n);if(o===n)break;n=o}}),Yue=(e,t,r)=>$.all([e.realPath(t),e.realPath(r)],{concurrency:2}).pipe($.map(([n,o])=>n===o),$.orElseSucceed(()=>!1)),XW=$.fn(\"Functions.resolveFunctionConfig\")(function*(e){let{root:t,slug:r,overrides:n,fs:o}=e;if(!t.startsWith(\"/\")||!Vue.test(r)||r===\"_shared\"||(yield*Eo(o,t))===void 0)return;let a=yield*o.realPath(t).pipe($.orElseSucceed(()=>\"\"));if(!a.startsWith(\"/\"))return;let i=yield*Eo(o,a);if(i===void 0||!i.isDirectory)return;let c=e.filesRoot===void 0?a:yield*o.realPath(e.filesRoot).pipe($.orElseSucceed(()=>\"\"));if(!c.startsWith(\"/\")||!bb(c,a))return;let u=n.$default,f=n[r],p={...u,...f};if(p.enabled===!1)return;let d=Zi(a,r),m=p?.entrypointPath&&p.entrypointPath.length>0?p.entrypointPath:p.entrypoint&&p.entrypoint.length>0?p.entrypoint:\"index.ts\";if(!m.startsWith(\"/\")){let P=yield*Eo(o,d);if(P===void 0||!P.isDirectory||!(yield*$u(o,a,d)))return}let h=yh(d,m);if(!(yield*$u(o,c,h)))return;let y=yield*Eo(o,h);if(y===void 0||!y.isFile||y.isSymbolicLink)return;let S=f?.importMapPath??f?.import_map,b=u?.importMapRoot??u?.import_map_root,x=S!==void 0?yh(d,S):b!==void 0?yh(a,b):yh(d,\"\");if(x.length>0){if(!(yield*$u(o,c,x)))return;let P=yield*Eo(o,x);if(P===void 0||!P.isFile||P.isSymbolicLink)return}else for(let P of Yk){let G=Zi(d,P),he=yield*Eo(o,G);if(he!==void 0){if(!he.isFile||he.isSymbolicLink||!(yield*$u(o,c,G)))return;x=G;break}}let w=x.length===0?void 0:yield*Zue(o,c,h),I=w!==void 0&&(yield*Yue(o,w,x)),T=(p.staticFiles??p.static_files??[]).map(P=>yh(d,P));for(let P of T){if(!bb(c,P))return;let G=P.search(ZW),he=G<0?P:P.slice(0,G),me=G<0?Zl(P):he.slice(0,Math.max(0,he.lastIndexOf(\"/\")))||a;if(!(yield*YW(o,c,me)))return;if(!ZW.test(P)){let E=yield*Eo(o,P);if(E!==void 0&&(!(yield*$u(o,c,P))||E.isSymbolicLink))return}}return{entrypointPath:h,importMapPath:x,importMapDiscoveredByRuntime:I,staticFiles:T,verifyJWT:p.verifyJWT??p.verify_jwt??!0,env:{...u?.env,...f?.env}}}),Que=e=>Zi(Zl(e.entrypointPath),\"package.json\"),eq=e=>{let t=new Map,r=new Map;return(n,o)=>{let s=r.get(n);if(s!==void 0)return s;let a=Zl(o.entrypointPath),i=t.get(a),c=i===void 0||i===n?a:e();return i===void 0&&t.set(a,n),r.set(n,c),c}},tq=$.fn(\"Functions.packageJsonContainedFor\")(function*(e){if(!e.root.startsWith(\"/\"))return!1;let t=yield*Eo(e.fs,e.root);if(t===void 0||!t.isDirectory&&!t.isSymbolicLink)return!1;let r=yield*e.fs.realPath(e.root).pipe($.orElseSucceed(()=>\"\"));if(!r.startsWith(\"/\"))return!1;let n=yield*Eo(e.fs,r);if(n===void 0||!n.isDirectory)return!1;let o=Que(e.config),s=yield*Eo(e.fs,o);return s===void 0||!s.isFile||s.isSymbolicLink?!1:yield*$u(e.fs,r,o)});var Qk=new TextEncoder,Sh=new TextDecoder,Eb=new TextDecoder(\"utf-8\",{fatal:!0}),rbe=2**32;function rq(...e){let t=e.reduce((o,{length:s})=>o+s,0),r=new Uint8Array(t),n=0;for(let o of e)r.set(o,n),n+=o.length;return r}function Ql(e){let t=new Uint8Array(e.length);for(let r=0;r127)throw new TypeError(\"non-ASCII string encountered in encode()\");t[r]=n}return t}var Ib=(e,t=\"algorithm.name\")=>new TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`);function Xue(e,t){if(t&&!e.usages.includes(t))throw new TypeError(`CryptoKey does not support this operation, its usages must include ${t}.`)}function nq(e,t){let{modulusLength:r}=t.algorithm;if(typeof r!=\"number\"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}function oq(e,t,r){let n=e.algorithm;if(n.name!==t.name)throw Ib(t.name);if(t.hash&&n.hash?.name!==t.hash)throw Ib(t.hash,\"algorithm.hash\");if(t.namedCurve&&n.namedCurve!==t.namedCurve)throw Ib(t.namedCurve,\"algorithm.namedCurve\");if(t.length!==void 0&&n.length!==t.length)throw Ib(t.length,\"algorithm.length\");Xue(e,r)}function efe(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(\", \")}, or ${n}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t==\"function\"&&t.name?e+=` Received function ${t.name}`:typeof t==\"object\"&&t!=null&&t.constructor?.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var bh=(e,t,...r)=>efe(`Key for the ${e} algorithm must be `,t,...r);var Hr=class extends Error{static code=\"ERR_JOSE_GENERIC\";code=\"ERR_JOSE_GENERIC\";constructor(t,r){super(t,r),this.name=this.constructor.name,Error.captureStackTrace?.(this,this.constructor)}},Ka=class extends Hr{static code=\"ERR_JWT_CLAIM_VALIDATION_FAILED\";code=\"ERR_JWT_CLAIM_VALIDATION_FAILED\";claim;reason;payload;constructor(t,r,n=\"unspecified\",o=\"unspecified\"){super(t,{cause:{claim:n,reason:o,payload:r}}),this.claim=n,this.reason=o,this.payload=r}},Eh=class extends Hr{static code=\"ERR_JWT_EXPIRED\";code=\"ERR_JWT_EXPIRED\";claim;reason;payload;constructor(t,r,n=\"unspecified\",o=\"unspecified\"){super(t,{cause:{claim:n,reason:o,payload:r}}),this.claim=n,this.reason=o,this.payload=r}},wb=class extends Hr{static code=\"ERR_JOSE_ALG_NOT_ALLOWED\";code=\"ERR_JOSE_ALG_NOT_ALLOWED\"},as=class extends Hr{static code=\"ERR_JOSE_NOT_SUPPORTED\";code=\"ERR_JOSE_NOT_SUPPORTED\"};var wn=class extends Hr{static code=\"ERR_JWS_INVALID\";code=\"ERR_JWS_INVALID\"},Xl=class extends Hr{static code=\"ERR_JWT_INVALID\";code=\"ERR_JWT_INVALID\"};var Ih=class extends Hr{static code=\"ERR_JWKS_INVALID\";code=\"ERR_JWKS_INVALID\"},ep=class extends Hr{static code=\"ERR_JWKS_NO_MATCHING_KEY\";code=\"ERR_JWKS_NO_MATCHING_KEY\";constructor(t=\"no applicable key found in the JSON Web Key Set\",r){super(t,r)}},Ab=class extends Hr{[Symbol.asyncIterator]=async function*(){};static code=\"ERR_JWKS_MULTIPLE_MATCHING_KEYS\";code=\"ERR_JWKS_MULTIPLE_MATCHING_KEYS\";constructor(t=\"multiple matching keys found in the JSON Web Key Set\",r){super(t,r)}},Cb=class extends Hr{static code=\"ERR_JWKS_TIMEOUT\";code=\"ERR_JWKS_TIMEOUT\";constructor(t=\"request timed out\",r){super(t,r)}},Tb=class extends Hr{static code=\"ERR_JWS_SIGNATURE_VERIFICATION_FAILED\";code=\"ERR_JWS_SIGNATURE_VERIFICATION_FAILED\";constructor(t=\"signature verification failed\",r){super(t,r)}};var Xk=e=>{if(e?.[Symbol.toStringTag]===\"CryptoKey\")return!0;try{return e instanceof CryptoKey}catch{return!1}},tfe=e=>e?.[Symbol.toStringTag]===\"KeyObject\",sq=e=>Xk(e)||tfe(e);function aq(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64(e);let t=atob(e),r=new Uint8Array(t.length);for(let n=0;ntypeof o!=\"string\")||new Set(n).size!==n.length)throw new TypeError('\"key_ops\" (Key Operations) Parameter must be an array of unique strings');t.key_ops=n}return t}var nO=e=>e[Symbol.toStringTag],rfe=(e,t,r)=>{let{alg:n}=e;if(t.use!==void 0){let o=r===\"sign\"||r===\"verify\"?\"sig\":\"enc\";if(t.use!==o)throw new TypeError(`Invalid key for this operation, its \"use\" must be \"${o}\" when present`)}if(t.alg!==void 0&&t.alg!==n)throw new TypeError(`Invalid key for this operation, its \"alg\" must be \"${n}\" when present`);if(Array.isArray(t.key_ops)){let o=r===\"encrypt\"||r===\"decrypt\"?e.ops?.[r===\"encrypt\"?0:1]:r;if(o&&!t.key_ops.includes(o))throw new TypeError(`Invalid key for this operation, its \"key_ops\" must include \"${o}\" when present`)}};function nfe(e,t,r){let{alg:n,secret:o}=e,s=r===\"decrypt\"||r===\"sign\";if(o&&t instanceof Uint8Array)return[fq,t];if(Yi(t)){let a=cq(t);if(typeof a.kty!=\"string\")throw new TypeError(o?bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\",\"Uint8Array\"):bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\"));if(!(o?a.kty===\"oct\"&&typeof a.k==\"string\":a.kty!==\"oct\"&&(s?a.kty===\"AKP\"&&typeof a.priv==\"string\"||typeof a.d==\"string\":a.d===void 0&&a.priv===void 0)))throw new TypeError(o?'JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present':`JSON Web Key for this operation must be a ${s?\"private\":\"public\"} JWK`);return rfe(e,a,r),[dq,t,a]}if(!sq(t))throw new TypeError(o?bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\",\"Uint8Array\"):bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\"));if(o){if(t.type!==\"secret\")throw new TypeError(`${nO(t)} instances for symmetric algorithms must be of type \"secret\"`)}else{if(t.type===\"secret\")throw new TypeError(`${nO(t)} instances for asymmetric algorithms must not be of type \"secret\"`);let a=s?\"private\":\"public\";if((t.type===\"public\"||t.type===\"private\")&&t.type!==a){let i=r===\"sign\"?\"signing\":r===\"verify\"?\"verifying\":`${r.slice(0,-1)}tion`;throw new TypeError(`${nO(t)} instances for asymmetric algorithm ${i} must be of type \"${a}\"`)}}return Xk(t)?[lq,t]:[pq,t]}var fq=0,lq=1,pq=2,dq=3,oO,ofe={__proto__:null,prime256v1:\"P-256\",secp384r1:\"P-384\",secp521r1:\"P-521\"};function _b(e,t,r){oO||=new WeakMap;let n=oO.get(e);return r&&(n?n[t]=r:oO.set(e,{[t]:r})),r??n?.[t]}var uq=async(e,t,r)=>_b(e,r.alg)??_b(e,r.alg,await Ob(r,{...t,alg:r.alg})),sfe=(e,t)=>{let r=_b(e,t.alg);if(r)return r;let n=e.type===\"public\",o=t.usages[n?0:1],{asymmetricKeyType:s}=e,a=ofe[e.asymmetricKeyDetails?.namedCurve],i=t.resolve?.({crv:a,asymmetricKeyType:s})??t.subtle;return _b(e,t.alg,e.toCryptoKey(i,n,o))};async function mq(e,t,r){let n=nfe(e,t,r);switch(n[0]){case fq:case lq:return n[1];case dq:{let o=n[1],s=n[2];if(s.kty===\"oct\")return wh(s.k);if(!Object.isFrozen(o)){let{key_ops:a}=o;Array.isArray(a)&&Object.freeze(a),Object.freeze(o)}return uq(o,s,e)}case pq:{let o=n[1];return o.type===\"secret\"?o.export():\"toCryptoKey\"in o&&typeof o.toCryptoKey==\"function\"?sfe(o,e):uq(o,o.export({format:\"jwk\"}),e)}}}function hq(e){let t={__proto__:null};for(let r in e)t[r]={...e[r],alg:r};return t}var xq={__proto__:null,b64:!0};function gq(e,t){if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!=\"string\")))throw new TypeError(`\"${e}\" option must be an array of strings`);if(t)return new Set(t)}function yq(e,t,r,n,o){if(o.crit!==void 0&&n?.crit===void 0)throw new e('\"crit\" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return[];if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(a=>typeof a!=\"string\"||a.length===0))throw new e('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');let s=r===void 0?t:{__proto__:null,...r,...t};for(let a of n.crit){if(!(a in s))throw new as(`Extension Header Parameter \"${a}\" is not recognized`);if(!Object.hasOwn(o,a)||o[a]===void 0)throw new e(`Extension Header Parameter \"${a}\" is missing`);if(s[a]&&(!Object.hasOwn(n,a)||n[a]===void 0))throw new e(`Extension Header Parameter \"${a}\" MUST be integrity protected`)}return n.crit}function Sq(e,t){if(t.includes(\"b64\")){let r=e.b64;if(typeof r!=\"boolean\")throw new wn('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');return r}return!0}async function afe(e,t,r){return t instanceof Uint8Array?crypto.subtle.importKey(\"raw\",t,e.subtle,!1,[r]):(oq(t,e.subtle,r),e.minRsaBits&&nq(e.alg,t),t)}async function bq(e,t,r,n){let o=await afe(e,t,\"verify\");try{return await crypto.subtle.verify(e.signing,o,r,n)}catch{return!1}}var Ah=[[\"verify\"],[\"sign\"]];function sO(e){let t={name:\"HMAC\",hash:`SHA-${e}`};return{kty:[\"oct\"],secret:!0,subtle:t,signing:t,usages:Ah}}function tp(e,t){let n={name:t?\"RSA-PSS\":\"RSASSA-PKCS1-v1_5\",hash:`SHA-${e}`};return{kty:[\"RSA\"],subtle:n,signing:t?{...n,saltLength:t}:n,usages:Ah,minRsaBits:2048}}function aO(e,t){return{kty:[\"EC\"],crv:e,subtle:{name:\"ECDSA\",namedCurve:e},signing:{name:\"ECDSA\",hash:`SHA-${t}`},usages:Ah}}function Eq(){let e={name:\"Ed25519\"};return{kty:[\"OKP\"],crv:\"Ed25519\",subtle:e,signing:e,usages:Ah}}function iO(e){let r={name:`ML-DSA-${e}`};return{kty:[\"AKP\"],subtle:r,signing:r,usages:Ah}}var cO=hq({HS256:sO(256),HS384:sO(384),HS512:sO(512),RS256:tp(256),RS384:tp(384),RS512:tp(512),PS256:tp(256,32),PS384:tp(384,48),PS512:tp(512,64),ES256:aO(\"P-256\",256),ES384:aO(\"P-384\",384),ES512:aO(\"P-521\",512),EdDSA:Eq(),Ed25519:Eq(),\"ML-DSA-44\":iO(44),\"ML-DSA-65\":iO(65),\"ML-DSA-87\":iO(87)});function Iq(e){let t=typeof e==\"string\"?cO[e]:void 0;if(!t)throw new as(`alg ${e} is not supported either by JOSE or your javascript runtime`);return t}function wq(e){return[e&&gq(\"algorithms\",e.algorithms),e?.crit]}function ife(e,t=e===void 0?{}:kb(e,wn,\"JWS Protected Header is invalid\")){return t}function cfe(e,t,r){let n=Sq(e,yq(wn,xq,r[1],e,t)),o=t.alg;if(typeof o!=\"string\"||!o)throw new wn('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');if(r[0]&&!r[0].has(o))throw new wb('\"alg\" (Algorithm) Header Parameter value not allowed');return[n,o]}function ufe(e){try{return Ql(e)}catch{throw new wn(\"JWS Compact Serialization payload must use only ASCII characters\")}}async function ffe(e,t,r,n,o,s,a){let i=!1;typeof r==\"function\"&&(r=await r(o,e),i=!0);let c=typeof a==\"string\",u=Iq(s),f=rq(n!==void 0?Ql(n):new Uint8Array,Ql(\".\"),c?t[2]??=iq(a,\"payload\",wn):a),p=tO(e.signature,\"signature\",wn),d=await mq(u,r,\"verify\");if(!await bq(u,d,p,f))throw new Tb;return[c?tO(a,\"payload\",wn):a,o,c,d,i]}async function Aq(e,t,r){if(e instanceof Uint8Array&&(e=Sh.decode(e)),typeof e!=\"string\")throw new wn(\"Compact JWS must be a string or Uint8Array\");let{0:n,1:o,2:s,length:a}=e.split(\".\");if(a!==3)throw new wn(\"Invalid Compact JWS\");let i={payload:o,protected:n,signature:s},c=ife(n),[u,f]=cfe(c,c,t),p=u?o:ufe(o);return ffe(i,t,r,n,c,f,p)}var lfe=e=>Math.floor(e.getTime()/1e3),pfe={s:1,m:60,h:3600,d:86400,w:604800,y:31557600},dfe=/^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i,rp=\"check_failed\";function uO(){throw new TypeError(\"Invalid time period format\")}function Cq(e){typeof e!=\"string\"&&uO();let t=dfe.exec(e);(!t||t[4]&&t[1])&&uO();let r=parseFloat(t[2]),n=Math.round(r*pfe[t[3][0].toLowerCase()]);return Number.isFinite(n)||uO(),t[1]===\"-\"||t[4]===\"ago\"?-n:n}function fO(e,t){if(!Number.isFinite(t))throw new TypeError(`Invalid ${e} input`);return t}var Tq=e=>{let t=e.toLowerCase();return e.includes(\"/\")?t:`application/${t}`},mfe=(e,t)=>typeof e==\"string\"?t.includes(e):Array.isArray(e)?t.some(r=>e.includes(r)):!1;function lO(e,t,r=!1){let n=e[t];if(!(n===void 0&&!r)){if(typeof n!=\"number\")throw new Ka(`\"${t}\" claim must be a number`,e,t,\"invalid\");return n}}function pO(e,t){throw new Ka(`unexpected \"${t}\" claim value`,e,t,rp)}function vq(e,t,r={}){let n;try{n=JSON.parse(Eb.decode(t))}catch{}if(!Yi(n))throw new Xl(\"JWT Claims Set must be a top-level JSON object\");let{typ:o}=r;if(o!==void 0&&(typeof e.typ!=\"string\"||Tq(e.typ)!==Tq(o)))throw new Ka('unexpected \"typ\" JWT header value',n,\"typ\",rp);let{requiredClaims:s=[],issuer:a,subject:i,audience:c,maxTokenAge:u}=r,f=[...s];u!==void 0&&f.push(\"iat\"),c!==void 0&&f.push(\"aud\"),i!==void 0&&f.push(\"sub\"),a!==void 0&&f.push(\"iss\");for(let x of new Set(f.reverse()))if(!Object.hasOwn(n,x))throw new Ka(`missing required \"${x}\" claim`,n,x,\"missing\");a!==void 0&&!(Array.isArray(a)?a:[a]).includes(n.iss)&&pO(n,\"iss\"),i!==void 0&&n.sub!==i&&pO(n,\"sub\"),c!==void 0&&!mfe(n.aud,typeof c==\"string\"?[c]:c)&&pO(n,\"aud\");let{clockTolerance:p}=r,d=0;if(typeof p==\"string\")d=Cq(p);else if(p!==void 0){if(typeof p!=\"number\")throw new TypeError(\"Invalid clockTolerance option type\");d=p}fO(\"clockTolerance option\",d);let{currentDate:m}=r,h=fO(\"currentDate option\",lfe(m===void 0?new Date:m)),y=lO(n,\"iat\",u!==void 0),S=lO(n,\"nbf\");if(S!==void 0&&S>h+d)throw new Ka('\"nbf\" claim timestamp check failed',n,\"nbf\",rp);let b=lO(n,\"exp\");if(b!==void 0&&b<=h-d)throw new Eh('\"exp\" claim timestamp check failed',n,\"exp\",rp);if(u!==void 0){let x=h-y,w=fO(\"maxTokenAge option\",typeof u==\"number\"?u:Cq(u));if(x-d>w)throw new Eh('\"iat\" claim timestamp check failed (too far in the past)',n,\"iat\",rp);if(x<-d)throw new Ka('\"iat\" claim timestamp check failed (it should be in the past)',n,\"iat\",rp)}return n}async function Rb(e,t,r){let n=await Aq(e,wq(r),t);if(!n[2])throw new Xl(\"JWTs MUST NOT use unencoded payload\");let s={payload:vq(n[1],n[0],r),protectedHeader:n[1]};return typeof t==\"function\"?{...s,key:n[3]}:s}function hfe(e,t,r,n){let{kty:o,key_ops:s,ext:a,kid:i,alg:c,use:u,crv:f}=rO(e),p=Array.isArray(s)?[...s]:s;return(a===void 0||typeof a==\"boolean\")&&(p===void 0||Array.isArray(p)&&p.every((d,m)=>typeof d==\"string\"&&p.indexOf(d)===m)&&p.includes(\"verify\"))&&t.kty.includes(o)&&(n===void 0||typeof n==\"string\"&&n===i)&&(c===void 0?o!==\"AKP\":r===c)&&(u===void 0||u===\"sig\")&&(!t.crv||f===t.crv)}async function kq(e,t,r){let n=e.get(t)||e.set(t,{}).get(t),{alg:o}=r;if(n[o]===void 0){let s=await Ob(r,{...t,alg:o,ext:!0});if(s.type!==\"public\")throw new Ih(\"JSON Web Key Set members must be public keys\");n[o]=s}return n[o]}function Ku(e){let t;try{t=structuredClone(e)}catch{}if(!vb(t))throw new Ih(\"JSON Web Key Set malformed\");let r=new WeakMap;return Object.defineProperty(async(o,s)=>{let{alg:a,kid:i}={...o,...s?.header},c=typeof a==\"string\"?cO[a]:void 0;if(!c||c.secret)throw new as('Unsupported \"alg\" value for a JSON Web Key Set');let u=t.keys.filter(d=>hfe(d,c,a,i)),{0:f,length:p}=u;if(!p)throw new ep;if(p!==1){let d=new Ab;throw d[Symbol.asyncIterator]=async function*(){for(let m of u)try{yield await kq(r,m,c)}catch{}},d}return kq(r,f,c)},\"jwks\",{value:()=>structuredClone(t)})}function xfe(){return typeof WebSocketPair<\"u\"||typeof navigator<\"u\"&&navigator.userAgent===\"Cloudflare-Workers\"||typeof EdgeRuntime<\"u\"&&EdgeRuntime===\"vercel\"}var dO;(typeof navigator>\"u\"||!navigator.userAgent?.startsWith?.(\"Mozilla/5.0 \"))&&(dO=\"jose/v6.2.10\");var _q=Symbol();async function gfe(e,t,r,n=fetch){let o=await n(e,{method:\"GET\",signal:r,redirect:\"manual\",headers:t}).catch(s=>{throw s.name===\"TimeoutError\"?new Cb:s});if(o.status!==200)throw new Hr(\"Expected 200 OK from the JSON Web Key Set HTTP response\");try{return await o.json()}catch{throw new Hr(\"Failed to parse the JSON Web Key Set HTTP response as JSON\")}}var Rq=Symbol();function Ch(e,t){return Number.isFinite(e)&&Date.now(){if(d&&xfe()&&(d=void 0),!d){let x=++m,w=d=gfe(r,c,AbortSignal.timeout(s),u).then(I=>{let T=Ku(I);if(x<=h)return;y=T;let P=Date.now();f&&(f.uat=P,f.jwks=I),p=P,h=x}).finally(()=>{d===w&&(d=void 0)})}await d};return Object.defineProperties(async(x,w)=>{(!y||!Ch(p,i))&&await S();try{return await y(x,w)}catch(I){if(I instanceof ep&&!Ch(p,a))return await S(),y(x,w);throw I}},{coolingDown:{get:()=>Ch(p,a),enumerable:!0},fresh:{get:()=>Ch(p,i),enumerable:!0},reload:{value:S,enumerable:!0},reloading:{get:()=>!!d,enumerable:!0},jwks:{value:()=>y?.jwks(),enumerable:!0}})}function hO(e){let t;if(typeof e==\"string\"){let n=e.split(\".\");(n.length===3||n.length===5)&&([t]=n)}else if(typeof e==\"object\"&&e)if(\"protected\"in e)t=e.protected;else throw new TypeError(\"Token does not contain a Protected Header\");let r=\"Invalid Token or Protected Header formatting\";if(typeof t!=\"string\"||!t)throw new TypeError(r);return kb(t,TypeError,r)}var Sfe=new Set([\"HOME\",\"HOSTNAME\",\"PATH\",\"PWD\"]),Io=$.runSync($.gen(function*(){let e=t=>t.pipe(nn.option);return{hostPort:yield*e(nn.String(\"SUPABASE_INTERNAL_HOST_PORT\")),functionsRoot:yield*e(nn.String(\"SUPABASE_INTERNAL_FUNCTIONS_ROOT\")),filesRoot:yield*e(nn.String(\"SUPABASE_INTERNAL_FUNCTIONS_FILES_ROOT\")),jwtSecret:yield*e(nn.String(\"SUPABASE_INTERNAL_JWT_SECRET\")),supabaseUrl:yield*e(nn.String(\"SUPABASE_URL\")),wallclock:yield*e(nn.String(\"SUPABASE_INTERNAL_WALLCLOCK_LIMIT_SEC\")),publishableKey:yield*e(nn.String(\"SUPABASE_INTERNAL_PUBLISHABLE_KEY\")),secretKey:yield*e(nn.String(\"SUPABASE_INTERNAL_SECRET_KEY\")),functionsConfig:yield*e(nn.String(\"SUPABASE_INTERNAL_FUNCTIONS_CONFIG\")),debug:yield*e(nn.String(\"SUPABASE_INTERNAL_DEBUG\")),jwks:yield*e(nn.String(\"SUPABASE_JWKS\"))}}).pipe($.provideService(Gl.ConfigProvider,Gl.fromEnvRecord(Deno.env.toObject(),{preserveEmptyStrings:!0})))),sp=(e,t=\"\")=>ye.getOrElse(e,()=>t),Pq=sp(Io.hostPort,\"8081\"),Lq=sp(Io.functionsRoot),bfe=sp(Io.jwtSecret),Efe=sp(Io.supabaseUrl,\"http://127.0.0.1:54321\"),Ife=new URL(\"/auth/v1/.well-known/jwks.json\",Efe),Mq=Number.parseInt(sp(Io.wallclock,\"400\"),10),Fq=ye.getOrUndefined(Io.publishableKey),Nq=ye.getOrUndefined(Io.secretKey),Ba={BootError:In.ServiceUnavailable,InvalidWorkerResponse:In.InternalServerError,WorkerLimit:546},wfe={[Ba.BootError]:\"BOOT_ERROR\",[Ba.InvalidWorkerResponse]:\"WORKER_ERROR\",[Ba.WorkerLimit]:\"WORKER_LIMIT\"},Afe={[Ba.BootError]:\"Worker failed to boot (please check logs)\",[Ba.InvalidWorkerResponse]:\"Function exited due to an error (please check logs)\",[Ba.WorkerLimit]:\"Worker failed to respond due to a resource limit (please check logs)\"},Cfe=new Map([[Deno.errors.InvalidWorkerCreation,Ba.BootError],[Deno.errors.InvalidWorkerResponse,Ba.InvalidWorkerResponse],[Deno.errors.WorkerRequestCancelled,Ba.WorkerLimit]]),Tfe=e=>{let t=Deno.errors.WorkerAlreadyRetired;return t!==void 0&&e instanceof t},vfe=(s=>(s.MissingAuthHeader=\"UNAUTHORIZED_NO_AUTH_HEADER\",s.InvalidLegacyJWT=\"UNAUTHORIZED_JWT\",s.InvalidAsymmetricJWT=\"UNAUTHORIZED_ASYMMETRIC_JWT\",s.InvalidTokenFormat=\"UNAUTHORIZED_INVALID_JWT_FORMAT\",s.UnsupportedTokenAlgorithm=\"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM\",s))(vfe||{}),kfe=Ie.Struct({enabled:Ie.optionalKey(Ie.Boolean),verifyJWT:Ie.optionalKey(Ie.Boolean),verify_jwt:Ie.optionalKey(Ie.Boolean),entrypointPath:Ie.optionalKey(Ie.String),entrypoint:Ie.optionalKey(Ie.String),importMapPath:Ie.optionalKey(Ie.String),import_map:Ie.optionalKey(Ie.String),importMapRoot:Ie.optionalKey(Ie.String),import_map_root:Ie.optionalKey(Ie.String),staticFiles:Ie.optionalKey(Ie.Array(Ie.String)),static_files:Ie.optionalKey(Ie.Array(Ie.String)),env:Ie.optionalKey(Ie.Record(Ie.String,Ie.String))}),Ofe=Ie.Record(Ie.String,kfe),_fe=Ie.declare(e=>typeof e==\"object\"&&e!==null&&\"keys\"in e&&Array.isArray(e.keys)&&e.keys.every(t=>typeof t==\"object\"&&t!==null)),Rfe=()=>ye.match(Io.functionsConfig,{onNone:()=>({}),onSome:e=>$.runSync(Ie.decodeEffect(Ie.fromJsonString(Ofe))(e).pipe($.orElseSucceed(()=>({}))))}),xO=Rfe();if(ye.getOrUndefined(Io.debug)===\"true\"){let e=Object.fromEntries(Object.entries(xO).map(([t,r])=>[t,Object.fromEntries(Object.entries(r).filter(([n])=>n!==\"env\"))]));$.runSync(Lu.log(\"Functions config:\",JSON.stringify(e,null,2)))}var Bu=(e,t,r={})=>{let n={...r},o=null;return e!=null&&(typeof e==\"object\"?(n[\"Content-Type\"]=\"application/json\",o=JSON.stringify(e)):(n[\"Content-Type\"]=\"text/plain\",o=typeof e==\"string\"?e:JSON.stringify(e)??null)),new Response(o,{status:t,headers:n})},np={\"Access-Control-Allow-Origin\":\"*\",\"Access-Control-Allow-Headers\":\"authorization, x-client-info, apikey\",\"Access-Control-Expose-Headers\":\"sb-error-code\"},Uq=({code:e,message:t=\"Invalid JWT\"})=>Bu({code:e,message:t,msg:t},In.Unauthorized,{...np,\"sb-error-code\":e}),Pfe=e=>{for(let[t,r]of Cfe.entries())if(t!==void 0&&e instanceof t)return Bu({code:wfe[r],message:Afe[r]},r,np);return Bu({code:Zk[In.InternalServerError],message:\"Request failed due to an internal server error\"},In.InternalServerError,np)};function Mfe(e){let t=e.split(\" \");return t.length===2&&t[0]===\"Bearer\"?t[1]:null}var Ffe=e=>{let t=e.headers.get(\"authorization\"),r=e.headers.get(\"sb-api-key\")?.replace(\"Bearer\",\"\").trim();if(!t&&!r)return{code:\"UNAUTHORIZED_NO_AUTH_HEADER\",message:\"Missing authorization header\"};let n=Mfe(t??\"\"),o=!n||n.startsWith(\"sb_\")?r:n;return o||{code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"}},op=class extends an.TaggedError(\"BootstrapOperationError\"){},Nfe=$.runSync(ye.match(Io.jwks,{onNone:()=>$.succeed(ye.some(Ku({keys:[]}))),onSome:e=>$.gen(function*(){let t=yield*Ie.decodeEffect(Ie.fromJsonString(_fe))(e);return yield*$.try({try:()=>Ku(t),catch:r=>new op({cause:r})})}).pipe($.option)})),Ufe=ye.getOrElse(Nfe,()=>mO(Ife)),Qi=e=>$.tryPromise({try:e,catch:t=>new op({cause:t})}),Dfe=e=>$.gen(function*(){return yield*Qi(()=>Rb(e,Ufe)),ye.none()}).pipe($.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_ASYMMETRIC_JWT\"})));function Lfe(e,t){return $.gen(function*(){let r=yield*$.try({try:()=>hO(t).alg,catch:n=>new op({cause:n})});return r?r===\"HS256\"?yield*Qi(()=>Rb(t,new TextEncoder().encode(e))).pipe($.as(ye.none()),$.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_JWT\"}))):r===\"ES256\"||r===\"RS256\"?yield*Dfe(t):ye.some({code:\"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM\",message:`Unsupported JWT algorithm ${r}`}):ye.some({code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"})}).pipe($.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"})))}var $q={lstat:e=>Qi(()=>Deno.lstat(e)).pipe($.mapError(t=>new Yl({cause:t})),$.map(t=>({isDirectory:t.isDirectory,isFile:t.isFile,isSymbolicLink:t.isSymlink}))),realPath:e=>Qi(()=>Deno.realPath(e)).pipe($.mapError(t=>new Yl({cause:t}))),readDirectory:e=>Hs.suspend(()=>Hs.fromAsyncIterable(Deno.readDir(e),t=>new op({cause:t})).pipe(Hs.map(t=>t.name))).pipe(Hs.runCollect,$.mapError(t=>new Yl({cause:t})))},$fe=e=>XW({root:Lq,filesRoot:ye.getOrUndefined(Io.filesRoot),slug:e,overrides:xO,fs:$q}),Dq=new Set,Kfe=(e,t)=>t.importMapDiscoveredByRuntime||!QW(t.importMapPath)||Dq.has(e)?$.void:$.sync(()=>Dq.add(e)).pipe($.andThen(Lu.warn(`[functions] ${e}: ${t.importMapPath} is not the nearest Deno config of ${t.entrypointPath}, so Edge Runtime loads it as a plain import map without comments or jsr:/npm: subpath imports. Move it next to the entrypoint or into a parent directory without a closer deno.json(c).`))),Bfe=eq(()=>Deno.makeTempDirSync({prefix:\"supabase-worker-\"})),jfe=e=>e.importMapPath?$.succeed(!1):tq({root:sp(Io.filesRoot,Lq),config:e,fs:$q}),Kq=e=>Hs.fromEffectRepeat(Qi(()=>e.read()).pipe($.flatMap(t=>t.done?er.done():$.succeed(t.value)))),Hfe=e=>e===void 0?$.void:Hs.runDrain(Kq(e)).pipe($.ignore);function zfe(e,t){let r=new URL(e.url),n=e.headers.get(\"x-forwarded-host\");n&&(r.hostname=n);let o=new Request(r.href,{method:e.method,headers:e.headers,body:t===void 0?null:Hs.toReadableStream(Kq(t)),signal:e.signal,duplex:\"half\"});return o.headers.delete(\"sb-api-key\"),EdgeRuntime.applySupabaseTag(e,o),o}Deno.serve({handler:e=>$.runPromiseExit($.gen(function*(){let t=yield*$.acquireRelease($.sync(()=>e.body?.getReader()),u=>$.interruptible(Hfe(u))),{pathname:r}=new URL(e.url);if(r===\"/_internal/health\")return Bu({message:\"ok\"},In.OK);if(r===\"/_internal/metric\")return Response.json(yield*Qi(()=>EdgeRuntime.getRuntimeMetrics()));let n=r.split(\"/\")[1];if(!n)return Bu(\"Function not found\",In.NotFound,np);let o=yield*$fe(n);if(!o)return Bu(\"Function not found\",In.NotFound,np);if(yield*Kfe(n,o),e.method!==\"OPTIONS\"&&o.verifyJWT){let u=Ffe(e);if(typeof u!=\"string\")return Uq(u);let f=yield*Lfe(bfe,u);if(ye.isSome(f))return Uq(f.value)}let s={...Deno.env.toObject(),...Object.fromEntries(Object.entries(o.env??{}).filter(([u])=>!u.startsWith(\"SUPABASE_\"))),SUPABASE_FUNCTION_SLUG:n};Fq&&(s.SUPABASE_PUBLISHABLE_KEYS=yield*Ie.encodeEffect(Ie.fromJsonString(Ie.Unknown))({default:Fq})),Nq&&(s.SUPABASE_SECRET_KEYS=yield*Ie.encodeEffect(Ie.fromJsonString(Ie.Unknown))({default:Nq}));let a=Object.entries(s).filter(([u])=>!Sfe.has(u)&&!u.startsWith(\"SUPABASE_INTERNAL_\")),i=!(yield*jfe(o));return yield*$.gen(function*(){let u=yield*Qi(()=>EdgeRuntime.userWorkers.create({servicePath:Bfe(n,o),memoryLimitMb:256,workerTimeoutMs:Number.isFinite(Mq)?Mq*1e3:4e5,noModuleCache:!1,noNpm:i,envVars:a,forceCreate:!0,customModuleRoot:\"\",cpuTimeSoftLimitMs:1e3,cpuTimeHardLimitMs:2e3,decoratorType:\"tc39\",maybeEntrypoint:VW(o.entrypointPath).href,context:{useReadSyncFileAPI:!0,...o.importMapPath===\"\"||o.importMapDiscoveredByRuntime?{}:{importMapPath:o.importMapPath}},staticPatterns:o.staticFiles}));return yield*Qi(()=>u.fetch(zfe(e,t)))}).pipe($.retry({times:1,while:({cause:u})=>e.body===null&&Tfe(u)}),$.catchTag(\"BootstrapOperationError\",({cause:u})=>Lu.error(\"[functions] worker error\",u).pipe($.andThen($.succeed(Pfe(u))))))}).pipe($.scoped),{signal:e.signal}).then(t=>{if(Or.isSuccess(t))return t.value;if(e.signal.aborted&&er.hasInterruptsOnly(t.cause))return new Response(null,{status:499});throw er.squash(t.cause)}),onListen:()=>{let t=Object.keys(xO).slice(0,5).map(r=>` - http://127.0.0.1:${Pq}/functions/v1/${r}`);$.runSync(Lu.log(`Serving functions on http://127.0.0.1:${Pq}/functions/v1/${t.length?`\n${t.join(`\n`)}`:\"\"}\nUsing ${Deno.version.deno}`))},onError:()=>Bu({code:Zk[500],message:\"Request failed due to an internal server error\"},500,np)});export{vfe as RequestErrors,Mfe as extractBearerToken,zfe as prepareUserRequest};\n"; +export const defaultFunctionsBootstrap = "var Bq=Object.defineProperty;var An=(e,t)=>{for(var r in t)Bq(e,r,{get:t[r],enumerable:!0})};var te=(e,t)=>{switch(t.length){case 0:return e;case 1:return t[0](e);case 2:return t[1](t[0](e));case 3:return t[2](t[1](t[0](e)));case 4:return t[3](t[2](t[1](t[0](e))));case 5:return t[4](t[3](t[2](t[1](t[0](e)))));case 6:return t[5](t[4](t[3](t[2](t[1](t[0](e))))));case 7:return t[6](t[5](t[4](t[3](t[2](t[1](t[0](e)))))));case 8:return t[7](t[6](t[5](t[4](t[3](t[2](t[1](t[0](e))))))));case 9:return t[8](t[7](t[6](t[5](t[4](t[3](t[2](t[1](t[0](e)))))))));default:{let r=e;for(let n=0,o=t.length;nt(r,...arguments)};switch(e){case 0:case 1:throw new RangeError(`Invalid arity ${e}`);case 2:return function(r,n){return arguments.length>=2?t(r,n):function(o){return t(o,r)}};case 3:return function(r,n,o){return arguments.length>=3?t(r,n,o):function(s){return t(s,r,n)}};default:return function(){if(arguments.length>=e)return t.apply(this,arguments);let r=arguments;return function(n){return t(n,...r)}}}};var D=e=>e;var gt=e=>()=>e,Cn=gt(!0),ap=gt(!1),Mb=gt(null),Zn=gt(void 0),Wr=Zn;function Fb(e,...t){return te(e,t)}function gO(e,t,r,n,o,s,a,i,c){switch(arguments.length){case 1:return e;case 2:return function(){return t(e.apply(this,arguments))};case 3:return function(){return r(t(e.apply(this,arguments)))};case 4:return function(){return n(r(t(e.apply(this,arguments))))};case 5:return function(){return o(n(r(t(e.apply(this,arguments)))))};case 6:return function(){return s(o(n(r(t(e.apply(this,arguments))))))};case 7:return function(){return a(s(o(n(r(t(e.apply(this,arguments)))))))};case 8:return function(){return i(a(s(o(n(r(t(e.apply(this,arguments))))))))};case 9:return function(){return c(i(a(s(o(n(r(t(e.apply(this,arguments)))))))))}}}function on(e){let t=new WeakMap;return r=>{let n=t.get(r);if(n!==void 0)return n;let o=e(r);return t.set(r,o),o}}function qs(e){let t=new WeakMap;return r=>{let n=t.get(r);if(n!==void 0)return n;let o=e(r);return t.set(r,o),o!==r&&t.set(o,o),o}}var er={};An(er,{AsyncFiberError:()=>dJ,AsyncFiberErrorTypeId:()=>lJ,Done:()=>o0,DoneTypeId:()=>nJ,ExceededCapacityError:()=>s0,ExceededCapacityErrorTypeId:()=>fJ,IllegalArgumentError:()=>ud,IllegalArgumentErrorTypeId:()=>iJ,InterruptorStackTrace:()=>ZI,NoSuchElementError:()=>rJ,NoSuchElementErrorTypeId:()=>tJ,ReasonTypeId:()=>$3,StackTrace:()=>VI,TimeoutError:()=>aJ,TimeoutErrorTypeId:()=>oJ,TypeId:()=>L3,UnknownError:()=>xJ,UnknownErrorTypeId:()=>mJ,annotate:()=>gJ,annotations:()=>yJ,combine:()=>z3,die:()=>Rc,done:()=>ue,empty:()=>B3,fail:()=>j3,filterInterruptors:()=>Q3,findDefect:()=>cd,findDie:()=>G3,findError:()=>q3,findErrorOption:()=>r0,findFail:()=>W3,findInterrupt:()=>Z3,fromReasons:()=>gs,hasDies:()=>J3,hasFails:()=>t0,hasInterrupts:()=>V3,hasInterruptsOnly:()=>e0,interrupt:()=>H3,interruptors:()=>Y3,isAsyncFiberError:()=>pJ,isCause:()=>id,isDieReason:()=>QI,isDone:()=>Pc,isExceededCapacityError:()=>uJ,isFailReason:()=>ai,isIllegalArgumentError:()=>cJ,isInterruptReason:()=>K3,isNoSuchElementError:()=>eJ,isReason:()=>YI,isTimeoutError:()=>sJ,isUnknownError:()=>hJ,makeDieReason:()=>Tf,makeFailReason:()=>Cf,makeInterruptReason:()=>XI,map:()=>fa,pretty:()=>n0,prettyErrors:()=>X3,reasonAnnotations:()=>ng,squash:()=>rg});var ip=e=>{let t=new Set(Reflect.ownKeys(e));if(e.constructor===Object)return t;e instanceof Error&&t.delete(\"stack\");let r=Object.getPrototypeOf(e),n=r;for(;n!==null&&n!==Object.prototype;){let o=Reflect.ownKeys(n);for(let s=0;snew Uint8Array(e.buffer,e.byteOffset,e.byteLength),up=e=>e instanceof ArrayBuffer||typeof SharedArrayBuffer<\"u\"&&e instanceof SharedArrayBuffer,fp=e=>{try{return new Uint8Array(e)}catch{return}};var ec=0,SO=()=>{ec++};function qr(e){return typeof e==\"string\"}function lp(e){return typeof e==\"number\"}function Th(e){return typeof e==\"boolean\"}function bO(e){return typeof e==\"bigint\"}function Nb(e){return typeof e==\"symbol\"}function vh(e){return qr(e)||lp(e)||Nb(e)}function Jr(e){return typeof e==\"function\"}function EO(e){return e===void 0}function cs(e){return e!==void 0}function kh(e){return e!=null}function IO(e){return!1}function Ub(e){return!0}function fr(e){return typeof e==\"object\"&&e!==null&&!Array.isArray(e)}function pp(e){return typeof e==\"object\"&&e!==null||Jr(e)}var A=l(2,(e,t)=>pp(e)&&t in e),Wt=l(2,(e,t)=>A(e,\"_tag\")&&e._tag===t);function wO(e){return e instanceof Error}function Js(e){return A(e,Symbol.iterator)||qr(e)}var re=\"~effect/Hash\",V=e=>{switch(typeof e){case\"number\":return Lt(e);case\"bigint\":return Pe(e.toString(10));case\"string\":return Pe(e);case\"function\":case\"object\":{if(e===null)break;if(e instanceof Date)return Number.isNaN(e.getTime())?Pe(\"Invalid Date\"):Pe(e.toISOString());if(e instanceof RegExp)return Pe(e.toString());{if(zu.has(e))return Db(e);let t=CO.get(e);if(t!==void 0)return t;if(Kb.has(e))return SO(),Pe(\"[Circular]\");Kb.add(e);let r=ec,n;try{if(jq(e))n=e[re]();else if(typeof e==\"function\")n=Db(e);else if(up(e)){let o=fp(e);n=o===void 0?Db(e):wo(o)}else e instanceof DataView?n=wo(cp(e)):Array.isArray(e)||ArrayBuffer.isView(e)?n=wo(e):e instanceof Map?n=Hq(e):e instanceof Set?n=zq(e):n=mp(e)}finally{Kb.delete(e)}return r===ec&&CO.set(e,n),n}}}return lr(TO(Pe(String(e))))},Db=e=>($b.has(e)||$b.set(e,lr(Math.random()*4294967296|0)),$b.get(e)),TO=e=>(e^=e>>>16,e=Math.imul(e,2246822507),e^=e>>>13,e=Math.imul(e,3266489909),e^e>>>16),Ee=l(2,(e,t)=>TO(Math.imul(e,2654435761)+Math.imul(t,2246822507))),lr=e=>e&3221225471|e>>>1&1073741824,jq=e=>A(e,re)&&typeof e[re]==\"function\",Lb=new DataView(new ArrayBuffer(8)),Lt=e=>{let t=e|0;return t===e?lr(t):(Lb.setFloat64(0,e!==e?NaN:e),lr(Ee(Lb.getInt32(0),Lb.getInt32(4))))},Pe=e=>{let t=5381,r=e.length;for(;r;)t=t*33^e.charCodeAt(--r);return lr(t)},dp=(e,t)=>{let r=12289;for(let n of t)r^=Ee(V(n),V(e[n]));return lr(r)},mp=e=>dp(e,ip(e)),vO=(e,t)=>r=>{let n=e;for(let o of r)n^=t(o);return lr(n)},wo=e=>{let t=6151;for(let r of e)t=Ee(t,V(r));return lr(t)},Hq=vO(Pe(\"Map\"),([e,t])=>Ee(V(e),V(t))),AO=Pe(\"Set\"),zq=vO(AO,e=>Ee(AO,V(e))),$b=new WeakMap,CO=new WeakMap,Kb=new WeakSet;var ne=\"~effect/Equal\";function Z(){return arguments.length===1?e=>tc(e,arguments[0]):tc(arguments[0],arguments[1])}function tc(e,t){if(e===t)return!0;if(e==null||t==null)return!1;let r=typeof e;return r!==typeof t?!1:r===\"number\"&&e!==e&&t!==t?!0:r!==\"object\"&&r!==\"function\"||zu.has(e)||zu.has(t)?!1:Wq(e,t)}function Wq(e,t){let r=Oh.length;for(let s=r;s-- >0;)if(Oh[s]===e&&jb[s]===t)return!0;if(r)return kO(e,t);let n=OO.get(e);n||OO.set(e,n=new WeakMap);let o=n.get(t);return o===void 0&&n.set(t,o=kO(e,t)),o}function kO(e,t){Oh.push(e),jb.push(t);try{return qq(e,t)}finally{Oh.pop(),jb.pop()}}var Oh=[],jb=[],OO=new WeakMap;function qq(e,t){if(V(e)!==V(t))return!1;if(e instanceof Date){if(!(t instanceof Date))return!1;let n=e.getTime(),o=t.getTime();return n===o||Number.isNaN(n)&&Number.isNaN(o)}else if(e instanceof RegExp)return t instanceof RegExp&&e.toString()===t.toString();let r=_O(e);if(r!==_O(t)||typeof e==\"function\"&&!r)return!1;if(r)return e[ne](t);if(Array.isArray(e))return!Array.isArray(t)||e.length!==t.length?!1:Jq(e,t);if(up(e)){if(!up(t)||e instanceof ArrayBuffer!=t instanceof ArrayBuffer)return!1;let n=fp(e),o=fp(t);return n!==void 0&&o!==void 0&&Bb(n,o)}else if(ArrayBuffer.isView(e)){let n=e instanceof DataView;return!ArrayBuffer.isView(t)||e.byteLength!==t.byteLength||n!==t instanceof DataView?!1:n?Bb(cp(e),cp(t)):Bb(e,t)}else{if(e instanceof Map)return!(t instanceof Map)||e.size!==t.size?!1:Hb(e,t,Vq,Zq);if(e instanceof Set)return!(t instanceof Set)||e.size!==t.size?!1:Hb(e,t,V,tc)}return Gq(e,t)}function Jq(e,t){for(let r=0;rV(e[0]),Zq=(e,t)=>tc(e[0],t[0])&&tc(e[1],t[1]),Yq=()=>0;function _h(e,t){return hp((r,n)=>e(r[0],n[0])&&t(r[1],n[1]))}function hp(e){return function(r,n){return Hb(r,n,Yq,e)}}var _O=e=>A(e,ne)&&typeof e[ne]==\"function\",xp=()=>Z;var Rh=e=>(zu.add(e),e);var Gs=Symbol.for(\"~effect/Redactable\"),Qq=e=>A(e,Gs);function Ao(e){return Qq(e)?zb(e):e}function zb(e){return e[Gs](globalThis[rc]?.context??Xq)}var rc=\"~effect/Fiber/currentFiber\",RO=new Map,Xq={\"~effect/Context\":{},base:RO,depth:0,mapUnsafe:RO,pipe(){return te(this,arguments)}};function K(e,t){let r=t?.space??0,n=new WeakSet,o=r?typeof r==\"number\"?\" \".repeat(r):r:\"\",s=f=>o.repeat(f),a=(f,p)=>{let d=f?.constructor;return d&&d!==Object.prototype.constructor&&d.name?`${d.name}(${p})`:p},i=f=>{try{return Reflect.ownKeys(f)}catch{return[\"[ownKeys threw]\"]}};function c(f,p=0){try{return u(f,p)}catch{return(typeof f==\"object\"&&f!==null||typeof f==\"function\")&&n.delete(f),\"[inspection threw]\"}}function u(f,p=0){if(typeof f==\"string\")return JSON.stringify(f);if(typeof f==\"number\"||f==null||typeof f==\"boolean\"||typeof f==\"symbol\")return String(f);if(typeof f==\"bigint\")return String(f)+\"n\";if(typeof f==\"object\"||typeof f==\"function\"){if(n.has(f))return e6;n.add(f);let d;if(Gs in f)d=c(zb(f),p);else if(Array.isArray(f))d=!o||f.length<=1?`[${f.map(m=>c(m,p)).join(\",\")}]`:`[\n${s(p+1)}${f.map(m=>c(m,p+1)).join(`,\n`+s(p+1))}\n${s(p)}]`;else if(f instanceof Date)d=qb(f);else if(!t?.ignoreToString&&A(f,\"toString\")&&typeof f.toString==\"function\"&&f.toString!==Object.prototype.toString&&f.toString!==Array.prototype.toString){let m=t6(f);d=f instanceof Error&&f.cause!==void 0?`${m} (cause: ${c(f.cause,p)})`:m}else if(Symbol.iterator in f)d=`${f.constructor.name}(${c(Array.from(f),p)})`;else{let m=i(f);if(!o||m.length<=1){let h=`{${m.map(y=>`${us(y)}:${c(PO(f,y),p)}`).join(\",\")}}`;d=a(f,h)}else{let h=`{\n${m.map(y=>`${s(p+1)}${us(y)}: ${c(PO(f,y),p+1)}`).join(`,\n`)}\n${s(p)}}`;d=a(f,h)}}return n.delete(f),d}return String(f)}return c(e,0)}var e6=\"[Circular]\";function us(e){return typeof e==\"string\"?JSON.stringify(e):String(e)}function Ph(e){return e.map(t=>`[${us(t)}]`).join(\"\")}function qb(e){try{return e.toISOString()}catch{return\"Invalid Date\"}}function t6(e){try{let t=e.toString();return typeof t==\"string\"?t:String(t)}catch{return\"[toString threw]\"}}function PO(e,t){try{return e[t]}catch{return\"[property access threw]\"}}function nc(e,t){let r=[],n=new WeakMap;return JSON.stringify(e,function(o,s){let a=Object.getOwnPropertyDescriptor(n.get(this)??this,o)?.value,i=A(a,Gs)?Ao(a):Ao(s);if(typeof i==\"bigint\")return K(i);if(typeof i!=\"object\"||i===null)return i;let c=i instanceof Error&&!A(i,\"toJSON\")?{...i,name:i.name,message:i.message}:i;for(;r.length>0&&r[r.length-1]!==this;)r.pop();if(r.includes(i))return;if(r.push(i),c!==i&&r.push(c),!r6(c)||o6(c))return c;let u=n6(c);return n.set(u,c),r.push(u),u},t?.space)??\"null\"}function r6(e){for(let t of Object.getOwnPropertyNames(e))if(Object.getOwnPropertyDescriptor(e,t)?.get!==void 0)return!0;return!1}function n6(e){let t=Array.isArray(e)?[]:{},r=Array.isArray(e)?Array.from({length:e.length},(n,o)=>String(o)):Object.keys(e);for(let n of r)Object.defineProperty(t,n,{enumerable:!0,get:()=>{let o=Reflect.get(e,n);return Object.getOwnPropertyDescriptor(e,n)?.get!==void 0?Ao(o):o}});return t}function o6(e){for(let t of[Number.prototype.valueOf,Boolean.prototype.valueOf,String.prototype.valueOf])try{return Reflect.apply(t,e,[]),!0}catch{}return!1}var Je=Symbol.for(\"nodejs.util.inspect.custom\"),qt=e=>{try{return e=Ao(e),A(e,\"toJSON\")&&Jr(e.toJSON)&&e.toJSON.length===0?e.toJSON():Array.isArray(e)?e.map(qt):e}catch{return\"[toJSON threw]\"}},FO=(e,t=2)=>{if(typeof e==\"string\")return e;try{return typeof e==\"object\"?nc(e,{space:t}):K(e,{space:t})}catch{return String(e)}},$t={toJSON(){return qt(this)},[Je](){return this.toJSON()},toString(){return K(this.toJSON())}},MO=class{[Je](){return this.toJSON()}toString(){return K(this.toJSON())}};var a6=()=>{let e=Object.getOwnPropertyDescriptor(Error,\"stackTraceLimit\");return e===void 0?Object.isExtensible(Error):Object.hasOwn(e,\"writable\")?e.writable===!0:e.set!==void 0},i6=a6(),Co=()=>Error.stackTraceLimit,pr=e=>{i6&&(Error.stackTraceLimit=e)};var Ha=class{constructor(t){this.value=t,this.done=!1}next(t){return this.done?(this.value=t,this):(this.done=!0,{value:this.value,done:!1})}},c6=()=>{let e=\"~effect/Utils/internal\",t={[e]:s=>s()},r={[e]:s=>s()},n=Co();if(n===0)return r[e];pr(2);let o=t[e](()=>new Error);return pr(n),o.stack?.includes(e)===!0?t[e]:r[e]},za=c6();function B(e,t,r){t===\"__proto__\"?Object.defineProperty(e,t,{value:r,writable:!0,enumerable:!0,configurable:!0}):e[t]=r}function Mh(e,t){if(!Object.hasOwn(t,\"__proto__\")){Object.assign(e,t);return}for(let r of Reflect.ownKeys(t))Object.prototype.propertyIsEnumerable.call(t,r)&&B(e,r,t[r])}var fs=\"~effect/Effect\",oc=\"~effect/Exit\",f6={_A:D,_E:D,_R:D},Jb=`${fs}/identifier`,xe=`${fs}/args`,lt=`${fs}/evaluate`,Gt=`${fs}/successCont`,Tn=`${fs}/failureCont`,sc=`${fs}/ensureCont`,uc=Symbol.for(\"effect/Effect/Yield\"),kr={pipe(){return te(this,arguments)},toJSON(){return{...this}},toString(){return K(this.toJSON(),{ignoreToString:!0,space:2})},[Je](){return this.toJSON()}},UO={[re](){return dp(this,Object.keys(this))},[ne](e){let t=Object.keys(this),r=Object.keys(e);if(t.length!==r.length)return!1;for(let n=0;nA(e,fs),Sp=e=>A(e,oc),gp=\"~effect/Cause\",Wu=\"~effect/Cause/Reason\",Ju=e=>A(e,gp),DO=e=>A(e,Wu),To=class{constructor(t){this[gp]=gp,this.reasons=t}pipe(){return te(this,arguments)}toJSON(){return{_id:\"Cause\",reasons:this.reasons.map(t=>t.toJSON())}}toString(){return`Cause(${K(this.reasons)})`}[Je](){return this.toJSON()}[ne](t){return Ju(t)&&this.reasons.length===t.reasons.length&&this.reasons.every((r,n)=>Z(r,t.reasons[n]))}[re](){return wo(this.reasons)}},NO=new WeakMap,qu=class{[Wu];annotations;_tag;constructor(t,r,n){if(this[Wu]=Wu,this._tag=t,r!==bp&&typeof n==\"object\"&&n!==null&&r.size>0){let o=NO.get(n);o&&(r=new Map([...o,...r])),NO.set(n,r)}this.annotations=r}annotate(t,r){if(t.mapUnsafe.size===0)return this;let n=new Map(this.annotations);if(t.mapUnsafe.forEach((s,a)=>{r?.overwrite!==!0&&n.has(a)||n.set(a,s)}),r?.overwrite!==!0&&n.size===this.annotations.size)return this;let o=Object.assign(Object.create(Object.getPrototypeOf(this)),this);return o.annotations=n,o}pipe(){return te(this,arguments)}toString(){return K(this)}[Je](){return this.toString()}},bp=new Map,ac=class extends qu{constructor(t,r=bp){super(\"Fail\",r,t),this.error=t}toString(){return`Fail(${K(this.error)})`}toJSON(){return{_tag:\"Fail\",error:this.error}}[ne](t){return fc(t)&&Z(this.error,t.error)&&Z(this.annotations,t.annotations)}[re](){return Ee(Pe(this._tag))(Ee(V(this.error))(V(this.annotations)))}},ls=e=>new To(e),p6=(e,t)=>{let r=new Map,n=[];for(let o of e.concat(t)){let s=V(o),a=r.get(s);if(a===void 0)r.set(s,[o]);else{if(a.some(i=>Z(i,o)))continue;a.push(o)}n.push(o)}return n},Ep=l(2,(e,t)=>{if(e.reasons.length===0)return t;if(t.reasons.length===0)return e;let r=new To(p6(e.reasons,t.reasons));return Z(e,r)?e:r}),Gb=(e,t)=>{let r=e.reasons.slice();for(let n of t.reasons)Zs(n)&&!r.some(o=>Zs(o)&&o.fiberId===n.fiberId&&o.annotations===n.annotations)&&r.push(n);return r.length===e.reasons.length?e:new To(r)},Fh=new To([]),Gu=e=>new To([new ac(e)]),ic=class extends qu{constructor(t,r=bp){super(\"Die\",r,t),this.defect=t}toString(){return`Die(${K(this.defect)})`}toJSON(){return{_tag:\"Die\",defect:this.defect}}[ne](t){return lc(t)&&Z(this.defect,t.defect)&&Z(this.annotations,t.annotations)}[re](){return Ee(Pe(this._tag))(Ee(V(this.defect))(V(this.annotations)))}},Vb=e=>new To([new ic(e)]),Vu=l(e=>Ju(e[0]),(e,t,r)=>t.mapUnsafe.size===0?e:new To(e.reasons.map(n=>n.annotate(t,r)))),fc=e=>e._tag===\"Fail\",lc=e=>e._tag===\"Die\",Zs=e=>e._tag===\"Interrupt\";function d6(e){return Gr(\"Effect.evaluate: Not implemented\")}var vn=e=>({...l6,[Jb]:e.op,[lt]:e[lt]??d6,[Gt]:e[Gt],[Tn]:e[Tn],[sc]:e[sc]}),Yn=e=>{let t=vn(e),r=function(n){this[xe]=n};return r.prototype=t,function(n){return new r(n)}},LO=e=>{let t={[oc]:oc,_tag:e.op,get[e.prop](){return this[xe]},...vn(e),toString(){return`${e.op}(${K(this[xe])})`},toJSON(){return{_id:\"Exit\",_tag:e.op,[e.prop]:this[xe]}},[ne](n){return Sp(n)&&n._tag===this._tag&&Z(this[xe],n[xe])},[re](){return Ee(Pe(e.op),V(this[xe]))}},r=function(n){this[xe]=n};return r.prototype=t,function(n){return new r(n)}},We=LO({op:\"Success\",prop:\"value\",[lt](e){let t=e.getCont(Gt);return t?t[Gt](this[xe],e,this):e.yieldWith(this)}}),Nh={key:\"effect/Cause/StackTrace\"},Zb={key:\"effect/Cause/InterruptorStackTrace\"},Nt=LO({op:\"Failure\",prop:\"cause\",[lt](e){let t=this[xe],r=!1;e.cache.stackFrame&&(t=Vu(t,{mapUnsafe:new Map([[Nh.key,e.cache.stackFrame]])}),r=!0);let n=e.getCont(Tn),o=e._interruptedCause;if(o&&e.interruptible){let s=!1;for(;n&&e.interruptible;)s||=Jb in n,n=e.getCont(Tn);s&&(t=ls(t.reasons.filter(a=>a._tag!==\"Fail\"))),t=Gb(t,o),r=!0}return n?n[Tn](t,e,r?void 0:this):e.yieldWith(r?Nt(t):this)}}),ko=e=>Nt(Gu(e)),Gr=e=>Nt(Vb(e)),se=Yn({op:\"WithFiber\",[lt](e){return this[xe](e)}}),$O=Yn({op:\"WithFiberSucceed\",[lt](e){let t=this[xe](e),r=e.getCont(Gt);return r?r[Gt](t,e):e.yieldWith(We(t))}}),m6=(function(){class e extends globalThis.Error{}let t=vn({op:\"YieldableError\",[lt](){return ko(this)}});return delete t.toString,Object.assign(e.prototype,t),e})(),Ip=(function(){let e=Symbol.for(\"effect/Data/Error/plainArgs\");return class extends m6{constructor(r){super(r?.message,r?.cause?{cause:r.cause}:void 0),r&&(Mh(this,r),Object.defineProperty(this,e,{value:r,enumerable:!1}))}toJSON(){return{...this[e],...this}}}})(),Ys=e=>{class t extends Ip{_tag=e}return t.prototype.name=e,t},yp=\"~effect/Cause/NoSuchElementError\",Uh=e=>A(e,yp),vo=class extends Ys(\"NoSuchElementError\"){[yp]=yp;constructor(t){super({message:t})}},cc=\"~effect/Cause/Done\",Dh=e=>A(e,cc),KO={[cc]:cc,_tag:\"Done\",value:void 0},pc=e=>e===void 0?KO:{[cc]:cc,_tag:\"Done\",value:e},h6=ko(KO),BO=e=>e===void 0?h6:ko(pc(e));var Lh=e=>vn({op:e.label,[lt]:e.evaluate});var ye={};An(ye,{Do:()=>Q6,all:()=>$6,andThen:()=>M6,as:()=>n_,asVoid:()=>R6,bind:()=>Y6,bindTo:()=>V6,composeK:()=>D6,contains:()=>J6,containsWith:()=>c_,exists:()=>G6,filter:()=>hc,filterMap:()=>j6,firstSomeOf:()=>O6,flatMap:()=>dc,flatMapNullishOr:()=>F6,flatten:()=>mc,fromIterable:()=>w6,fromNullOr:()=>oE,fromNullishOr:()=>vp,fromUndefinedOr:()=>nE,gen:()=>X6,getFailure:()=>C6,getOrElse:()=>Tp,getOrNull:()=>Zh,getOrThrow:()=>sE,getOrThrowWith:()=>Yh,getOrUndefined:()=>ps,getSuccess:()=>A6,isNone:()=>ge,isOption:()=>rf,isSome:()=>Ce,let:()=>Z6,lift2:()=>W6,liftNullishOr:()=>_6,liftPredicate:()=>q6,liftThrowable:()=>Oo,makeCombinerFailFast:()=>u_,makeEquivalence:()=>H6,makeOrder:()=>z6,makeReducer:()=>e4,makeReducerFailFast:()=>t4,map:()=>Vt,match:()=>Zt,none:()=>v,orElse:()=>T6,orElseResult:()=>k6,orElseSome:()=>v6,partitionMap:()=>B6,product:()=>s_,productMany:()=>L6,reduceCompact:()=>K6,some:()=>_,tap:()=>o_,toArray:()=>i_,toRefinement:()=>I6,void:()=>P6,zipLeft:()=>U6,zipRight:()=>N6,zipWith:()=>a_});function jO(e){return{combine:e}}function Qb(e,t,r){return{combine:e,initialValue:t,combineAll:r??(n=>{let o=t;for(let s of n)o=e(o,s);return o})}}var Kt=e=>(t,r)=>t===r||e(t,r),x6=(e,t)=>e===t,Wa=()=>x6;function WO(e){return Kt((t,r)=>{if(t.length!==r.length)return!1;for(let n=0;n{if(t.length!==r.length)return!1;for(let n=0;nl(3,(t,r,n)=>e(t,o=>({...o,[r]:n(o)}))),Kh=e=>l(2,(t,r)=>e(t,n=>({[r]:n}))),Bh=(e,t)=>l(3,(r,n,o)=>t(r,s=>e(o(s),a=>({...s,[n]:a}))));var JO=\"~effect/Option\",GO={[JO]:{_A:e=>e},...kr,[Symbol.iterator](){return new Ha(this)}},g6=Object.defineProperty(Object.assign(Object.create(GO),{_tag:\"Some\",_op:\"Some\",[ne](e){return jh(e)&&Xb(e)&&Z(this.value,e.value)},[re](){return Ee(V(this._tag))(V(this.value))},toString(){return`some(${K(this.value)})`},toJSON(){return{_id:\"Option\",_tag:this._tag,value:qt(this.value)}}}),\"valueOrUndefined\",{get(){return this.value}}),y6=V(\"None\"),S6=Object.assign(Object.create(GO),{_tag:\"None\",_op:\"None\",valueOrUndefined:void 0,[ne](e){return jh(e)&&Hh(e)},[re](){return y6},toString(){return\"none()\"},toJSON(){return{_id:\"Option\",_tag:this._tag}}}),jh=e=>A(e,JO),Hh=e=>e._tag===\"None\",Xb=e=>e._tag===\"Some\",wp=Object.create(S6),VO=function(e){this.value=e};VO.prototype=g6;var Ap=e=>new VO(e);var YO=\"~effect/Result\",QO={[YO]:{_A:e=>e,_E:e=>e},...kr,[Symbol.iterator](){return new Ha(this)}},b6=Object.assign(Object.create(QO),{_tag:\"Success\",_op:\"Success\",[ne](e){return zh(e)&&Qu(e)&&Z(this.success,e.success)},[re](){return Ee(V(this._tag))(V(this.success))},toString(){return`success(${K(this.success)})`},toJSON(){return{_id:\"Result\",_tag:this._tag,value:qt(this.success)}}}),E6=Object.assign(Object.create(QO),{_tag:\"Failure\",_op:\"Failure\",[ne](e){return zh(e)&&Yu(e)&&Z(this.failure,e.failure)},[re](){return Ee(V(this._tag))(V(this.failure))},toString(){return`failure(${K(this.failure)})`},toJSON(){return{_id:\"Result\",_tag:this._tag,failure:qt(this.failure)}}}),zh=e=>A(e,YO),Yu=e=>e._tag===\"Failure\",Qu=e=>e._tag===\"Success\",XO=function(e){this.failure=e};XO.prototype=E6;var Wh=e=>new XO(e),e_=function(e){this.success=e};e_.prototype=b6;var qh=e=>new e_(e),eE=e=>Qu(e)?wp:Ap(e.failure),tE=e=>Yu(e)?wp:Ap(e.success);function qa(e){return(t,r)=>t===r?0:e(t,r)}var r_=qa((e,t)=>eglobalThis.Number.isNaN(e)&&globalThis.Number.isNaN(t)?0:globalThis.Number.isNaN(e)?-1:globalThis.Number.isNaN(t)?1:eeqa((r,n)=>e(t(r),t(n)))),ef=rE(Qs,e=>e.getTime());var Jh=e=>l(2,(t,r)=>e(t,r)===-1),tf=e=>l(2,(t,r)=>e(t,r)===1),Gh=e=>l(2,(t,r)=>e(t,r)!==1),Vh=e=>l(2,(t,r)=>e(t,r)!==-1);var v=()=>wp,_=Ap,rf=jh,ge=Hh,Ce=Xb,Zt=l(2,(e,{onNone:t,onSome:r})=>ge(e)?t():r(e.value)),I6=e=>t=>Ce(e(t)),w6=e=>{for(let t of e)return _(t);return v()},A6=tE,C6=eE,Tp=l(2,(e,t)=>ge(e)?t():e.value),T6=l(2,(e,t)=>ge(e)?t():e),v6=l(2,(e,t)=>ge(e)?_(t()):e),k6=l(2,(e,t)=>ge(e)?Vt(t(),qh):Vt(e,Wh)),O6=e=>{let t=v();for(t of e)if(Ce(t))return t;return t},vp=e=>e==null?v():_(e),nE=e=>e===void 0?v():_(e),oE=e=>e===null?v():_(e),_6=e=>(...t)=>vp(e(...t)),Zh=Tp(Mb),ps=Tp(Zn),Oo=e=>(...t)=>{try{return _(e(...t))}catch{return v()}},Yh=l(2,(e,t)=>{if(Ce(e))return e.value;throw t()}),sE=Yh(()=>new Error(\"getOrThrow called on a None\")),Vt=l(2,(e,t)=>ge(e)?v():_(t(e.value))),n_=l(2,(e,t)=>Vt(e,()=>t)),R6=n_(void 0),P6=_(void 0);var dc=l(2,(e,t)=>ge(e)?v():t(e.value)),M6=l(2,(e,t)=>dc(e,r=>{let n=Jr(t)?t(r):t;return rf(n)?n:_(n)})),F6=l(2,(e,t)=>ge(e)?v():vp(t(e.value))),mc=dc(D),N6=l(2,(e,t)=>dc(e,()=>t)),U6=l(2,(e,t)=>o_(e,()=>t)),D6=l(2,(e,t)=>r=>dc(e(r),t)),o_=l(2,(e,t)=>dc(e,r=>Vt(t(r),()=>r))),s_=l(2,(e,t)=>Ce(e)&&Ce(t)?_([e.value,t.value]):v()),L6=l(2,(e,t)=>{if(ge(e))return v();let r=[e.value];for(let n of t){if(ge(n))return v();r.push(n.value)}return _(r)}),$6=e=>{if(Symbol.iterator in e){let r=[];for(let n of e){if(ge(n))return v();r.push(n.value)}return _(r)}let t={};for(let r of Object.keys(e)){let n=e[r];if(ge(n))return v();B(t,r,n.value)}return _(t)},a_=l(3,(e,t,r)=>Vt(s_(e,t),([n,o])=>r(n,o))),K6=l(3,(e,t,r)=>{let n=t;for(let o of e)Ce(o)&&(n=r(n,o.value));return n}),i_=e=>ge(e)?[]:[e.value],B6=l(2,(e,t)=>{if(ge(e))return[v(),v()];let r=t(e.value);return Yu(r)?[v(),_(r.failure)]:[_(r.success),v()]}),j6=l(2,(e,t)=>{if(ge(e))return v();let r=t(e.value);return Qu(r)?_(r.success):v()}),hc=l(2,(e,t)=>ge(e)?v():t(e.value)?_(e.value):v()),H6=e=>Kt((t,r)=>ge(t)?ge(r):ge(r)?!1:e(t.value,r.value)),z6=e=>qa((t,r)=>Ce(t)?Ce(r)?e(t.value,r.value):1:-1),W6=e=>l(2,(t,r)=>a_(t,r,e)),q6=l(2,(e,t)=>t(e)?_(e):v()),c_=e=>l(2,(t,r)=>ge(t)?!1:e(t.value,r)),J6=c_(xp()),G6=l(2,(e,t)=>ge(e)?!1:t(e.value)),V6=Kh(Vt),Z6=$h(Vt);var Y6=Bh(Vt,dc),Q6=_({}),X6=(...e)=>{let r=(e.length===1?e[0]:e[1].bind(e[0]))(),n=r.next();for(;!n.done;){let o=n.value;if(ge(o))return o;n=r.next(o.value)}return _(n.value)};function e4(e){return Qb((t,r)=>ge(t)?r:ge(r)?t:_(e.combine(t.value,r.value)),v())}function u_(e){return jO((t,r)=>ge(t)||ge(r)?v():_(e.combine(t.value,r.value)))}function t4(e){let t=u_(e).combine,r=_(e.initialValue);return Qb(t,r,n=>{let o=r;for(let s of n)if(o=t(o,s),ge(o))return o;return o})}var f_=\"~effect/Context/Service\",Et=function(){function e(){}let t=e;Object.setPrototypeOf(t,r4);let r=(n,o)=>(t.key=n,o?.defaultValue&&(t[iE]=iE,t.defaultValue=o.defaultValue),o?.make&&(t.make=o.make),o?.fiberCached&&l_.add(n),t);return arguments.length>0?r(arguments[0],arguments[1]):r},r4={[f_]:f_,...Lh({label:\"Service\",evaluate(e){return We(Me(e.context,this))}}),toJSON(){return{_id:\"Service\",key:this.key}},of(e){return e},context(e){return xc(this,e)},use(e){return se(t=>e(Me(t.context,this)))},useSync(e){return se(t=>We(e(Me(t.context,this))))}},l_=new Set,iE=\"~effect/Context/Reference\",p_=\"~effect/Context\",n4=8,Qh=(e,t,r,n,o)=>{let s=Object.create(s4);return s.cacheRoot=e??s,s.base=t,s.overlay=r,s.depth=n,s._flat=void 0,s.baseHits=0,s.maxDepth=o,s},cE=(e,t)=>{t&&(cE(e,t.parent),e.set(t.key,t.value))},d_=e=>{if(e._flat)return e._flat;if(!e.overlay)return e._flat=e.base;let t=new Map(e.base);return cE(t,e.overlay),e._flat=t},o4=(e,t)=>{let r=new Map(e.mapUnsafe);return t(r),Qh(void 0,r,void 0,0,e.maxDepth)},Xh=Symbol(),uE=(e,t)=>{let r=e;for(let o=r.overlay;o;o=o.parent)if(o.key===t)return o.value;let n=r.base.get(t);return n===void 0&&!r.base.has(t)?Xh:(r.overlay&&++r.baseHits>=r.base.size&&r.baseHits>=n4&&(r.base=d_(r),r.overlay=void 0,r.depth=0),n)},Xs=(e,t)=>{let r=t?.maxDepth;return Qh(void 0,e,void 0,0,Number.isInteger(r)&&r>=0?r:8)},s4={get mapUnsafe(){return d_(this)},...kr,[p_]:{_Services:e=>e},toJSON(){return{_id:\"Context\",services:Array.from(this.mapUnsafe).map(([e,t])=>({key:e,value:t}))}},[ne](e){if(!kp(e))return!1;let t=this.mapUnsafe,r=e.mapUnsafe;if(t.size!==r.size)return!1;for(let[n,o]of t)if(!r.has(n)||!Z(o,r.get(n)))return!1;return!0},[re](){return Lt(this.mapUnsafe.size)}},m_=(e,t)=>e.cacheRoot===t.cacheRoot,kp=e=>A(e,p_);var h_=e=>!!e[iE],Pr=()=>a4,a4=Xs(new Map),xc=(e,t)=>Xs(new Map([[e.key,t]])),dr=l(3,(e,t,r)=>i4(e,t.key,r)),i4=(e,t,r)=>{let n=e,o=l_.has(t)?void 0:n.cacheRoot;if(n.depth>=n.maxDepth){let s=new Map(n._flat??n.base);return n._flat||cE(s,n.overlay),s.set(t,r),Qh(o,s,void 0,0,n.maxDepth)}return Qh(o,n.base,{key:t,value:r,parent:n.overlay},n.depth+1,n.maxDepth)};var ex=l(2,(e,t)=>Op(e,t.key)),Op=(e,t)=>{let r=uE(e,t);return r===Xh?void 0:r},ds=l(2,(e,t)=>{let r=uE(e,t.key);if(r===Xh){if(h_(t))return x_(t);throw c4(t)}return r}),Me=ds,aE=\"~effect/Context/defaultValue\",x_=e=>aE in e?e[aE]:e[aE]=e.defaultValue(),c4=e=>{let t=new Error(`Service not found${e.key?`: ${String(e.key)}`:\"\"}`);if(t.stack){let r=t.stack.split(`\n`);r.splice(1,3),t.stack=r.join(`\n`)}return t},tx=l(2,(e,t)=>{let r=uE(e,t.key);return r!==Xh?_(r):h_(t)?_(x_(t)):v()}),rx=l(2,(e,t)=>e.mapUnsafe.size===0?t:t.mapUnsafe.size===0?e:o4(e,r=>t.mapUnsafe.forEach((n,o)=>r.set(o,n)))),g_=(...e)=>{let t=new Map;for(let r=0;r{t.set(o,n)});return Xs(t)};var Te=Et;var fE=e=>e.length>0;var It=e=>e>0?Math.floor(e):0,eo=e=>Math.max(1,It(e));var j=qh,q=Wh;var lE=e=>{if(Jr(e))try{return j(e())}catch(t){return q(t)}else try{return j(e.try())}catch(t){return q(e.catch(t))}};var y_=zh,ae=Yu,rt=Qu;var nf=l(2,(e,t)=>ae(e)?q(t(e.failure)):e),sr=l(2,(e,t)=>rt(e)?j(t(e.success)):e),mr=l(2,(e,{onFailure:t,onSuccess:r})=>ae(e)?t(e.failure):r(e.success));var _p=l(2,(e,t)=>ae(e)?t(e.failure):e.success);var f4=l(2,(e,t)=>{if(rt(e))return e.success;throw t(e.failure)}),ms=f4(D);var Yt=l(2,(e,t)=>ae(e)?q(e.failure):t(e.success));var pE=e=>{if(Symbol.iterator in e){let r=[];for(let n of e){if(ae(n))return n;r.push(n.success)}return j(r)}let t={};for(let r of Object.keys(e)){let n=e[r];if(ae(n))return n;B(t,r,n.success)}return j(t)};var S_=WO;var l4=(e,t)=>{let r=t?.length!==void 0?eo(t.length):1/0;return{[Symbol.iterator](){let n=0;return{next(){return nd4(l4(()=>e,{length:t}))),E_=e=>p4(e,1/0);var I_=e=>{let r=e[Symbol.iterator]().next();if(r.done)throw new Error(\"headUnsafe: empty iterable\");return r.value};var w_=l(2,(e,t)=>{let r=0;for(let n of e){let o=t(n,r);if(Th(o)){if(o)return _(n)}else if(Ce(o))return o;r++}return v()});var d4=e=>({[Symbol.iterator](){let t=e[Symbol.iterator](),r;function n(){for(;;){if(r===void 0){let s=t.next();if(s.done)return s;r=s.value[Symbol.iterator]()}let o=r.next();if(!o.done)return o;r=void 0}}return{next:n}}});var A_=l(2,(e,t)=>({[Symbol.iterator](){let r=e[Symbol.iterator](),n=0;return{next(){let o=r.next();for(;!o.done;){if(t(o.value,n++))return{done:!1,value:o.value};o=r.next()}return{done:!0,value:void 0}}}}}));var m4=l(2,(e,t)=>Object.hasOwn(e,t));var gc=l(2,(e,t)=>{let r={...e};for(let n of C_(e))B(r,n,t(e[n],n));return r});var C_=e=>Object.keys(e);var h4=e=>l(2,(t,r)=>{for(let n of C_(t))if(!m4(r,n)||!e(t[n],r[n]))return!1;return!0});var T_=e=>{let t=h4(e);return(r,n)=>t(r,n)&&t(n,r)};var nx=globalThis.Array;var ox=l(2,(e,t)=>{let r=eo(e),n=new nx(r);for(let o=0;oe<=t?ox(t-e+1,r=>e+r):[e];var wt=e=>nx.isArray(e)?e:nx.from(e);var sx=l(2,(e,t)=>[...e,t]),mE=l(2,(e,t)=>wt(e).concat(wt(t)));var v_=nx.isArray;var Mr=fE,yt=fE;function of(e){let t=Number(e);return String(t)===e&&Number.isInteger(t)&&t>=0&&t<2**32-1}function x4(e,t){return!Number.isFinite(e)||e<0||e>=t.length}var k_=l(2,(e,t)=>{let r=Math.floor(t);if(x4(r,e))throw new Error(`Index out of bounds: ${r}`);return e[r]});var ax=e=>e[e.length-1];var hE=w_;var g4=(e,t)=>{let r=V(t),n=e.get(r);if(n===void 0)return e.set(r,[t]),!0;for(let o of n)if(Z(o,t))return!1;return n.push(t),!0};var Qt=()=>[],Oe=e=>[e],kn=l(2,(e,t)=>e.map(t));var O_=e=>{let t=[];for(let r of e)Ce(r)&&t.push(r.value);return t};var ix=l(2,(e,t)=>{let r=wt(e),n=[];for(let o=0;o{let r=[],n=[],o=0;for(let s of e){let a=t(s,o++);rt(a)?r.push(a.success):n.push(a.failure)}return[r,n]});var __=Zu;var cx=e=>{let t=wt(e);if(t.length<2)return[...t];let r=new Map,n=[];for(let o of t)g4(r,o)&&n.push(o);return n};var fx=\"~effect/Duration\",ar=BigInt(0),U_=BigInt(1),y4=BigInt(2),S4=BigInt(10),R_=BigInt(24),ux=BigInt(60),lx=BigInt(1e3),ea=BigInt(1e6),af=BigInt(1e9),px=BigInt(6e10),dx=BigInt(36e11),mx=BigInt(864e11),D_=BigInt(6048e11),L_=e=>BigInt(Math.sign(e)*Math.round(Math.abs(e))),yE=e=>Number.isInteger(e)?BigInt(e)*ea:L_(e*1e6),P_=e=>hr(Number.isFinite(e)?L_(e):e),$_=(e,t)=>{let r=Number(e);if(Number.isFinite(r))return r/t;let n=BigInt(t);return Number(e/n)+Number(e%n)/t},gE=(e,t)=>{let r=e.indexOf(\".\");if(r===-1)return BigInt(e)*t;let n=e[0]===\"-\",o=e.slice(r+1),s=S4**BigInt(o.length),a=(BigInt(e.slice(n?1:0,r))*s+BigInt(o))*t;return b4(n?-a:a,s)},b4=(e,t)=>{let r=e=t?U_:ar);return e{let r=Number(e)*t;if(!Number.isFinite(r))return hr(r);let n=gE(e,BigInt(t)*ea);return hr(Number.isInteger(r)&&BigInt(r)*ea===n?r:n)};var E4=/^(-?\\d+(?:\\.\\d+)?)\\s+(nanos?|micros?|millis?|seconds?|minutes?|hours?|days?|weeks?)$/,ct=e=>{switch(typeof e){case\"number\":return na(e);case\"bigint\":return On(e);case\"string\":{if(e===\"Infinity\")return ra;if(e===\"-Infinity\")return cf;let t=E4.exec(e);if(!t)break;let[r,n,o]=t;if(o===\"nano\"||o===\"nanos\")return On(gE(n,U_));if(o===\"micro\"||o===\"micros\")return On(gE(n,lx));switch(o){case\"milli\":case\"millis\":return sf(n,1);case\"second\":case\"seconds\":return sf(n,1e3);case\"minute\":case\"minutes\":return sf(n,6e4);case\"hour\":case\"hours\":return sf(n,36e5);case\"day\":case\"days\":return sf(n,864e5);case\"week\":case\"weeks\":return sf(n,6048e5)}break}case\"object\":{if(e===null)break;if(fx in e)return e;if(Array.isArray(e)){if(e.length!==2||!e.every(lp))return F_(e);if(Number.isNaN(e[0])||Number.isNaN(e[1]))return ta;if(e[0]===-1/0||e[1]===-1/0)return cf;if(e[0]===1/0||e[1]===1/0)return ra;let s=e[0]*1e9+e[1];return Number.isFinite(s)&&Number.isInteger(e[0])&&Number.isInteger(e[1])?hr(BigInt(e[0])*af+BigInt(e[1])):P_(s)}let t=e,r=0;if(t.weeks&&(r+=t.weeks*6048e5),t.days&&(r+=t.days*864e5),t.hours&&(r+=t.hours*36e5),t.minutes&&(r+=t.minutes*6e4),t.seconds&&(r+=t.seconds*1e3),t.milliseconds&&(r+=t.milliseconds),!t.microseconds&&!t.nanoseconds){if(!Number.isFinite(r))return hr(r);let s=M_(t);return s===void 0||BigInt(r)*ea===s?hr(r):hr(s)}let n=r*1e6+(t.microseconds??0)*1e3+(t.nanoseconds??0),o=Number.isFinite(n)?M_(t):void 0;return o===void 0?P_(n):hr(o)}}return F_(e)},Ga=e=>!e||Number.isInteger(e),M_=e=>{if(!Ga(e.weeks)||!Ga(e.days)||!Ga(e.hours)||!Ga(e.minutes)||!Ga(e.seconds)||!Ga(e.milliseconds)||!Ga(e.microseconds)||!Ga(e.nanoseconds))return;let t=ar;return e.weeks&&(t+=BigInt(e.weeks)*D_),e.days&&(t+=BigInt(e.days)*mx),e.hours&&(t+=BigInt(e.hours)*dx),e.minutes&&(t+=BigInt(e.minutes)*px),e.seconds&&(t+=BigInt(e.seconds)*af),e.milliseconds&&(t+=BigInt(e.milliseconds)*ea),e.microseconds&&(t+=BigInt(e.microseconds)*lx),e.nanoseconds&&(t+=BigInt(e.nanoseconds)),t},F_=e=>{throw new Error(`Invalid Input: ${e}`)},K_=Oo(ct),N_={_tag:\"Millis\",millis:0},I4={_tag:\"Infinity\"},w4={_tag:\"NegativeInfinity\"},A4={[fx]:fx,[re](){switch(this.value._tag){case\"Millis\":return V(yE(this.value.millis));case\"Nanos\":return V(this.value.nanos);default:return mp(this.value)}},[ne](e){return Fp(e)&&T4(this,e)},toString(){switch(this.value._tag){case\"Infinity\":return\"Infinity\";case\"NegativeInfinity\":return\"-Infinity\";case\"Nanos\":return`${this.value.nanos} nanos`;case\"Millis\":return`${this.value.millis} millis`}},toJSON(){switch(this.value._tag){case\"Millis\":return{_id:\"Duration\",_tag:\"Millis\",millis:this.value.millis};case\"Nanos\":return{_id:\"Duration\",_tag:\"Nanos\",nanos:String(this.value.nanos)};case\"Infinity\":return{_id:\"Duration\",_tag:\"Infinity\"};case\"NegativeInfinity\":return{_id:\"Duration\",_tag:\"NegativeInfinity\"}}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},hr=e=>{let t=Object.create(A4);return typeof e==\"number\"?isNaN(e)||e===0||Object.is(e,-0)?t.value=N_:Number.isFinite(e)?Number.isInteger(e)?t.value={_tag:\"Millis\",millis:e}:t.value={_tag:\"Nanos\",nanos:yE(e)}:t.value=e>0?I4:w4:e===ar?t.value=N_:t.value={_tag:\"Nanos\",nanos:e},t},Fp=e=>A(e,fx),sn=e=>e.value._tag!==\"Infinity\"&&e.value._tag!==\"NegativeInfinity\",Sc=e=>{switch(e.value._tag){case\"Millis\":return e.value.millis===0;case\"Nanos\":return e.value.nanos===ar;case\"Infinity\":case\"NegativeInfinity\":return!1}},hx=e=>{switch(e.value._tag){case\"Millis\":return e.value.millis<0;case\"Nanos\":return e.value.nanos{switch(e.value._tag){case\"Infinity\":case\"NegativeInfinity\":return ra;case\"Millis\":return e.value.millis<0?hr(-e.value.millis):e;case\"Nanos\":return e.value.nanoshr(e);var na=e=>hr(e),uf=e=>hr(e*1e3);var Nr=e=>j_(ct(e),{onMillis:D,onNanos:t=>$_(t,1e6),onInfinity:()=>1/0,onNegativeInfinity:()=>-1/0}),hs=e=>j_(ct(e),{onMillis:t=>t/1e3,onNanos:t=>$_(t,1e9),onInfinity:()=>1/0,onNegativeInfinity:()=>-1/0});var yc=e=>{let t=ct(e);switch(t.value._tag){case\"Infinity\":case\"NegativeInfinity\":throw new Error(\"Cannot convert infinite duration to nanos\");case\"Nanos\":return t.value.nanos;case\"Millis\":return yE(t.value.millis)}},B_=Oo(yc);var j_=l(2,(e,t)=>{switch(e.value._tag){case\"Millis\":return t.onMillis(e.value.millis);case\"Nanos\":return t.onNanos(e.value.nanos);case\"Infinity\":return t.onInfinity();case\"NegativeInfinity\":return(t.onNegativeInfinity??t.onInfinity)()}}),H_=l(3,(e,t,r)=>e.value._tag===\"Infinity\"||e.value._tag===\"NegativeInfinity\"||t.value._tag===\"Infinity\"||t.value._tag===\"NegativeInfinity\"?r.onInfinity(e,t):e.value._tag===\"Millis\"?t.value._tag===\"Millis\"?r.onMillis(e.value.millis,t.value.millis):r.onNanos(yc(e),t.value.nanos):r.onNanos(e.value.nanos,yc(t)));var z_=(e,t)=>H_(e,t,{onMillis:(r,n)=>r===n,onNanos:(r,n)=>r===n,onInfinity:(r,n)=>r.value._tag===n.value._tag});var W_=l(2,(e,t)=>H_(e,t,{onMillis:(r,n)=>hr(r-n),onNanos:(r,n)=>hr(r-n),onInfinity:(r,n)=>{let o=r.value._tag,s=n.value._tag;return o===\"Infinity\"?s===\"Infinity\"?ta:ra:o===\"NegativeInfinity\"?s===\"NegativeInfinity\"?ta:cf:s===\"Infinity\"?cf:ra}}));var T4=l(2,(e,t)=>z_(e,t)),v4=e=>{if(e.value._tag===\"Infinity\")return{days:1/0,hours:1/0,minutes:1/0,seconds:1/0,millis:1/0,nanos:1/0};if(e.value._tag===\"NegativeInfinity\")return{days:-1/0,hours:-1/0,minutes:-1/0,seconds:-1/0,millis:-1/0,nanos:-1/0};let t=yc(e),r=t{if(e.value._tag===\"Infinity\")return\"Infinity\";if(e.value._tag===\"NegativeInfinity\")return\"-Infinity\";if(Sc(e))return\"0\";if(hx(e))return\"-\"+SE(C4(e));let t=v4(e),r=[];return t.days!==0&&r.push(`${t.days}d`),t.hours!==0&&r.push(`${t.hours}h`),t.minutes!==0&&r.push(`${t.minutes}m`),t.seconds!==0&&r.push(`${t.seconds}s`),t.millis!==0&&r.push(`${t.millis}ms`),t.nanos!==0&&r.push(`${t.nanos}ns`),r.join(\" \")},q_=e=>{if(!sn(e))return v();let t=yc(e),r=t(e===void 0?ar:BigInt(e)*r)+(t===void 0?ar:BigInt(t.padEnd(9,\"0\"))*(r/af)),J_=e=>{let t=k4.exec(e);if(t===null)return v();let[,r,n,o,s,a,i,c,u,f]=t;if(a!==void 0&&(i!==void 0||u!==void 0)||c!==void 0&&u!==void 0)return v();let p=Mp(n,void 0,D_)+Mp(o,void 0,mx)+Mp(s,a,dx)+Mp(i,c,px)+Mp(u,f,af),d=r===\"-\"?-p:p,m=Number(d/ea);return _(d%ea===ar&&Number.isSafeInteger(m)?na(m):On(d))};var bE=l(2,(e,t)=>r=>{let n=e(r);if(ae(n))return q(r);let o=t(n.success);return ae(o)?q(r):o}),G_=e=>t=>{let r=e(t);return ae(r)?v():_(r.success)};var ff=Te(\"effect/Scheduler\",{fiberCached:!0,defaultValue:()=>new bc}),Z_=e=>{let t=!1;return Promise.resolve().then(()=>{t||e()}),()=>{t=!0}},O4=\"setImmediate\"in globalThis?e=>{let t=globalThis.setImmediate(e);return()=>globalThis.clearImmediate(t)}:e=>{let t=setTimeout(e,0);return()=>clearTimeout(t)},Y_=e=>{try{return O4(e)}catch{return Z_(e)}},EE=class{buckets=[];scheduleTask(t,r){let n=this.buckets,o=n.length,s,a=0;for(;ar);a++)s=n[a];s&&s[0]===r?s[1].push(t):a===o?n.push([r,[t]]):n.splice(a,0,[r,[t]])}drain(){let t=this.buckets;return this.buckets=[],t}},bc=class{executionMode;setImmediate;constructor(t=\"async\",r){this.executionMode=t,this.setImmediate=r??(t===\"sync\"?Z_:Y_)}shouldYield(t){return t.currentOpCount>=t.cache.maxOpsBeforeYield}makeDispatcher(){return new IE(this.setImmediate)}},IE=class{tasks=new EE;running=void 0;setImmediate;constructor(t=Y_){this.setImmediate=t}scheduleTask(t,r){this.tasks.scheduleTask(t,r),this.running===void 0&&(this.running=this.setImmediate(this.afterScheduled))}afterScheduled=()=>{this.running=void 0,this.runTasks()};runTasks(){let t=this.tasks.drain();for(let r=0;r0;)this.running!==void 0&&(this.running(),this.running=void 0),this.runTasks()}},Q_=Te(\"effect/Scheduler/MaxOpsBeforeYield\",{fiberCached:!0,defaultValue:()=>2048}),X_=Te(\"effect/Scheduler/PreventSchedulerYield\",{fiberCached:!0,defaultValue:()=>!1});var an={};An(an,{Class:()=>xx,Error:()=>Np,TaggedClass:()=>_4,TaggedError:()=>Ut,taggedEnum:()=>R4});var xx=class extends ja{constructor(e){super(),e&&Mh(this,e)}},_4=e=>class extends xx{_tag=e},R4=()=>new Proxy({},{get(e,t,r){return t===\"$is\"?Wt:t===\"$match\"?P4:n=>({...n,_tag:t})}});function P4(){if(arguments.length===1){let r=arguments[0];return function(n){return r[n._tag](n)}}let e=arguments[0];return arguments[1][e._tag](e)}var Np=Ip,Ut=Ys;var eR=\"~effect/encoding/EncodingError\",ro=class extends Ut(\"EncodingError\"){[eR]=eR};var gx=e=>tR(typeof e==\"string\"?U4.encode(e):e),AE=e=>{switch(e){case 16:return F4();case 32:return N4();default:{let t=\"\";for(let r=e>>>3;r>0;r--)t+=M4();return t}}},ce=Uint8Array.from(\"0123456789abcdef\",e=>e.charCodeAt(0)),Ec=()=>Math.random()*4294967296>>>0,M4=()=>{let e=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15])},F4=()=>{let e=Ec(),t=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15],ce[t>>>28],ce[t>>>24&15],ce[t>>>20&15],ce[t>>>16&15],ce[t>>>12&15],ce[t>>>8&15],ce[t>>>4&15],ce[t&15])},N4=()=>{let e=Ec(),t=Ec(),r=Ec(),n=Ec();return String.fromCharCode(ce[e>>>28],ce[e>>>24&15],ce[e>>>20&15],ce[e>>>16&15],ce[e>>>12&15],ce[e>>>8&15],ce[e>>>4&15],ce[e&15],ce[t>>>28],ce[t>>>24&15],ce[t>>>20&15],ce[t>>>16&15],ce[t>>>12&15],ce[t>>>8&15],ce[t>>>4&15],ce[t&15],ce[r>>>28],ce[r>>>24&15],ce[r>>>20&15],ce[r>>>16&15],ce[r>>>12&15],ce[r>>>8&15],ce[r>>>4&15],ce[r&15],ce[n>>>28],ce[n>>>24&15],ce[n>>>20&15],ce[n>>>16&15],ce[n>>>12&15],ce[n>>>8&15],ce[n>>>4&15],ce[n&15])},CE=e=>{let t=new TextEncoder().encode(e);if(t.length%2!==0)return q(new ro({module:\"Hex\",kind:\"Decode\",input:e,message:`Length must be a multiple of 2, but is ${t.length}`}));try{let r=t.length/2,n=new Uint8Array(r);for(let o=0;osr(CE(e),t=>D4.decode(t)),U4=new TextEncoder,D4=new TextDecoder,L4=Array.from({length:256},(e,t)=>t.toString(16).padStart(2,\"0\")),tR=e=>{let t=\"\";for(let r=0;r{if(48<=e&&e<=57)return e-48;if(97<=e&&e<=102)return e-97+10;if(65<=e&&e<=70)return e-65+10;throw new TypeError(\"Invalid input\")};var kE=\"effect/Tracer/ParentSpan\",Ic=class extends Et()(kE,{fiberCached:!0}){},$4=e=>e;var yx=Te(\"effect/Tracer/DisablePropagation\",{defaultValue:ap}),oR=Te(\"effect/Tracer/CurrentTraceLevel\",{defaultValue:()=>\"Info\"}),sR=Te(\"effect/Tracer/MinimumTraceLevel\",{defaultValue:()=>\"All\"}),OE=\"effect/Tracer\",_E=Te(OE,{fiberCached:!0,defaultValue:()=>RE}),RE=$4({span:e=>new vE(e)}),vE=class{_tag=\"Span\";sampled;name;parent;annotations;links;startTime;kind;status;_traceId=void 0;_spanId=void 0;_attributes=void 0;_events=void 0;constructor(t){this.name=t.name,this.parent=t.parent,this.annotations=t.annotations,this.links=t.links,this.startTime=t.startTime,this.kind=t.kind,this.sampled=t.sampled,this.status={_tag:\"Started\",startTime:t.startTime}}get traceId(){return this._traceId??=ps(this.parent)?.traceId??AE(32)}get spanId(){return this._spanId??=AE(16)}get attributes(){return this._attributes??=new Map}get events(){return this._events??=[]}end(t,r){this.status._tag!==\"Ended\"&&(this.status={_tag:\"Ended\",endTime:t,exit:r,startTime:this.status.startTime})}attribute(t,r){this.status._tag!==\"Ended\"&&this.attributes.set(t,r)}event(t,r,n){this.status._tag!==\"Ended\"&&this.events.push([t,r,n??{}])}addLinks(t){this.status._tag!==\"Ended\"&&this.links.push(...t)}};var iR=\"effect/Metric/FiberRuntimeMetrics\";var cR=Te(\"effect/ErrorReporter/CurrentErrorReporters\",{defaultValue:()=>new Set}),Up=Te(\"effect/References/CurrentStackFrame\",{fiberCached:!0,defaultValue:Zn}),Sx=Te(\"effect/References/TracerEnabled\",{fiberCached:!0,defaultValue:Cn}),wc=Te(\"effect/References/TracerTimingEnabled\",{defaultValue:Cn}),Dp=Te(\"effect/References/TracerSpanAnnotations\",{defaultValue:()=>({})}),Lp=Te(\"effect/References/TracerSpanLinks\",{defaultValue:()=>[]}),oa=Te(\"effect/References/CurrentLogAnnotations\",{defaultValue:()=>({})}),PE=Te(\"effect/References/CurrentLogLevel\",{fiberCached:!0,defaultValue:()=>\"Info\"}),ME=Te(\"effect/References/MinimumLogLevel\",{fiberCached:!0,defaultValue:()=>\"Info\"}),FE=Te(\"effect/References/UnhandledLogLevel\",{defaultValue:()=>\"Error\"}),bx=Te(\"effect/References/CurrentLogSpans\",{defaultValue:()=>[]});var Va=e=>{if(e?.captureStackTrace===!1)return e;if(e?.captureStackTrace!==void 0&&typeof e.captureStackTrace!=\"boolean\")return e;let t=Co();if(t===0&&e?.captureStackTrace!==!0)return{...e,captureStackTrace:!1};pr(3);let r=new Error;return pr(t),{...e,captureStackTrace:j4(()=>r.stack)}},NE=e=>t=>{let r;return()=>{if(r!==void 0)return r;let n=t();if(!n)return;let o=n.split(`\n`);if(o[e]!==void 0)return r=o[e].trim(),r}},j4=NE(3);var Ex=class extends qu{constructor(t,r=bp){super(\"Interrupt\",r,\"Interrupted\"),this.fiberId=t}toString(){return`Interrupt(${this.fiberId})`}toJSON(){return{_tag:\"Interrupt\",fiberId:this.fiberId}}[ne](t){return Zs(t)&&this.fiberId===t.fiberId&&this.annotations===t.annotations}[re](){return Pe(`${this._tag}:${this.fiberId}`)}},xR=e=>new Ex(e),Ya=e=>new To([new Ex(e)]),kx=e=>e.reasons.some(fc),gR=e=>{let t=e.reasons.find(fc);return t?j(t):q(e)},hf=e=>{for(let t=0;te.reasons.some(lc),Ox=e=>xf(e)&&kx(e)?ls(e.reasons.map(t=>t._tag===\"Fail\"&&!Dh(t.error)?new ic(t.error,t.annotations):t)):e,cn=e=>xf(e)?q(Ox(e)):hf(e),SR=e=>{let t=e.reasons.find(lc);return t?j(t):q(e)},Gp=e=>{let t=e.reasons.find(lc);return t?j(t.defect):q(e)},_x=e=>e.reasons.some(Zs),bR=e=>{let t=e.reasons.find(Zs);return t?j(t):q(e)},Rx=e=>{let t;for(let r=0;r{let t=Rx(e);return ae(t)?H4:t.success},H4=new Set,Px=e=>e.reasons.length>0&&e.reasons.every(Zs),IR=e=>Xs(e.annotations),wR=e=>{let t=new Map;for(let r of e.reasons)if(r.annotations.size>0)for(let[n,o]of r.annotations)t.set(n,o);return Xs(t)},gf=l(2,(e,t)=>{let r=!1,n=e.reasons.map(o=>fc(o)?(r=!0,new ac(t(o.error),o.annotations)):o);return r?ls(n):e}),Mx=e=>{let t;for(let r of e.reasons){if(r._tag===\"Fail\")return r.error;r._tag===\"Die\"&&(t??=r)}return t!==void 0?t.defect:e.reasons.length>0?new globalThis.Error(\"All fibers interrupted without error\"):new globalThis.Error(\"Empty cause\")},qE=(e,t)=>{let r=[],n=[];if(e.reasons.length===0)return r;let o=Co();o!==0&&pr(1);try{for(let s of e.reasons){if(s._tag===\"Interrupt\"){n.push(s);continue}r.push(DE(s._tag===\"Die\"?s.defect:s.error,s.annotations,t))}if(r.length===0){let s=new Error(\"The fiber was interrupted by:\");s.name=\"InterruptCause\",s.stack=J4(s,n);let a=new globalThis.Error(\"All fibers interrupted without error\",{cause:s});a.name=\"InterruptError\",a.stack=`${a.name}: ${a.message}`,r.push(DE(a,n[0].annotations,t))}}finally{o!==0&&pr(o)}return r},DE=(e,t,r,n=new Set)=>{let o=typeof e,s;if(e&&o===\"object\"){n.add(e);let a=e.cause;if(s=new globalThis.Error(z4(e),{cause:a!==void 0&&!n.has(a)?DE(a,void 0,void 0,n):void 0}),typeof e.name==\"string\"&&(s.name=e.name),typeof e.stack==\"string\")s.stack=q4(e.stack,s,t);else{let i=`${s.name}: ${s.message}`;s.stack=t?LE(i,t):i}r?.includeCauseInStack&&(s.stack=CR(s));for(let i of Object.keys(e))i in s||(s[i]=e[i])}else{s=new globalThis.Error(e?o===\"string\"?e:nc(e):`Unknown error: ${e}`);let a=`${s.name}: ${s.message}`;s.stack=t?LE(a,t):a}return s},z4=e=>{if(typeof e.message==\"string\")return e.message;if(typeof e.toString==\"function\"&&e.toString!==Object.prototype.toString&&e.toString!==Array.prototype.toString)try{return e.toString()}catch{}return nc(e)},W4=/\\((.*)\\)/g,q4=(e,t,r)=>{let n=`${t.name}: ${t.message}`,o=(e.startsWith(n)?e.slice(n.length):e).split(`\n`),s=[n];for(let a=1;a{let r=t?.get(Nh.key);return r&&(e=`${e}\n${AR(r)}`),e},J4=(e,t)=>{let r=[`${e.name}: ${e.message}`];for(let n of t){let o=n.fiberId!==void 0?`#${n.fiberId}`:\"unknown\",s=n.annotations.get(Zb.key);r.push(` at fiber (${o})`),s&&r.push(AR(s))}return r.join(`\n`)},AR=e=>{let t=[],r=e,n=0;for(;r&&n<10;){let o=r.stack();if(o){let s=o.matchAll(W4),a=!1;for(let[,i]of s)a=!0,t.push(` at ${r.name} (${i})`);a||t.push(` at ${r.name} (${o.replace(/^at /,\"\")})`)}else t.push(` at ${r.name}`);r=r.parent,n++}return t.join(`\n`)},Fx=e=>qE(e).map(CR).join(`\n`),CR=e=>e.cause?`${e.stack} {\n${TR(e.cause,\" \")}\n}`:e.stack,TR=(e,t)=>{let r=e.stack.split(`\n`),n=`${t}[cause]: ${r[0]}`;for(let o=1,s=r.length;o{try{return globalThis.process?.getBuiltinModule?.(\"node:async_hooks\")?.AsyncResource}catch{return}})(),vR=()=>uR===void 0?void 0:new uR(\"effect/Fiber\"),sa=()=>globalThis[rc],lf=class{constructor(t,r=!0){this.setContext(t),this.id=++V4.id,this.currentOpCount=0,this.interruptible=r,this._stack=[],this._observers=void 0,this._exit=void 0,this._children=void 0,this._interruptedCause=void 0,this._yielded=void 0,this._running=!1,this._deferredInterrupt=!1,this._parent=void 0,this._asyncContext=void 0,this.cache.runtimeMetrics?.recordFiberStart(this.context)}get[JE](){return G4}get currentDispatcher(){return this._dispatcher??=this.cache.scheduler.makeDispatcher()}getRef(t){return Me(this.context,t)}addObserver(t){return this._exit?(t(this._exit),Wr):(this._observers===void 0?this._observers=[t]:this._observers.push(t),()=>this.removeObserver(t))}removeObserver(t){if(this._exit||this._observers===void 0)return;let r=this._observers.indexOf(t);r>=0&&this._observers.splice(r,1)}interruptUnsafe(t,r){if(this._exit)return;let n=Ya(t);this.cache.stackFrame&&(n=Vu(n,xc(Nh,this.cache.stackFrame))),r&&(n=Vu(n,r)),this._interruptedCause=this._interruptedCause?Gb(this._interruptedCause,n):n,this.interruptible&&(this._running?this._deferredInterrupt=!0:this.evaluate(Le(this._interruptedCause)))}pollUnsafe(){return this._exit}evaluate(t){if(this._exit)return;if(this._asyncContext!==void 0){let s=this._asyncContext;this._asyncContext=void 0;try{return s.runInAsyncScope(this.evaluate,this,t)}finally{s.emitDestroy()}}else if(this._yielded!==void 0){let s=this._yielded;this._yielded=void 0,s()}let r=this.runLoop(t);if(r===uc){this._asyncContext=vR();return}let n=$E.interruptChildren&&$E.interruptChildren(this);if(n!==void 0)return this.evaluate(oe(n,()=>r));if(this._exit=r,this.cache.runtimeMetrics?.recordFiberEnd(this.context,this._exit),this._parent&&(this._parent._children?.delete(this),this._parent=void 0),this._observers!==void 0){let s=this._observers;this._observers=void 0;for(let a=0;ai)}if(s=a.tracerContext?a.tracerContext(s,this):s[lt](this),s===uc){let i=this._yielded;if(oc in i)return this._deferredInterrupt=!1,this._yielded=void 0,i;if(this._deferredInterrupt){this._yielded=void 0,i();continue}return uc}}catch(a){if(!A(s,lt))return Gr(`Fiber.runLoop: Not a valid effect: ${String(s)}`);s=Gr(a)}}finally{this._running=n,globalThis[rc]=r}}getCont(t){if(this._deferredInterrupt)return this._deferredInterrupt=!1,Y4;for(;;){let r=this._stack.pop();if(!r)return;let n=r[sc];if(n!==void 0){let o=n.call(r,this);if(o)return o[t]=o,o}if(r[t])return r}}succeedWith(t){if((++this.currentOpCount&Q4-1)===0)return We(t);let r=this.getCont(Gt);return r?r[Gt](t,this):this.yieldWith(We(t))}yieldWith(t){return this._yielded=t,uc}children(){return this._children??=new Set}pipe(){return te(this,arguments)}setContext(t){let r=this.context;if(this.context=t,r!==void 0&&m_(r,t))return;let n=t.cacheRoot,o=n._fiberCache??=Z4(t);this.cache?.scheduler!==o.scheduler&&(this._dispatcher=void 0),this.cache=o}get currentSpanLocal(){let t=this.cache.span;return t?._tag===\"Span\"?t:void 0}},Z4=e=>{let t=Op(e,OE);return{scheduler:Me(e,ff),tracer:t,tracerContext:t?t.context:void 0,tracerEnabled:Me(e,Sx),span:Op(e,kE),logLevel:Me(e,PE),minimumLogLevel:Me(e,ME),stackFrame:Me(e,Up),runtimeMetrics:Op(e,iR),maxOpsBeforeYield:Me(e,Q_),preventYield:Me(e,X_)}},Y4={[Gt](e,t){return Le(t._interruptedCause)},[Tn](e,t){return Le(t._interruptedCause)}},Q4=32,$E={interruptChildren:void 0},Nx=e=>{if(!e.cache.stackFrame)return;let t=new Map;return t.set(Zb.key,e.cache.stackFrame),Xs(t)},X4=e=>{if(!(e._children===void 0||e._children.size===0))return pf(e._children)},GE=e=>{let t=e;return t._exit?z(t._exit):Dt(r=>t._exit?r(z(t._exit)):X(e.addObserver(n=>r(z(n)))))},Ux=e=>Dt(t=>{let r=e[Symbol.iterator](),n=[],o;function s(){let a=r.next();for(;!a.done;){if(a.value._exit){n.push(a.value._exit),a=r.next();continue}o=a.value.addObserver(i=>{n.push(i),s()});return}t(z(n))}return s(),X(()=>o?.())}),Ix=e=>{let t=e;return t._exit?t._exit:Dt(r=>t._exit?r(t._exit):X(e.addObserver(r)))},kR=e=>Dt(t=>{let r=Array.from(e);if(r.length===0)return t(z(Qt()));let n=new Array(r.length),o=Qt(),s=()=>{for(let c=0;c{if(a++,f._tag===\"Failure\")return i=!0,s(),t(f);n[c]=f.value,a===r.length&&t(z(n))};o.push(u),r[c].addObserver(u)}return X(()=>{i=!0,s()})}),Dx=e=>se(t=>OR(e,t.id)),OR=l(e=>A(e[0],JE),(e,t,r)=>se(n=>{let o=Nx(n);return o=o&&r?rx(o,r):o??r,e.interruptUnsafe(t,o),Zp(GE(e))})),pf=e=>se(t=>{let r=Nx(t),n=Qt();for(let o of e)o.interruptUnsafe(t.id,r),n.push(o);return Zp(Ux(n))});var z=We,Le=Nt,dt=ko,X=Yn({op:\"Sync\",[lt](e){let t=this[xe],r=t(),n=e.getCont(Gt);return n?n[Gt](r,e):e.yieldWith(We(r))}}),be=Yn({op:\"Suspend\",[lt](e){let t=this[xe];return t()}}),VE=l(e=>e.length>=2||rf(e[0]),(e,t)=>ge(e)?t?QE(t):dt(new vo(\"Effect.fromOption: Option.none\")):z(e.value)),yf=mr({onFailure:dt,onSuccess:z}),_R=e=>e==null?dt(new vo):z(e),ZE=Yn({op:\"Yield\",[lt](e){let t=!1;return e.currentDispatcher.scheduleTask(()=>{t||e.evaluate(Ur)},this[xe]??0),e.yieldWith(()=>{t=!0})}}),Sf=ZE(0),YE=e=>z(_(e)),Tc=z(v()),RR=e=>ge(e)?Tc:Fe(e.value,_),PR=e=>be(()=>Le(e())),Qa=e=>Gr(e),QE=e=>be(()=>dt(e())),Se=z(void 0);var MR=e=>{let t=typeof e==\"function\"?e:e.try,r=typeof e==\"function\"?n=>new mf(n,\"An error occurred in Effect.try\"):e.catch;return be(()=>{try{return z(t())}catch(n){return dt(r(n))}})};var XE=e=>eI(function(t,r){e(r).then(n=>t(z(n)),n=>t(Qa(n)))},e.length!==0),FR=e=>{let t=typeof e==\"function\"?e:e.try,r=typeof e==\"function\"?n=>new mf(n,\"An error occurred in Effect.tryPromise\"):e.catch;return eI(function(n,o){let s=a=>be(()=>{try{return dt(za(()=>r(a)))}catch(i){return Qa(i)}});try{t(o).then(a=>n(z(a)),a=>n(s(a)))}catch(a){n(s(a))}},t.length!==0)},e3=e=>se(t=>e(t.id)),NR=se(z),UR=e3(z),eI=(function(){let e=vn({op:\"Async\",[lt](r){let n=!1,o=!1,s=this.withSignal?new AbortController:void 0,a=this.register.call(r.cache.scheduler,i=>{n||(n=!0,o?r.evaluate(i):o=i)},s?.signal);return o!==!1?o:(o=!0,r.yieldWith(()=>{n=!0}),s===void 0&&a===void 0?uc:(r._stack.push(t3(()=>(n=!0,s?.abort(),a??Ur))),uc))}}),t=function(r,n){this.register=r,this.withSignal=n};return t.prototype=e,function(r,n){return new t(r,n)}})(),t3=Yn({op:\"AsyncFinalizer\",[sc](e){e.interruptible&&(e.interruptible=!1,e._stack.push(od))},[Tn](e,t){return _x(e)?oe(jP(Nt(e),this[xe]()),()=>Le(e)):Le(e)}}),Dt=e=>eI(e,e.length>=2),Lx=Dt(Wr),DR=(...e)=>{if(e.length===1){let n=e[0];return be(()=>Cc(n()))}let[t,r]=e;return be(()=>Cc(r.call(t.self)))},tI=(e,t)=>typeof e==\"function\"?e:t.shift().bind(e.self),rI=(e,...t)=>{let r=tI(e,t),n=t.length===0?function(){return be(()=>Cc(r.apply(this,arguments)))}:function(){let o=be(()=>Cc(r.apply(this,arguments)));for(let s=0;sObject.defineProperty(t,\"length\",{value:e,configurable:!0}),fR=NE(2),LR=function(){let e=typeof arguments[0]==\"string\",t=e?arguments[0]:\"Effect.fn\",r=e?arguments[1]:void 0,n=Co(),o;return n!==0&&(pr(2),o=new globalThis.Error,pr(n)),e?(s,...a)=>lR(t,s,o,a,e,r):lR(t,arguments[0],o,Array.prototype.slice.call(arguments,1),e,r)},lR=(e,t,r,n,o,s)=>{let a=tI(t,n),i=`${e} (definition)`,c=r?fR(()=>r.stack):Zn,u=f=>p=>({name:e,stack:f?fR(()=>f.stack):Zn,parent:{name:i,stack:c,parent:p}});return nI(a.length,function(...f){let p=be(()=>{let h=a.apply(this,arguments);return de(h)?h:Cc(h)});for(let h=0;hzE(p,h)):p,Up,u(m))})},$R=(e,...t)=>{let r=tI(e,t);return nI(r.length,t.length===0?function(){return pR(()=>r.apply(this,arguments))}:function(){let n=pR(()=>r.apply(this,arguments));for(let o of t)n=o(n,...arguments);return n})},pR=e=>{try{let t=e(),r;for(;;){let n=t.next(r);if(n.done)return z(n.value);let o=n.value;if(o&&o._tag===\"Success\"){r=o.value;continue}else{if(o&&o._tag===\"Failure\")return n.value;{let s=!0;return be(()=>s?(s=!1,oe(n.value,a=>Cc(t,a))):be(()=>Cc(e())))}}}}catch(t){return Qa(t)}},Cc=(function(){let e=vn({op:\"Iterator\",[Gt](r,n){let o=this.iterator;for(;;){let s=o.next(r);if(s.done)return z(s.value);if(Ve(s.value)){if(s.value._tag===\"Failure\")return s.value}else return n._stack.push(this),s.value;r=s.value.value}},[lt](r){return this[Gt](this.initial,r)}}),t=function(r,n){this.iterator=r,this.initial=n};return t.prototype=e,function(r,n){return new t(r,n)}})(),Rn=l(2,(e,t)=>new aa(e,oI,z(t))),$x=function(e){return e._stack.push(this),this[xe]},r3=vn({op:\"OnSuccess\",[lt]:$x}),aa=function(e,t,r){this[xe]=e,this[Gt]=t,this.payload=r};aa.prototype=r3;var oI=function(){return this.payload},KR=function(e,t){return t.succeedWith(this.payload)},Kx=(()=>{let e=Co();if(e===0)return!1;let t=\"~effect/Effect/stackProbe\",r={[t]:function(){return new Error}};pr(1);let n=r[t]();return pr(e),n.stack?.includes(\"[as \"+t+\"]\")===!0})(),n3=function(e,t){let r=this.payload;return t.succeedWith(Kx?r(e):za(()=>r(e)))},BR=function(e){let t=this.payload;return t(e)},o3=function(e){let t=this.payload;return new aa(t(e),KR,e)},s3=function(e){return new aa(this.payload,KR,e)},bf=e=>Fe(e,_),jR=e=>ed(e,{onFailure:z,onSuccess:dt}),xs=l(2,(e,t)=>new aa(e,de(t)?oI:BR,t)),Vp=l(2,(e,t)=>new aa(e,de(t)?s3:o3,t)),Zp=e=>new aa(e,oI,Ur),HR=e=>un(e,dt),sI=(e,t)=>se(r=>{let n=new Set;return oi(r,()=>n.size===0?void 0:pf(n)),Dt(o=>{let s=wt(e),a=s.length,i=0,c=!1,u=[],f=(p,d,m)=>{if(i++,p._tag===\"Failure\"){u.push(...p.cause.reasons),i>=a&&o(Le(Ox(ls(u))));return}let h=!c;c=!0,o(p),h&&t?.onWinner&&t.onWinner({fiber:d,index:m,parentFiber:r})};for(let p=0;p{n.delete(d),f(m,d,p)}),c)break}})}),aI=(e,t)=>se(r=>{let n=new Set;return oi(r,()=>n.size===0?void 0:pf(n)),Dt(o=>{let s=!1,a=0;for(let i of e){if(s)break;let c=a++,u=_c(r,i,!0,!0,!1);n.add(u),u.addObserver(f=>{n.delete(u);let p=!s;s=!0,o(f),p&&t?.onWinner&&t.onWinner({fiber:u,index:c,parentFiber:r})})}})}),zR=l(e=>de(e[1]),(e,t,r)=>sI([e,t],r)),iI=l(e=>de(e[1]),(e,t,r)=>aI([e,t],r)),oe=l(2,(e,t)=>new aa(e,BR,t)),WR=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?t.onSuccess(e.value):t.onFailure(e.cause):_o(e,t)),Ve=e=>e[oc]!==void 0,qR=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?t(e.value):e:oe(e,t)),JR=e=>oe(e,D),Fe=l(2,(e,t)=>new aa(e,n3,t)),GR=l(2,(e,t)=>Ve(e)?lI(e,t):Fe(e,t)),VR=l(2,(e,t)=>Ve(e)?pI(e,t):EI(e,t)),ZR=l(2,(e,t)=>Ve(e)?dI(e,t):II(e,t)),YR=l(2,(e,t)=>{if(Ve(e)){if(e._tag===\"Success\")return e;let r=cn(e.cause);return ae(r)?Nt(r.failure):t(r.success)}return ti(e,t)}),Ef=e=>Nt(Ya(e)),Xa=e=>e._tag===\"Success\",QR=e=>e._tag===\"Success\"?j(e):q(e),XR=e=>e._tag===\"Success\"?j(e.value):q(e),cI=e=>e._tag===\"Failure\",eP=e=>e._tag===\"Failure\"?j(e):q(e),Yp=e=>e._tag===\"Failure\"?j(e.cause):q(e),uI=bE(Yp,hf),tP=bE(Yp,Gp),fI=e=>e._tag===\"Failure\"&&_x(e.cause),rP=e=>e._tag===\"Failure\"&&xf(e.cause),nP=e=>e._tag===\"Failure\"&&kx(e.cause),Ur=We(void 0),lI=l(2,(e,t)=>e._tag===\"Success\"?We(t(e.value)):e),pI=l(2,(e,t)=>e._tag===\"Success\"?e:Nt(gf(e.cause,t))),dI=l(2,(e,t)=>e._tag===\"Success\"?We(t.onSuccess(e.value)):Nt(gf(e.cause,t.onFailure))),a3=l(2,(e,t)=>Xa(e)?We(t):e),oP=l(2,(e,t)=>Xa(e)?t:e),sP=l(2,(e,t)=>Xa(e)?t.onSuccess(e.value):t.onFailure(e.cause)),aP=a3(void 0),mI=e=>{let t=[];for(let r of e)r._tag===\"Failure\"&&t.push(...r.cause.reasons);return t.length===0?Ur:Nt(ls(t))},iP=e=>Xa(e)?_(e.value):v(),cP=e=>cI(e)?_(e.cause):v(),uP=e=>{let t=uI(e);return ae(t)?v():_(t.success)},fP=e=>e,lP=e=>se(t=>z(tx(t.context,e))),i3=e=>se(t=>VE(tx(t.context,e))),If=l(2,(e,t)=>se(r=>{let n=r.context,o=t(n);return n===o||(r.setContext(o),oi(r,()=>{r.setContext(n)})),e})),ia=l(3,(e,t,r)=>If(e,n=>{let o=ds(n,t),s=r(o);return o===s?n:dr(n,t,s)})),pP=(e,t,r)=>Oc(se(n=>{let o=ds(n.context,e),s=t(o);return n.setContext(dr(n.context,e,s)),ni(ds(n.context,ri),a=>{let i=tx(n.context,e);if(ge(i))return Se;let c=i.value,u;if(r?.reset===void 0){if(c!==s)return Se;u=o}else u=r.reset(o,s,c);return n.setContext(dr(n.context,e,u)),Se})})),hI=()=>c3,c3=se(e=>z(e.context)),ei=e=>se(t=>e(t.context)),dP=l(2,(e,t)=>If(e,gt(t))),Pn=l(2,(e,t)=>Ve(e)?e:If(e,rx(t))),Lr=function(){return arguments.length===1?l(2,(e,t)=>dR(e,arguments[0],t)):l(3,(e,t,r)=>dR(e,t,r)).apply(this,arguments)},dR=(e,t,r)=>If(e,dr(t,r)),Bx=l(3,(e,t,r)=>oe(r,n=>Lr(e,t,n))),mP=l(e=>de(e[1]),(e,t,r)=>xI(e,t,(n,o)=>[n,o],r)),xI=l(e=>de(e[1]),(e,t,r,n)=>n?.concurrent?Fe(sd([e,t],{concurrency:2}),([o,s])=>r(o,s)):oe(e,o=>Fe(t,s=>r(o,s)))),hP=l(e=>de(e[0]),(e,t,r)=>DI(e,t,r?n=>dt(r(n)):()=>dt(new vo))),xP=l(2,(e,t)=>oe(t,r=>r?bf(e):Tc)),gI=l(2,(e,t)=>Array.from({length:t},()=>e)),gP=l(e=>de(e[0]),(e,t,r)=>sd(gI(e,t),r)),yP=l(e=>de(e[0]),(e,t)=>si({while:Cn,body:gt(t?.disableYield?e:oe(e,r=>Sf)),step:Wr})),un=l(2,(e,t)=>new SP(e,t.length!==1?r=>t(r):t)),u3=vn({op:\"OnFailure\",[lt]:$x}),SP=function(e,t){this[xe]=e,this[Tn]=t};SP.prototype=u3;var yI=l(3,(e,t,r)=>un(e,n=>t(n)?r(n):Le(n))),ca=l(3,(e,t,r)=>un(e,n=>{let o=t(n);return ae(o)?Le(o.failure):r(o.success,n)})),ti=l(2,(e,t)=>ca(e,cn,r=>t(r))),bP=e=>ed(e,{onFailure:t=>Uh(t)?Tc:dt(t),onSuccess:YE}),EP=l(2,(e,t)=>ca(e,Gp,t)),IP=l(2,(e,t)=>un(e,r=>xs(t(r),Le(r)))),wP=l(3,(e,t,r)=>yI(e,t,n=>xs(r(n),Le(n)))),jx=l(3,(e,t,r)=>un(e,n=>{let o=t(n);return ae(o)?Le(n):xs(r(o.success,n),Le(n))})),SI=l(2,(e,t)=>jx(e,hf,r=>t(r))),AP=l(3,(e,t,r)=>{let n=Array.isArray(t)?o=>A(o,\"_tag\")&&t.includes(o._tag):Wt(t);return SI(e,o=>n(o)?r(o):Se)}),CP=l(2,(e,t)=>jx(e,Gp,r=>t(r))),Qp=l(e=>de(e[0]),(e,t,r,n)=>un(e,o=>{let s=cn(o);return ae(s)?Le(s.failure):t(s.success)?r(s.success):n?n(s.success):Le(o)})),Hx=l(e=>de(e[0]),(e,t,r,n)=>un(e,o=>{let s=cn(o);if(ae(s))return Le(s.failure);let a=t(s.success);return ae(a)?n?n(a.failure):Le(o):r(a.success)})),bI=l(e=>de(e[0]),(e,t,r,n)=>{let o=Array.isArray(t)?s=>A(s,\"_tag\")&&t.includes(s._tag):Wt(t);return Qp(e,o,r,n)}),TP=l(e=>de(e[0]),(e,t,r)=>{let n;return Hx(e,o=>(n??=Object.keys(t),A(o,\"_tag\")&&qr(o._tag)&&n.includes(o._tag)?j(o):q(o)),o=>t[o._tag](o),r)}),vP=l(e=>de(e[0]),(e,t,r,n,o)=>Qp(e,s=>Wt(s,t)&&A(s,\"reason\")&&(o!==void 0||Wt(s.reason,r)),s=>{let a=s.reason;return Wt(a,r)?n(a,s):o?o(a,s):dt(s)})),kP=l(e=>de(e[0]),(e,t,r,n)=>{let o;return Qp(e,s=>Wt(s,t)&&A(s,\"reason\")&&A(s.reason,\"_tag\")&&qr(s.reason._tag)&&(n!==void 0||(o??=Object.keys(r)).includes(s.reason._tag)),s=>{let a=s.reason;return o??=Object.keys(r),o.includes(a._tag)?r[a._tag](a,s):n?n(a,s):dt(s)})}),OP=l(2,(e,t)=>Hx(e,r=>Wt(r,t)&&A(r,\"reason\")?j(r.reason):q(r),dt)),EI=l(2,(e,t)=>un(e,r=>Le(gf(r,t)))),II=l(2,(e,t)=>_o(e,{onFailure:r=>Le(gf(r,t.onFailure)),onSuccess:r=>X(()=>t.onSuccess(r))})),wI=e=>ti(e,Qa),_P=l(2,(e,t)=>ti(e,r=>X(()=>t(r)))),RP=e=>be(()=>{let t=e[Symbol.iterator](),r=t.next();if(r.done)return Qa(new Error(\"Received an empty collection of effects\"));function n(o){let s=t.next();return s.done?o.value:ti(o.value,a=>n(s))}return n(r)}),AI=e=>ti(e,t=>oe(Sf,()=>AI(e))),Xp=e=>e===\"Unhandled\"?(...t)=>se(r=>{let n=r.getRef(FE);return n===void 0?Se:Ro(n)(...t)}):Ro(e===!0?void 0:e),PP=l(e=>de(e[0]),(e,t)=>{if(!t?.log)return ed(e,{onFailure:n=>Se,onSuccess:n=>Se});let r=Xp(t.log);return _o(e,{onFailure(n){let o=cn(n);return ae(o)?Le(o.failure):t.message===void 0?r(n):r(t.message,n)},onSuccess:n=>Se})}),zx=l(e=>de(e[0]),(e,t)=>{if(!t?.log)return _o(e,{onFailure:n=>Se,onSuccess:n=>Se});let r=Xp(t.log);return _o(e,{onFailure:n=>t.message===void 0?r(n):r(t.message,n),onSuccess:n=>Se})}),MP=e=>Wx(e,{onFailure:v,onSuccess:_}),Za=e=>td(e,{onFailure:q,onSuccess:j}),_o=l(2,(e,t)=>new FP(e,t.onSuccess.length!==1?r=>t.onSuccess(r):t.onSuccess,t.onFailure.length!==1?r=>t.onFailure(r):t.onFailure)),f3=vn({op:\"OnSuccessAndFailure\",[lt]:$x}),FP=function(e,t,r){this[xe]=e,this[Gt]=t,this[Tn]=r};FP.prototype=f3;var l3=function(e,t){let r=this.payload;return t.succeedWith(Kx?r.onSuccess(e):za(()=>r.onSuccess(e)))},NP=(e,t)=>{let r=vn({op:e,[lt]:$x,[Gt]:l3,[Tn]:t}),n=function(o,s){this[xe]=o,this.payload=s};return n.prototype=r,n},p3=NP(\"Match\",function(e,t){let r=cn(e);if(ae(r))return Le(r.failure);let n=this.payload;return t.succeedWith(Kx?n.onFailure(r.success):za(()=>n.onFailure(r.success)))}),d3=NP(\"MatchCause\",function(e,t){let r=this.payload;return t.succeedWith(Kx?r.onFailure(e):za(()=>r.onFailure(e)))}),CI=l(2,(e,t)=>new d3(e,t)),ed=l(2,(e,t)=>_o(e,{onFailure:r=>{let n=cn(r);return ae(n)?Le(n.failure):t.onFailure(n.success)},onSuccess:t.onSuccess})),Wx=l(2,(e,t)=>new p3(e,t)),td=l(2,(e,t)=>{if(Ve(e)){if(e._tag===\"Success\")return We(t.onSuccess(e.value));let r=cn(e.cause);return ae(r)?Nt(r.failure):We(t.onFailure(r.success))}return Wx(e,t)}),UP=l(2,(e,t)=>Ve(e)?e._tag===\"Success\"?We(t.onSuccess(e.value)):We(t.onFailure(e.cause)):CI(e,t)),rd=e=>Ve(e)?We(e):m3(e),m3=Yn({op:\"Exit\",[lt](e){return e._stack.push(this),this[xe]},[Gt](e,t,r){return t.succeedWith(r??We(e))},[Tn](e,t,r){return t.succeedWith(r??Nt(e))}}),DP=td({onFailure:()=>!0,onSuccess:()=>!1}),LP=td({onFailure:()=>!1,onSuccess:()=>!0}),$P=l(2,(e,t)=>xs(Af(t),e)),TI=l(2,(e,t)=>oe(vI(e,t.duration),r=>ge(r)?t.orElse():z(r.value))),h3=e=>new jp(`Operation timed out after '${SE(e)}'`),KP=l(2,(e,t)=>{let r=ct(t);return TI(e,{duration:r,orElse:()=>dt(h3(r))})}),vI=l(2,(e,t)=>iI(bf(e),Rn(Af(t),v()))),BP=e=>Mo(t=>{let r=t.monotonicTimeNanosUnsafe();return Fe(e,n=>[On(t.monotonicTimeNanosUnsafe()-r),n])}),KE=\"~effect/Scope\",BE=\"~effect/Scope/Closeable\",ri=Et(\"effect/Scope\"),kI=(e,t)=>se(r=>(S3(r),qx(e,t)??Se)),qx=(e,t)=>{let r=e.state;if(r._tag===\"Closed\"||(e.state={_tag:\"Closed\",exit:t},e.parent!==void 0&&Ax(e.parent,e),r._tag===\"Empty\"))return;if(r.finalizer!==void 0)return wx(r.finalizer,t);let n=r.finalizers;return n.size===1?wx(n.values().next().value,t):x3(e,n,t)},wx=(e,t)=>{try{return e(t)}catch(r){return Gr(r)}},jP=(e,t)=>Xa(e)?t:un(t,r=>Le(Ox(Ep(e.cause,r)))),x3=rI(function*(e,t,r){let n=[],o=[],s=Array.from(t),a=sa();for(let i=s.length-1;i>=0;i--){let[c,u]=s[i];e.strategy===\"sequential\"?n.push(yield*rd(wx(u,r))):c!==a&&o.push(_c(a,wx(u,r),!0,!0,\"inherit\"))}return o.length>0&&(n=yield*Ux(o)),yield*mI(n)});var HP=(e,t)=>{let r=zP(t,e);return e.state._tag===\"Closed\"?(r.state=e.state,r):(wf(e,r,n=>kI(r,n)),r)},ni=(e,t)=>be(()=>e.state._tag===\"Closed\"?t(e.state.exit):(wf(e,{},t),Se)),Jx=(e,t)=>ni(e,gt(t)),wf=(e,t,r)=>{if(e.state._tag===\"Empty\")e.state={_tag:\"Open\",finalizerKey:t,finalizer:r,finalizers:void 0};else if(e.state._tag===\"Open\"){let n=e.state;n.finalizer!==void 0&&(n.finalizers=new Map([[n.finalizerKey,n.finalizer]]),n.finalizerKey=void 0,n.finalizer=void 0),n.finalizers.set(t,r)}},Ax=(e,t)=>{if(e.state._tag!==\"Open\")return;let r=e.state;r.finalizerKey===t?e.state=jE:r.finalizers!==void 0&&(r.finalizers.delete(t),r.finalizers.size===0&&(e.state=jE))},Gx=e=>zP(e,void 0),zP=(e=\"sequential\",t)=>({[BE]:BE,[KE]:KE,strategy:e,parent:t,state:jE}),jE={_tag:\"Empty\"};var vc=ri,WP=Lr(ri),OI=e=>se(t=>{let r=t.context,n=Gx();return t.setContext(dr(t.context,ri,n)),oi(t,o=>(t.setContext(r),qx(n,o))),e});var Vx=e=>be(()=>{let t=Gx();return Mn(e(t),r=>be(()=>qx(t,r)??Se))}),kc=(e,t,r)=>ei(n=>no(o=>oe(vc,s=>Vp(r?.interruptible?o(e):e,a=>ni(s,i=>Pn(t(a,i),n)))))),_I=e=>oe(vc,t=>ei(r=>ni(t,n=>Pn(e(n),r)))),qP=(function(){let e=vn({op:\"OnExit\",[lt](r){return r._stack.push(this),this.effect},[sc](r){r.interruptible&&this.interruptible!==!0&&(r._stack.push(od),r.interruptible=!1)},[Gt](r,n,o){o??=We(r);let s;try{s=this.onExit(o)}catch(a){s=Gr(a)}return s?oe(s,a=>o):o},[Tn](r,n,o){o??=Nt(r);let s;try{s=this.onExit(o)}catch(a){s=Gr(a)}return s?oe(jP(o,s),a=>o):o}}),t=function(r,n,o){this.effect=r,this.onExit=n,this.interruptible=o};return t.prototype=e,t})(),Po=(e,t,r)=>new qP(e,t,r),oi=(e,t)=>{e._stack.push(new qP(void 0,t,void 0))},Mn=l(2,Po),JP=l(2,(e,t)=>Mn(e,r=>t)),RI=l(3,(e,t,r)=>Mn(e,n=>t(n)?r(n):Se)),PI=l(3,(e,t,r)=>Mn(e,n=>{let o=t(n);return ae(o)?Se:r(o.success,n)})),MI=l(2,(e,t)=>PI(e,Yp,t)),GP=l(3,(e,t,r)=>RI(e,n=>n._tag!==\"Failure\"?!1:t(n.cause),n=>r(n.cause))),FI=l(3,(e,t,r)=>Mn(e,n=>{if(n._tag!==\"Failure\")return Se;let o=t(n.cause);return ae(o)?Se:r(o.success,n.cause)})),VP=l(2,(e,t)=>FI(Rx,t)(e)),nd=(e,t,r)=>no(n=>oe(e,o=>Po(be(()=>n(t(o))),s=>r(o,s),!0))),ZP=e=>kc(e,t=>A(t,Symbol.asyncDispose)?XE(()=>t[Symbol.asyncDispose]()):X(()=>t[Symbol.dispose]())),NI=l(2,(e,t)=>X(()=>YP(e,typeof t==\"function\"?r=>Nr(ct(t(r))):gt(Nr(ct(t)))))),g3=gt(1/0),YP=(e,t)=>{let r=0,n,o,s=(a,i)=>(i.awaiters++,oi(a,()=>{if(!(--i.awaiters>0||i.done))return o===i&&(o=void 0),Dx(i.fiber)}),Ix(i.fiber));return[se(a=>{if(o!==void 0)return a===o.fiber?Ix(o.fiber):s(a,o);if(n!==void 0&&(r===1/0||a.getRef(Dr).currentTimeMillisUnsafe(){if(c.done=!0,o!==c||(o=void 0,fI(f)))return;let p=t(f);r=p===1/0?1/0:i.currentTimeMillisUnsafe()+p,n=f})),c.fiber._exit??u}),X(()=>{o=void 0,n=void 0})]},QP=l(2,(e,t)=>Fe(NI(e,t),r=>r[0])),XP=e=>X(()=>YP(e,g3)[0]),eM=se(e=>Le(Ya(e.id))),Oc=e=>se(t=>(t.interruptible&&(t.interruptible=!1,t._stack.push(od)),e)),tM=Yn({op:\"SetInterruptible\",[sc](e){if(e.interruptible=this[xe],e._interruptedCause&&e.interruptible)return()=>Le(e._interruptedCause)}}),od=tM(!0),y3=tM(!1),rM=e=>{if(e.interruptible=!0,e._stack.push(y3),e._interruptedCause)return Le(e._interruptedCause)},S3=e=>{let t=e;t.interruptible&&(t.interruptible=!1,t._stack.push(od))};var Zx=e=>se(t=>t.interruptible?e:rM(t)??e),no=e=>se(t=>t.interruptible?(t.interruptible=!1,t._stack.push(od),e(Zx)):e(D)),nM=e=>se(t=>{if(t.interruptible)return e(D);let r=rM(t),n=e(Oc);return r??n}),oM=Fe(kc(X(()=>new AbortController),e=>X(()=>e.abort())),e=>e.signal),sd=(e,t)=>Js(e)?t?.mode===\"result\"?_n(e,Za,t):_n(e,D,t):t?.discard?t.mode===\"result\"?_n(Object.values(e),Za,t):_n(Object.values(e),D,t):be(()=>Fe(_n(Object.entries(e),([r,n])=>Fe(t?.mode===\"result\"?Za(n):n,o=>[r,o]),{concurrency:t?.concurrency}),Object.fromEntries)),UI=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>Fe(_n(e,(n,o)=>Za(t(n,o)),r),n=>xE(n,D))),sM=l(3,(e,t,r)=>{let n=wt(e);return n.length===0?X(t):be(()=>{let o=0,s=t();return Fe(si({while:()=>or(s,n[o],o),step(a){s=a,o++}}),()=>s)})}),aM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>oe(UI(e,t,{concurrency:r?.concurrency}),([n,o])=>Mr(o)?dt(o):r?.discard?Se:z(n))),iM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=e[Symbol.iterator](),n=r.next();return n.done?z(v()):cM(r,0,t,n.value)})),cM=(e,t,r,n)=>oe(r(n,t),o=>{if(o)return z(_(n));let s=e.next();return s.done?z(v()):cM(e,t+1,r,s.value)}),uM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=e[Symbol.iterator](),n=r.next();return n.done?z(v()):fM(r,0,t,n.value)})),fM=(e,t,r,n)=>oe(r(n,t),o=>{if(rt(o))return z(_(o.success));let s=e.next();return s.done?z(v()):fM(e,t+1,r,s.value)}),si=Yn({op:\"While\",[Gt](e,t){return this[xe].step(e),this[xe].while()?(t._stack.push(this),this[xe].body()):Ur},[lt](e){return this[xe].while()?(e._stack.push(this),this[xe].body()):Ur}}),_n=l(e=>typeof e[1]==\"function\",(e,t,r)=>be(()=>{let n=ad(r?.concurrency);if(n===1)return b3(e,t,r);let o=wt(e),s=o.length;if(s===0)return r?.discard?Se:z([]);let a=r?.discard?void 0:new Array(s),i=E3({f:t,out:a},o,{concurrency:n});return i?Rn(i,a):z(a)})),lM=e=>oe(e,t=>{let r=t[Symbol.iterator]().next();return r.done?dt(new vo):z(r.value)}),b3=(e,t,r)=>be(()=>{let n=r?.discard?void 0:[],o=e[Symbol.iterator](),s=o.next(),a=0;return Rn(si({while:()=>!s.done,body:()=>t(s.value,a++),step:i=>{n&&n.push(i),s=o.next()}}),n)}),ad=e=>e===\"unbounded\"?Number.POSITIVE_INFINITY:Math.max(1,e??1),Yx=()=>e=>{let t=e.onItem,r=e.step,n=(s,a,i,c,u)=>oe(rd(u),f=>r(s,a[i],f,i)??o(s,a,i+1,c)??Se),o=(s,a,i=0,c=a.length)=>{for(;i{let t=e.onItem,r=e.step;return(n,o,s)=>{let a=0,i=s.end??o.length,c=s.concurrency,u=!1,f,p,d,m,h,y=b=>{let x=Gr(b);return m=x,u=!0,p&&p.size>0?oe(Oc(pf(Array.from(p))),()=>m??x):x},S=()=>{let b=!1;for(;!m&&a{p.delete(I);try{if(m){if(P._tag===\"Failure\"){let G=P.cause.reasons.filter(he=>he._tag!==\"Interrupt\");if(G.length>0){let he=ls(G);m=Nt(m._tag===\"Failure\"?Ox(Ep(m.cause,he)):he)}}}else{let G=r(n,x,P,T);G&&(m=G,S())}if(b){let G=S();G&&d(G)}else u&&p.size===0&&d(m??Se)}catch(G){d(y(G))}}),p.size{f=sa(),p=new Set,h=w,d=I;let T;try{T=S()}catch(P){return I(y(P))}return T?I(T):be(()=>(m??=Ur,oe(p?pf(p):Se,()=>m?._tag===\"Failure\"?m:Se)))})}if(u=!0,m){if(p&&p.size>0){let x=Nx(f);p.forEach(w=>w.interruptUnsafe(f.id,x));return}if(d||m._tag===\"Failure\")return m}else if(d)if(p)p.size===0&&d(Se);else return Ur};return S()}},Qx=()=>e=>pM(e),E3=pM({onItem(e,t,r){return e.f(t,r)},step(e,t,r,n){if(r._tag===\"Failure\")return r;e.out&&(e.out[n]=r.value)}}),DI=l(3,(e,t,r)=>oe(e,n=>t(n)?z(n):r(n))),LI=l(3,(e,t,r)=>oe(e,n=>{let o=t(n);return ae(o)?r(o.failure):z(o.success)})),dM=l(e=>de(e[0]),(e,t,r)=>LI(e,t,r?n=>dt(r(n)):()=>dt(new vo))),mM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>Fe(_n(e,(n,o)=>{let s=t(n,o);return typeof s==\"boolean\"?z(s?_(n):v()):Fe(s,a=>a?_(n):v())},r),O_)),hM=l(e=>Js(e[0])&&!de(e[0]),(e,t)=>be(()=>{let r=[];for(let n of e){let o=t(n);rt(o)&&r.push(o.success)}return z(r)})),xM=l(e=>Js(e[0])&&!de(e[0]),(e,t,r)=>be(()=>{let n=[];return Rn(_n(e,o=>Fe(t(o),s=>{rt(s)&&n.push(s.success)}),{discard:!0,concurrency:r?.concurrency}),n)})),gM=z({}),yM=Kh(Fe),SM=Bh(Fe,oe),bM=$h(Fe);var EM=l(e=>de(e[0]),(e,t)=>se(r=>(U3(),z(_c(r,e,t?.startImmediately,!1,t?.uninterruptible??!1))))),_c=(e,t,r=!1,n=!1,o=!1)=>{let s=e,a=o===\"inherit\"?s.interruptible:!o,i=new lf(s.context,a);return n||(s.children().add(i),i._parent=s),r?i.evaluate(t):(i._asyncContext=vR(),s.currentDispatcher.scheduleTask(()=>i.evaluate(t),0)),i},IM=l(e=>de(e[0]),(e,t)=>se(r=>z(_c(r,e,t?.startImmediately,!0,t?.uninterruptible)))),wM=e=>se(t=>{let r=t._children&&new Set(t._children),n=t.interruptible;return Po(e,o=>{let s=t._children;if(s===void 0||s.size===0)return Se;r&&(s=A_(s,i=>!r.has(i)));let a=Zp(Ux(s));return n?Zx(a):a})}),AM=e=>()=>se(t=>t===e?Se:Dx(e)),$I=l(e=>de(e[0]),(e,t,r)=>se(n=>{let o=t.state._tag===\"Closed\"?new lf(n.context):_c(n,e,r?.startImmediately,!0,r?.uninterruptible);return o._exit||(t.state._tag!==\"Closed\"?(wf(t,o,AM(o)),o.addObserver(()=>Ax(t,o))):o.interruptUnsafe(n.id,Nx(n))),z(o)})),CM=l(e=>de(e[0]),(e,t)=>oe(vc,r=>$I(e,r,t))),ua=e=>(t,r)=>{let n=new lf(r?.scheduler?dr(e,ff,r.scheduler):e,r?.uninterruptible!==!0);if(n.evaluate(t),n._exit)return n;if(r?.signal)if(r.signal.aborted)n.interruptUnsafe();else{let o=()=>n.interruptUnsafe();r.signal.addEventListener(\"abort\",o,{once:!0}),n.addObserver(()=>r.signal.removeEventListener(\"abort\",o))}return r?.onFiberStart&&r.onFiberStart(n),n},TM=l(2,(e,t)=>e._exit?e:t.state._tag===\"Closed\"?(e.interruptUnsafe(e.id),e):(Ax(t,e),wf(t,e,AM(e)),e.addObserver(()=>Ax(t,e)),e)),vM=ua(Pr()),KI=e=>{let t=ua(e);return(r,n)=>{let o=t(r,n);return n?.onExit&&o.addObserver(n.onExit),s=>o.interruptUnsafe(s)}},kM=KI(Pr()),Xx=e=>{let t=ua(e);return(r,n)=>{let o=t(r,n);return new Promise(s=>{o.addObserver(a=>s(a))})}},OM=Xx(Pr()),BI=e=>{let t=Xx(e);return(r,n)=>t(r,n).then(o=>{if(o._tag===\"Failure\")throw Mx(o.cause);return o.value})},_M=BI(Pr()),eg=e=>{let t=ua(e);return r=>{if(Ve(r))return r;let n=new bc(\"sync\"),o=t(r,{scheduler:n});return o._dispatcher?.flush(),o._exit??Gr(new qp(o))}},RM=eg(Pr()),jI=e=>{let t=eg(e);return r=>{let n=t(r);if(n._tag===\"Failure\")throw Mx(n.cause);return n.value}},PM=jI(Pr()),mR=z(!0),hR=z(!1),HE=class{waiters=[];scheduled=void 0;_isOpen;constructor(t){this._isOpen=t}scheduleUnsafe(t){if(this.waiters.length===0)return mR;if(this.scheduled===void 0)this.scheduled=this.waiters,t.currentDispatcher.scheduleTask(this.flushScheduled,0);else for(let r=0;r{if(this.scheduled===void 0)return;let t=this.scheduled;this.scheduled=void 0;for(let r=0;rthis._isOpen?hR:(this._isOpen=!0,this.scheduleUnsafe(t)));release=se(t=>this._isOpen?hR:this.scheduleUnsafe(t));openUnsafe(){return this._isOpen?!1:(this._isOpen=!0,this.flushWaiters(),!0)}await=Dt(t=>this._isOpen?t(Se):(this.waiters.push(t),X(()=>{let r=this.waiters.indexOf(t);r!==-1?this.waiters.splice(r,1):this.scheduled!==void 0&&(r=this.scheduled.indexOf(t),r!==-1&&this.scheduled.splice(r,1))})));closeUnsafe(){return this._isOpen?(this._isOpen=!1,!0):!1}close=X(()=>this.closeUnsafe());whenOpen=t=>oe(this.await,()=>t);isOpen(){return this._isOpen}},HI=e=>new HE(e??!1),MM=e=>X(()=>HI(e)),FM=se(e=>z(e.getRef(_E))),NM=l(2,(e,t)=>Lr(e,_E,t)),UM=Lr(Sx),DM=Lr(wc),Cx=BigInt(0),I3={_tag:\"Span\",spanId:\"noop\",traceId:\"noop\",sampled:!1,status:{_tag:\"Ended\",startTime:Cx,endTime:Cx,exit:Ur},attributes:new Map,links:[],kind:\"internal\",attribute(){},event(){},end(){},addLinks(){}},w3=e=>Object.assign(Object.create(I3),e),LM=e=>e?Me(e.annotations,yx)?e._tag===\"Span\"?LM(ps(e.parent)):v():_(e):v(),zI=(e,t,r)=>{let n=!e.cache.tracerEnabled||r?.annotations&&Me(r.annotations,yx),o=r?.parent!==void 0?_(r.parent):r?.root?v():LM(e.cache.span),s;if(n)s=w3({name:t,parent:o,annotations:dr(r?.annotations??Pr(),yx,!0)});else{let a=e.cache.tracer??RE,i=e.getRef(Dr),c=e.getRef(wc),u=e.getRef(Dp),f=e.getRef(Lp),p=r?.level??e.getRef(oR),d=r?.links!==void 0?[...f,...r.links]:f.length===0?[]:f.slice();s=a.span({name:t,parent:o,annotations:r?.annotations??Pr(),links:d,startTime:c?i.currentTimeNanosUnsafe():Cx,kind:r?.kind??\"internal\",root:r?.root??!1,sampled:r?.sampled??(Ce(o)&&o.value.sampled===!1?!1:!rF(e.getRef(sR),p))});for(let m in u)s.attribute(m,u[m]);if(r?.attributes!==void 0)for(let m in r.attributes)s.attribute(m,r.attributes[m])}return s},$M=(e,t)=>se(r=>z(zI(r,e,t))),$p=(e,t)=>Oc(se(r=>{let n=ds(r.context,ri),o=zI(r,e,t??{}),s=r.getRef(Dr),a=r.getRef(wc);return Rn(ni(n,i=>tg(o,i,s,a)),o)})),KM=function(){let e=typeof arguments[0]!=\"string\",t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return oe($p(t,r),o=>df(n,o,r))}return n=>oe($p(t,r),o=>df(n,o,r))},A3=(e,t)=>(t=typeof t==\"function\"?t:Zn,ia(Up,r=>({name:e,stack:t,parent:r}))),BM=Dp,jM=Lp,HM=l(e=>de(e[0]),(e,t,r={})=>{let o=(Array.isArray(t)?t:[t]).map(s=>({span:s,attributes:r}));return ia(e,Lp,s=>[...s,...o])}),tg=(e,t,r,n)=>X(()=>{e.status._tag!==\"Ended\"&&e.end(n?r.currentTimeNanosUnsafe():Cx,t)}),Kp=(e,...t)=>{let r=t.length===1?void 0:t[0],n=t[t.length-1];return se(o=>{let s=zI(o,e,r),a=o.getRef(Dr),i=o.getRef(wc);return oi(o,c=>tg(s,c,a,i)),n(s)})},zE=Lr(Ic),df=function(){let e=de(arguments[0]),t=e?arguments[1]:arguments[0],r=e?arguments[2]:arguments[1],n=D;return t._tag===\"Span\"&&(r=Va(r),n=A3(t.name,r?.captureStackTrace)),e?zE(n(arguments[0]),t):o=>zE(n(o),t)},zM=function(){let e=typeof arguments[0]!=\"string\",t=e?arguments[1]:arguments[0],r=Va(arguments[2]);if(e){let s=arguments[0];return Kp(t,arguments[2],a=>df(s,a,r))}let n=typeof arguments[1]==\"function\"?arguments[1]:void 0,o=n?void 0:arguments[1];return(s,...a)=>Kp(t,n?n(...a):o,i=>df(s,i,r))},WM=l(e=>de(e[0]),(e,...t)=>ia(e,Dp,r=>{let n=t.length===1?{...r,...t[0]}:{...r};return t.length===1||B(n,t[0],t[1]),n})),qM=(...e)=>se(t=>{let r=t.currentSpanLocal;if(r&&r.status._tag!==\"Ended\")if(e.length===1)for(let[n,o]of Object.entries(e[0]))r.attribute(n,o);else r.attribute(e[0],e[1]);return Se}),JM=se(e=>{let t=e.currentSpanLocal;return t?z(t):dt(new vo)}),GM=i3(Ic),Dr=Te(\"effect/Clock\",{defaultValue:()=>new WE}),UE=2**31-1,WE=class{currentTimeMillisUnsafe(){return Date.now()}currentTimeMillis=X(()=>this.currentTimeMillisUnsafe());currentTimeNanosUnsafe(){return C3()}currentTimeNanos=X(()=>this.currentTimeNanosUnsafe());monotonicTimeNanosUnsafe(){return ZM()}monotonicTimeNanos=X(()=>this.monotonicTimeNanosUnsafe());sleep(t){return this.sleepMillis(Nr(t))}sleepMillis(t){return t<=0?Sf:Number.isFinite(t)?Dt(r=>{let n=t>UE?this.sleepMillis(t-UE):Se,o=setTimeout(()=>r(n),Math.min(t,UE));return X(()=>clearTimeout(o))}):Lx}},VM=BigInt(1e6),ZM=(function(){let e=globalThis.process?.hrtime;if(typeof e?.bigint==\"function\")return()=>e.bigint();if(typeof performance<\"u\"&&typeof performance.now==\"function\")return()=>BigInt(Math.round(performance.now()*1e6));let t=BigInt(0);return()=>{let r=BigInt(Date.now())*VM;return r>t&&(t=r),t}})(),C3=(function(){let e=BigInt(1e9),t;return()=>{let r=ZM(),n=BigInt(Date.now())*VM;if(t===void 0)t=n-r;else{let o=t+r;(n>o?n-o:o-n)>e&&(t=n-r)}return t+r}})(),Mo=e=>se(t=>e(t.getRef(Dr))),Af=e=>Mo(t=>t.sleep(ct(e))),WI=Mo(e=>e.currentTimeMillis);var Bp=\"~effect/Cause/TimeoutError\",YM=e=>A(e,Bp),jp=class extends Ys(\"TimeoutError\"){[Bp]=Bp;constructor(t){super({message:t})}},Hp=\"~effect/Cause/IllegalArgumentError\",QM=e=>A(e,Hp),Tx=class extends Ys(\"IllegalArgumentError\"){[Hp]=Hp;constructor(t){super({message:t})}},zp=\"~effect/Cause/ExceededCapacityError\",XM=e=>A(e,zp),vx=class extends Ys(\"ExceededCapacityError\"){[zp]=zp;constructor(t){super({message:t})}},Wp=\"~effect/Cause/AsyncFiberError\",eF=e=>A(e,Wp),qp=class extends Ys(\"AsyncFiberError\"){[Wp]=Wp;constructor(t){super({message:\"An asynchronous Effect was executed with Effect.runSync\",fiber:t})}},Jp=\"~effect/Cause/UnknownError\",tF=e=>A(e,Jp),mf=class extends Ys(\"UnknownError\"){[Jp]=Jp;constructor(t,r){super({message:r,cause:t})}},qI=Te(\"effect/Console\",{defaultValue:()=>globalThis.console}),T3=e=>{switch(e){case\"All\":return Number.MIN_SAFE_INTEGER;case\"Fatal\":return 5e4;case\"Error\":return 4e4;case\"Warn\":return 3e4;case\"Info\":return 2e4;case\"Debug\":return 1e4;case\"Trace\":return 0;case\"None\":return Number.MAX_SAFE_INTEGER}},v3=rE(Qs,T3),rF=tf(v3),JI=Te(\"effect/Logger/CurrentLoggers\",{defaultValue:()=>new Set([F3,N3])}),k3=Te(\"effect/Logger/LogToStderr\",{defaultValue:ap}),nF=function(){let e=typeof arguments[0]==\"string\"?[[arguments[0],arguments[1]]]:Object.entries(arguments[0]);return Oc(se(t=>{let r=t.getRef(oa),n={...r};for(let o=0;o{let s=t.getRef(oa),a={...s};for(let i=0;i{let t=Object.create(_3);return t.log=e,t},R3=e=>e.replace(/[\\s=\"]/g,\"_\"),P3=(e,t)=>`${R3(e[0])}=${t-e[1]}ms`;var Ro=e=>(...t)=>{let r;for(let n=0,o=t.length;n{let o=e??n.cache.logLevel;if(rF(n.cache.minimumLogLevel,o))return Se;let s=n.getRef(Dr),a=n.getRef(JI);if(a.size>0){let i=new Date(s.currentTimeMillisUnsafe());for(let c of a)c.log({cause:r,fiber:n,date:i,logLevel:o,message:t})}return Se})};var Ac={bold:\"1\",red:\"31\",green:\"32\",yellow:\"33\",blue:\"34\",cyan:\"36\",white:\"37\",gray:\"90\",black:\"30\",bgBrightRed:\"101\"},ppe={None:[],All:[],Trace:[Ac.gray],Debug:[Ac.blue],Info:[Ac.green],Warn:[Ac.yellow],Error:[Ac.red],Fatal:[Ac.bgBrightRed,Ac.black]};var M3=e=>`${e.getHours().toString().padStart(2,\"0\")}:${e.getMinutes().toString().padStart(2,\"0\")}:${e.getSeconds().toString().padStart(2,\"0\")}.${e.getMilliseconds().toString().padStart(3,\"0\")}`;var F3=oF(({cause:e,date:t,fiber:r,logLevel:n,message:o})=>{let s=Array.isArray(o)?o.slice():[o];e.reasons.length>0&&s.push(Fx(e));let a=t.getTime(),i=r.getRef(bx),c=\"\";for(let d of i)c+=` ${P3(d,a)}`;let u=r.getRef(oa);Object.keys(u).length>0&&s.push(u);let f=r.getRef(qI);(r.getRef(k3)?f.error:f.log)(`[${M3(t)}] ${n.toUpperCase()} (#${r.id})${c}:`,...s)}),N3=oF(({cause:e,fiber:t,logLevel:r,message:n})=>{let o=t.getRef(Dr),s=t.getRef(oa),a=t.cache.span;if(a===void 0||a._tag===\"ExternalSpan\"||a.status._tag===\"Ended\")return;let i={};for(let[c,u]of Object.entries(s))B(i,c,u);i[\"effect.fiberId\"]=t.id,i[\"effect.logLevel\"]=r.toUpperCase(),e.reasons.length>0&&(i[\"effect.cause\"]=Fx(e)),a.event(FO(Array.isArray(n)&&n.length===1?n[0]:n),o.currentTimeNanosUnsafe(),i)});function U3(){$E.interruptChildren??=X4}var GI=z(void 0);var sF=l(e=>de(e[0]),(e,t)=>MI(e,r=>se(n=>(D3(n,r,t?.defectsOnly),Se)))),D3=(e,t,r)=>{let n=e.getRef(cR);if(n.size===0||r&&!xf(t))return;let o={cause:t,fiber:e,timestamp:e.getRef(Dr).currentTimeNanosUnsafe()};n.forEach(s=>s.report(o))};var L3=gp,$3=Wu,id=Ju,YI=DO,ai=fc,QI=lc,K3=Zs,gs=ls,B3=Fh,j3=Gu,Rc=Vb,H3=Ya,Cf=e=>new ac(e),Tf=e=>new ic(e),XI=xR,e0=Px,fa=gf,z3=Ep,rg=Mx,t0=kx,W3=gR,q3=hf,r0=yR,J3=xf,G3=SR,cd=Gp,V3=_x,Z3=bR,Y3=ER,Q3=Rx,X3=qE,n0=Fx,eJ=Uh,tJ=yp,rJ=vo,Pc=Dh,nJ=cc,o0=pc,ue=BO,oJ=Bp,sJ=YM,aJ=jp,iJ=Hp,cJ=QM,ud=Tx,uJ=XM,fJ=zp,s0=vx,lJ=Wp,pJ=eF,dJ=qp,mJ=Jp,hJ=tF,xJ=mf,gJ=Vu,ng=IR,yJ=wR,VI=class extends Et()(\"effect/Cause/StackTrace\"){},ZI=class extends Et()(\"effect/Cause/InterruptorStackTrace\"){};var $={};An($,{Do:()=>H5,Transaction:()=>Pf,TypeId:()=>N5,abortSignal:()=>cG,acquireDisposable:()=>Y8,acquireRelease:()=>Wc,acquireUseRelease:()=>p1,addFinalizer:()=>Q8,all:()=>Eg,andThen:()=>Yr,annotateCurrentSpan:()=>SG,annotateLogs:()=>YG,annotateLogsScoped:()=>QG,annotateSpans:()=>yG,as:()=>jt,asSome:()=>wg,asVoid:()=>pi,awaitAllChildren:()=>MG,bind:()=>q5,bindTo:()=>z5,cached:()=>nG,cachedInvalidateWithTTL:()=>sG,cachedWithTTL:()=>oG,callback:()=>Ff,catch:()=>Uo,catchCause:()=>nt,catchCauseFilter:()=>p8,catchCauseIf:()=>l8,catchDefect:()=>i8,catchEager:()=>Kf,catchFilter:()=>u8,catchIf:()=>c8,catchNoSuchElement:()=>f8,catchReason:()=>o8,catchReasons:()=>s8,catchTag:()=>r8,catchTags:()=>n8,clockWith:()=>qc,context:()=>Hc,contextWith:()=>Od,currentParentSpan:()=>EG,currentSpan:()=>bG,delay:()=>j0,die:()=>yr,effectify:()=>fV,ensuring:()=>hi,eventually:()=>y8,exit:()=>ao,fail:()=>F,failCause:()=>$e,failCauseSync:()=>da,failSync:()=>Ig,fiber:()=>FG,fiberId:()=>NG,filter:()=>z0,filterMap:()=>M8,filterMapEffect:()=>W0,filterMapOrElse:()=>N8,filterMapOrFail:()=>D8,filterOrElse:()=>F8,filterOrFail:()=>U8,findFirst:()=>$5,findFirstFilter:()=>K5,firstSuccessOf:()=>T8,flatMap:()=>C,flatMapEager:()=>Ct,flatten:()=>K0,flip:()=>e8,fn:()=>jG,fnUntraced:()=>_e,fnUntracedEager:()=>ew,forEach:()=>ui,forever:()=>ir,forkChild:()=>Df,forkDetach:()=>PG,forkIn:()=>rr,forkScoped:()=>Lf,fromNullishOr:()=>Y5,fromOption:()=>V5,fromResult:()=>jc,gen:()=>kt,head:()=>B5,ignore:()=>I8,ignoreCause:()=>di,interrupt:()=>co,interruptible:()=>aG,interruptibleMask:()=>iG,isEffect:()=>ws,isFailure:()=>H8,isSuccess:()=>z8,let:()=>W5,linkSpans:()=>AG,log:()=>zG,logDebug:()=>GG,logError:()=>X0,logFatal:()=>WG,logInfo:()=>JG,logTrace:()=>VG,logWarning:()=>qG,logWithLevel:()=>HG,makeSpan:()=>Z0,makeSpanScoped:()=>CG,map:()=>W,mapBoth:()=>d8,mapBothEager:()=>Sr,mapEager:()=>fn,mapError:()=>Do,mapErrorEager:()=>$f,match:()=>q0,matchCause:()=>$8,matchCauseEager:()=>K8,matchCauseEffect:()=>As,matchCauseEffectEager:()=>B8,matchEager:()=>L8,matchEffect:()=>j8,never:()=>Bc,onError:()=>Lo,onErrorFilter:()=>eG,onErrorIf:()=>X8,onExit:()=>Dn,onExitFilter:()=>rG,onExitIf:()=>tG,onExitPrimitive:()=>_d,onInterrupt:()=>V0,option:()=>X5,orDie:()=>m8,orElseSucceed:()=>C8,partition:()=>U5,promise:()=>Mf,provide:()=>W8,provideContext:()=>io,provideService:()=>Cs,provideServiceEffect:()=>Z8,race:()=>P8,raceAll:()=>H0,raceAllFirst:()=>R8,raceFirst:()=>Uf,reduce:()=>D5,repeat:()=>uG,repeatOrElse:()=>fG,replicate:()=>lG,replicateEffect:()=>pG,request:()=>_G,requestUnsafe:()=>RG,result:()=>Q5,retry:()=>S8,retryOrElse:()=>b8,runCallback:()=>DG,runCallbackWith:()=>UG,runFork:()=>Rd,runForkWith:()=>uo,runPromise:()=>Y0,runPromiseExit:()=>kg,runPromiseExitWith:()=>LG,runPromiseWith:()=>Q0,runSync:()=>$G,runSyncExit:()=>Ts,runSyncExitWith:()=>BG,runSyncWith:()=>KG,sandbox:()=>E8,satisfiesErrorType:()=>pV,satisfiesServicesType:()=>dV,satisfiesSuccessType:()=>lV,schedule:()=>dG,scheduleFrom:()=>d1,scope:()=>zc,scoped:()=>Tg,scopedWith:()=>vg,service:()=>J0,serviceOption:()=>G0,setContext:()=>q8,sleep:()=>mi,spanAnnotations:()=>IG,spanLinks:()=>wG,succeed:()=>g,succeedNone:()=>li,succeedSome:()=>$0,suspend:()=>L,sync:()=>Y,tap:()=>Qr,tapCause:()=>f1,tapCauseFilter:()=>g8,tapCauseIf:()=>x8,tapDefect:()=>l1,tapError:()=>Ag,tapErrorTag:()=>h8,timed:()=>_8,timeout:()=>v8,timeoutOption:()=>k8,timeoutOrElse:()=>O8,tracer:()=>mG,track:()=>eV,trackDefects:()=>nV,trackDuration:()=>oV,trackErrors:()=>rV,trackSuccesses:()=>tV,transposeOption:()=>Z5,try:()=>Nf,tryPromise:()=>fi,tx:()=>sV,txRetry:()=>uV,undefined:()=>j5,uninterruptible:()=>ma,uninterruptibleMask:()=>$o,unwrapReason:()=>a8,updateContext:()=>J8,updateService:()=>G8,updateServiceScoped:()=>V8,useSpan:()=>TG,validate:()=>L5,void:()=>ie,when:()=>Cg,whileLoop:()=>No,withErrorReporting:()=>A8,withExecutionPlan:()=>w8,withFiber:()=>Un,withFiberSucceed:()=>G5,withLogSpan:()=>XG,withLogger:()=>ZG,withParentSpan:()=>OG,withSpan:()=>vG,withSpanScoped:()=>kG,withTracer:()=>hG,withTracerEnabled:()=>xG,withTracerTiming:()=>gG,yieldNow:()=>kd,yieldNowWith:()=>J5,zip:()=>B0,zipWith:()=>t8});var Or={};An(Or,{asVoid:()=>_J,asVoidAll:()=>pd,die:()=>a0,fail:()=>la,failCause:()=>Fn,filterCause:()=>AJ,filterFailure:()=>wJ,filterSuccess:()=>EJ,filterValue:()=>IJ,findDefect:()=>TJ,findError:()=>CJ,findErrorOption:()=>MJ,getCause:()=>PJ,getSuccess:()=>RJ,hasDies:()=>bJ,hasFails:()=>SJ,hasInterrupts:()=>i0,interrupt:()=>ld,isExit:()=>fd,isFailure:()=>oo,isSuccess:()=>ut,map:()=>vJ,mapBoth:()=>OJ,mapError:()=>kJ,match:()=>c0,succeed:()=>Vr,void:()=>Bt});var fd=Sp,Vr=We,Fn=Nt,la=ko,a0=Gr,ld=Ef,Bt=Ur;var ut=Xa,oo=cI,SJ=nP,bJ=rP,i0=fI,EJ=QR,IJ=XR,wJ=eP,AJ=Yp,CJ=uI,TJ=tP,c0=sP,vJ=lI,kJ=pI,OJ=dI,_J=aP,pd=mI,RJ=iP,PJ=cP,MJ=uP;var FJ=\"~effect/Deferred\";var NJ={[FJ]:{_A:D,_E:D},pipe(){return te(this,arguments)}},aF=function(){this.resumes=void 0,this.effect=void 0};aF.prototype=NJ;var Mc=()=>new aF;var og=e=>Dt(t=>e.effect?t(e.effect):(e.resumes??=[],e.resumes.push(t),X(()=>{let r=e.resumes;if(r===void 0)return;let n=r.indexOf(t);n>=0&&r.splice(n,1)})));var UJ=l(2,(e,t)=>X(()=>ys(e,t))),DJ=UJ;var LJ=l(2,(e,t)=>DJ(e,Nt(t)));var u0=l(2,(e,t)=>LJ(e,Ya(t)));var ys=(e,t)=>{if(e.effect)return!1;if(e.effect=t,e.resumes){let r=e.resumes;e.resumes=void 0;for(let n=0;n{let r={observers:0,deferred:Mc(),scope:so(),finalizer:n=>be(()=>--r.observers>0?Se:(e.map.delete(t),Xe(r.scope,n)))};return r},lF=(e,t)=>t.state._tag===\"Closed\"?!1:(e.observers++,wf(t,{},e.finalizer),!0),mF=e=>A(e,dF),BJ={[dF]:{_ROut:D,_E:D,_RIn:D},pipe(){return te(this,arguments)}},hF=e=>{let t=Object.create(BJ);return t.build=e,t},jJ=e=>hF((t,r)=>{let n=tr(r);return Mn(e(t,n),o=>o._tag===\"Failure\"?Xe(n,o):Se)}),f0=e=>{let t=jJ((r,n)=>r.getOrElseMemoize(t,n,e));return t},ag=class{get[fF](){return fF}parent;constructor(t){this.parent=t}map=new Map;get(t,r){let n=this.map.get(t);return n?(lF(n,r),n.deferred.effect??og(n.deferred)):this.parent?.get(t,r)}getOrElseMemoize(t,r,n){return be(()=>{let o;return Po(be(()=>{let s=this.get(t,r);if(s)return s;let a=KJ(this,t);return lF(a,r)?(o=a.deferred,this.map.set(t,a),n(this,a.scope)):n(this,r)}),s=>{o&&ys(o,s)})})}},md=()=>new ag,HJ=e=>new ag(e);var dd=class e extends Et()(\"effect/Layer/CurrentMemoMap\"){static forkOrCreate(t){let r=ex(t,e);return r?HJ(r):md()}},hd=l(3,(e,t,r)=>Lr(Fe(be(()=>e.build(t,r)),dr(dd,t)),dd,t));var cg=l(2,(e,t)=>se(r=>hd(e,dd.forkOrCreate(r.context),t))),xF=function(){return arguments.length===1?e=>ig(xc(arguments[0],e)):ig(xc(arguments[0],arguments[1]))},ig=e=>hF(gt(z(e)));var pa=function(){return arguments.length===1?e=>pF(arguments[0],e):pF(arguments[0],arguments[1])},pF=(e,t)=>zJ(Fe(t,r=>xc(e,r))),zJ=e=>f0((t,r)=>Ss(e,r));var gF=(e,t,r)=>{let n=tr(r,\"parallel\");return _n(e,o=>o.build(t,tr(n,\"sequential\")),{concurrency:e.length}).pipe(Fe(o=>g_(...o)))},yF=(...e)=>f0((t,r)=>gF(e,t,r));var WJ=(e,t,r)=>f0((n,o)=>oe(Array.isArray(t)?gF(t,n,o):t.build(n,o),s=>e.build(n,o).pipe(Pn(s),Fe(a=>r(a,s))))),SF=l(2,(e,t)=>WJ(e,t,D));var vf=Dr;var fg=\"~effect/DateTime\",lg=\"~effect/DateTime/TimeZone\",EF={[fg]:fg,pipe(){return te(this,arguments)},[Je](){return this.toString()},toJSON(){return yd(this).toJSON()}},IF={...EF,_tag:\"Utc\",[re](){return Lt(this.epochMilliseconds)},[ne](e){return Of(e)&&e._tag===\"Utc\"&&this.epochMilliseconds===e.epochMilliseconds},toString(){return`DateTime.Utc(${yd(this).toJSON()})`}},wF={...EF,_tag:\"Zoned\",[re](){return Ee(Lt(this.epochMilliseconds))(V(this.zone))},[ne](e){return Of(e)&&e._tag===\"Zoned\"&&this.epochMilliseconds===e.epochMilliseconds&&Z(this.zone,e.zone)},toString(){return`DateTime.Zoned(${A0(this)})`}},AF={[lg]:lg,[Je](){return this.toString()}},JJ={...AF,_tag:\"Named\",[re](){return Pe(`Named:${this.id}`)},[ne](e){return Nc(e)&&e._tag===\"Named\"&&this.id===e.id},toString(){return`TimeZone.Named(${this.id})`},toJSON(){return{_id:\"TimeZone\",_tag:\"Named\",id:this.id}}},GJ={...AF,_tag:\"Offset\",[re](){return Pe(`Offset:${this.offset}`)},[ne](e){return Nc(e)&&e._tag===\"Offset\"&&this.offset===e.offset},toString(){return`TimeZone.Offset(${E0(this.offset)})`},toJSON(){return{_id:\"TimeZone\",_tag:\"Offset\",offset:this.offset}}},VJ={value:void 0,enumerable:!1,writable:!0},l0=new WeakMap,ug=(e,t)=>({get(){return Object.isExtensible(this)?void 0:l0.get(this)?.[e]},set(r){if(Object.isExtensible(this)){for(let n of t)Object.defineProperty(this,n,VJ);this[e]=r}else{let n=l0.get(this);n===void 0&&(n={},l0.set(this,n)),n[e]=r}}}),p0=[\"partsUtc\",\"adjustedEpochMilliseconds\",\"partsAdjusted\"];Object.defineProperty(IF,\"partsUtc\",ug(\"partsUtc\",[\"partsUtc\"]));Object.defineProperties(wF,{partsUtc:ug(\"partsUtc\",p0),adjustedEpochMilliseconds:ug(\"adjustedEpochMilliseconds\",p0),partsAdjusted:ug(\"partsAdjusted\",p0)});var Es=(e,t,r)=>{let n=Object.create(wF);return n.epochMilliseconds=e,n.zone=t,r!==void 0&&(n.partsUtc=r),n},Of=e=>A(e,fg);var Nc=e=>A(e,lg),CF=e=>Nc(e)&&e._tag===\"Offset\",TF=e=>Nc(e)&&e._tag===\"Named\",vF=e=>e._tag===\"Utc\",h0=e=>e._tag===\"Zoned\",kF=Kt((e,t)=>e.epochMilliseconds===t.epochMilliseconds);var OF=e=>{let t=Object.create(IF);return t.epochMilliseconds=e,t},kf=e=>{let t=e.getTime();if(Number.isNaN(t))throw new ud(\"Invalid date\");return OF(t)},dg=e=>{if(Of(e))return e;if(e instanceof Date)return kf(e);if(typeof e==\"object\"){if(\"epochMilliseconds\"in e)return kf(new Date(e.epochMilliseconds));let t=new Date(0);return n5(t,e),kf(t)}else if(typeof e==\"string\"&&!ZJ(e))return kf(new Date(e+\"Z\"));return kf(new Date(e))},ZJ=e=>/Z|GMT|[+-]\\d{2}$|[+-]\\d{2}:?\\d{2}$|\\]$/.test(e)||/z$|gmt$/i.test(e),YJ=-864e13+720*60*1e3,QJ=864e13-840*60*1e3,x0=(e,t)=>{let r=t?.timeZone;if(r===void 0&&Of(e)&&h0(e))return e;let n=dg(e);if(n.epochMillisecondsQJ)throw new RangeError(`Epoch millis out of range: ${n.epochMilliseconds}`);r===void 0&&typeof e==\"object\"&&\"timeZoneId\"in e&&(r=e.timeZoneId);let o;if(r===void 0){let s=new Date(n.epochMilliseconds).getTimezoneOffset()*-60*1e3;o=gd(s)}else if(Nc(r))o=r;else if(typeof r==\"number\")o=gd(r);else{let s=S0(r);if(ge(s))throw new ud(`Invalid time zone: ${r}`);o=s.value}return t?.adjustForTimeZone!==!0?Es(n.epochMilliseconds,o,n.partsUtc):o5(n.epochMilliseconds,o,t?.disambiguation??\"compatible\")},d0=Oo(x0),_F=Oo(dg),XJ=/^(.{17,35})\\[(.+)\\]$/,RF=e=>{let t=XJ.exec(e);if(t===null){let o=w0(e);return o!==null?d0(e,{timeZone:o}):v()}let[,r,n]=t;return d0(r,{timeZone:n})};var PF=e=>OF(e.epochMilliseconds);var pg=new Map,e5={day:\"numeric\",month:\"numeric\",year:\"numeric\",era:\"short\",hour:\"numeric\",minute:\"numeric\",second:\"numeric\",timeZoneName:\"longOffset\",fractionalSecondDigits:3,hourCycle:\"h23\"},t5=e=>{let t=e.resolvedOptions().timeZone,r=pg.get(t);if(r!==void 0)return r;let n=Object.create(JJ);return n.id=t,n.format=e,pg.set(t,n),n},g0=e=>{let t=pg.get(e);if(t!==void 0)return t;try{let r=t5(new Intl.DateTimeFormat(\"en-US\",{...e5,timeZone:e}));return pg.set(e,r),r}catch{throw new ud(`Invalid time zone: ${e}`)}},gd=e=>{let t=Object.create(GJ);return t.offset=e,t},y0=Oo(g0);var r5=/^(?:GMT)?[+-]/,S0=e=>{if(r5.test(e)){let t=w0(e);return t===null?v():_(gd(t))}return y0(e)},MF=e=>e._tag===\"Offset\"?E0(e.offset):e.id;var yd=e=>new Date(e.epochMilliseconds),mg=e=>{if(e._tag===\"Utc\")return new Date(e.epochMilliseconds);if(e.zone._tag===\"Offset\")return new Date(e.epochMilliseconds+e.zone.offset);if(e.adjustedEpochMilliseconds!==void 0)return new Date(e.adjustedEpochMilliseconds);let t=!1,r=e.zone.format.formatToParts(e.epochMilliseconds).filter(s=>s.type===\"era\"?(t=s.value===\"BC\",!1):s.type!==\"literal\"),n=Number(r[2].value),o=new Date(0);return o.setUTCFullYear(t?1-n:n,Number(r[0].value)-1,Number(r[1].value)),o.setUTCHours(Number(r[3].value),Number(r[4].value),Number(r[5].value),r[6]?.type===\"fractionalSecond\"?Number(r[6].value):(e.epochMilliseconds%1e3+1e3)%1e3),e.adjustedEpochMilliseconds=o.getTime(),o},b0=e=>mg(e).getTime()-I0(e),E0=e=>{let t=Math.abs(e),r=Math.floor(t/(3600*1e3)),n=Math.round(t%(3600*1e3)/(60*1e3));return n===60&&(r+=1,n=0),`${e<0?\"-\":\"+\"}${String(r).padStart(2,\"0\")}:${String(n).padStart(2,\"0\")}`},FF=e=>E0(b0(e)),I0=e=>e.epochMilliseconds;var n5=(e,t)=>{if((t.year!==void 0||t.month!==void 0||t.day!==void 0)&&e.setUTCFullYear(t.year??e.getUTCFullYear(),t.month!==void 0?t.month-1:e.getUTCMonth(),t.day??e.getUTCDate()),t.weekDay!==void 0){let r=t.weekDay-e.getUTCDay();e.setUTCDate(e.getUTCDate()+r)}t.hour!==void 0&&e.setUTCHours(t.hour),t.minute!==void 0&&e.setUTCMinutes(t.minute),t.second!==void 0&&e.setUTCSeconds(t.second),t.millisecond!==void 0&&e.setUTCMilliseconds(t.millisecond)};var bF=1440*60*1e3,o5=(e,t,r)=>{if(t._tag===\"Offset\")return Es(e-t.offset,t);let n=xd(e-bF,e,t),o=xd(e+bF,e,t);if(n===o)return Es(e-n,t);let s=n{let t=s5.exec(e);if(t===null)return null;let[,r,n,o]=t;return(r===\"+\"?1:-1)*(Number(n)*60+Number(o))*60*1e3},xd=(e,t,r)=>{let n=r.format.formatToParts(e).find(s=>s.type===\"timeZoneName\")?.value??\"\";if(n===\"GMT\")return 0;let o=w0(n);return o===null?b0(Es(t,r)):o};var NF=e=>yd(e).toISOString();var m0=e=>{let t=mg(e);return e._tag===\"Utc\"?t.toISOString():`${t.toISOString().slice(0,-1)}${FF(e)}`},A0=e=>e.zone._tag===\"Offset\"?m0(e):`${m0(e)}[${e.zone.id}]`;var Tpe=globalThis.Number;var DF=l(2,(e,t)=>{if(!globalThis.Number.isFinite(e)||!globalThis.Number.isFinite(t)||t===0)return NaN;if(globalThis.Number.isInteger(e)&&globalThis.Number.isInteger(t))return e%t;let[r,n]=UF(e),[o,s]=UF(t),a=Math.min(n,s),i=r*BigInt(10)**BigInt(n-a),c=o*BigInt(10)**BigInt(s-a),u=i%c;if(u===BigInt(0))return e<0||Object.is(e,-0)?-0:0;let f=globalThis.Number(`${u}e${a}`);return f===0?Math.sign(e)*globalThis.Number.MIN_VALUE:f});function UF(e){if(globalThis.Number.isInteger(e))return[BigInt(e),0];let t=Math.abs(e).toExponential(),r=t.indexOf(\"e\"),n=t.slice(0,r).replace(\".\",\"\");return[BigInt(n)*(e<0?-BigInt(1):BigInt(1)),globalThis.Number(t.slice(r+1))-n.length+1]}var LF=e=>{let t=Math.pow(2,Math.ceil(Math.log2(e)));return Math.max(te.toUpperCase();var KF=e=>e.trim();var c5=(e,t,r,n,o)=>{let s=e;for(let c of t)s=s.replace(c,\"$1\\0$2\");for(let c of r)s=s.replace(c,\"\\0\");let a=0,i=s.length;for(;s.charAt(a)===\"\\0\";)a++;for(;s.charAt(i-1)===\"\\0\";)i--;return a>=i?\"\":s.slice(a,i).split(\"\\0\").map(o).join(n)};var u5=[/([a-z0-9])([A-Z])/g,/([A-Z])([A-Z][a-z])/g],f5=/[^A-Z0-9]+/gi;var BF=e=>c5(e,u5,[f5],\"_\",$F);var At=l(2,(e,t)=>ca(e,l5,r=>t(r))),Is=e=>e.reasons.some(C0),C0=e=>e._tag===\"Fail\"&&Pc(e.error),Sd=e=>{let t,r=!1;for(let n of e.reasons)C0(n)?t??=n.error:n._tag!==\"Interrupt\"&&(r=!0);return t===void 0?q(e):r?q(gs(e.reasons.filter(n=>!C0(n)))):j(t)};var l5=e=>{let t=Sd(e);return ae(t)?t:j(t.success.value)},bd=e=>{let t=Sd(e);return ae(t)?Fn(t.failure):Vr(t.success.value)},Uc=l(2,(e,t)=>_o(e,{onSuccess:t.onSuccess,onFailure:r=>{let n=Sd(r);return ae(n)?t.onFailure(n.failure):t.onDone(n.success.value)}}));var jF=\"~effect/Schedule\";var gr=Te(\"effect/Schedule/CurrentMetadata\",{defaultValue:gt({input:void 0,output:void 0,duration:ta,attempt:0,start:0,now:0,elapsed:0,elapsedSincePrevious:0})}),p5={[jF]:{_Out:D,_In:D,_Env:D},pipe(){return te(this,arguments)}},T0=e=>A(e,jF),Ed=e=>{let t=Object.create(p5);return t.step=e,t},v0=()=>{let e=0,t,r;return(n,o)=>{r===void 0&&(r=n);let s=n-r,a=t===void 0?0:n-t;return t=n,{input:o,attempt:++e,start:r,now:n,elapsed:s,elapsedSincePrevious:a}}},d5=e=>Ed(Fe(e,t=>{let r=v0();return(n,o)=>t(r(n,o))})),Lc=e=>un(e.step,t=>z(()=>Le(t))),Fo=e=>Mo(t=>Fe(Lc(e),r=>{let n=v0();return o=>be(()=>{let s=t.currentTimeMillisUnsafe();return oe(r(s,o),([a,i])=>{let c=n(s,o);return c.output=a,c.duration=i,Rn(Af(i),c)})})})),Id=e=>Fe(Fo(e),t=>r=>Fe(t(r),n=>n.output));var k0=e=>Ed(Fe(Lc(e),t=>(r,n)=>Uc(t(r,n),{onSuccess:o=>z([n,o[1]]),onFailure:Le,onDone:()=>ue(n)}))),HF=e=>wd(Ad,({attempt:t})=>z(t<=e)),O0=e=>{let t=ct(e);return d5(z(r=>z([r.attempt-1,t])))};var wd=l(2,(e,t)=>Ed(Fe(Lc(e),r=>{let n=v0();return(o,s)=>oe(r(o,s),a=>{let[i,c]=a,u=t({...n(o,s),output:i,duration:c});return oe(de(u)?u:z(u),f=>f?z(a):ue(i))})})));var Ad=O0(ta);var zF=\"~effect/ExecutionPlan\";var m5={[zF]:zF,get captureRequirements(){let e=this;return ei(t=>z(h5(e.steps.map(r=>({...r,while:r.while?n=>Pn(r.while(n),t):void 0,schedule:r.schedule?Ed(Pn(Fe(Lc(r.schedule),n=>(o,s)=>Pn(n(o,s),t)),t)):void 0,provide:mF(r.provide)?SF(r.provide,ig(t)):r.provide})))))},pipe(){return te(this,arguments)}},h5=e=>{let t=Object.create(m5);return t.steps=e,t};var gg=Te(\"effect/ExecutionPlan/CurrentMetadata\",{defaultValue:gt({attempt:0,stepIndex:0})});var x5=(e,t,r)=>Vx(n=>oe(r?.local?hd(t,md(),n):cg(t,n),o=>Pn(e,o))),yg=l(e=>de(e[0]),(e,t,r)=>kp(t)?Pn(e,t):x5(e,Array.isArray(t)?yF(...t):t,r));var R0=l(3,(e,t,r)=>oe(Fo(t),n=>{let o=gr.defaultValue(),s=a=>Uc(n(a),{onSuccess(i){return o=i,oe(Lr(e,gr,o),s)},onFailure:Le,onDone:z});return ca(oe(Lr(e,gr,o),s),cn,a=>r(a,o.attempt===0?v():_(o)))})),P0=l(3,(e,t,r)=>oe(Fo(t),n=>{let o=gr.defaultValue(),s,a=ca(be(()=>Lr(e,gr,o)),cn,i=>(s=i,oe(n(i),c=>(o=c,a))));return At(a,i=>za(()=>r(s,i)))})),qF=l(2,(e,t)=>{let r=typeof t==\"function\"?t(D):T0(t)?t:Td(t);return R0(e,r,dt)}),Cd=l(2,(e,t)=>{let r=typeof t==\"function\"?t(D):T0(t)?t:Td(t);return P0(e,r,dt)}),JF=l(3,(e,t,r)=>oe(Fo(r),n=>{let o=s=>Uc(n(s),{onSuccess:a=>oe(Lr(e,gr,a),o),onFailure:Le,onDone:z});return o(t)})),g5=k0(Ad),Td=e=>{let t=e.schedule?k0(e.schedule):g5;return e.while&&(t=wd(t,({input:r})=>{let n=e.while(r);return de(n)?n:z(n)})),e.until&&(t=wd(t,({input:r})=>{let n=e.until(r);return de(n)?Fe(n,o=>!o):z(!n)})),e.times!==void 0&&(t=wd(t,({attempt:r})=>z(r<=e.times))),t};var M0=(e,t)=>{let r=-1,n=0,o=s=>zx(e(s));return{begin:Mo(s=>be(()=>{let a=t();a.stepIndex!==r&&(r=a.stepIndex,n=0),n++;let i={attempt:a.attempt,stepAttempt:n,stepIndex:a.stepIndex,startNanos:s.monotonicTimeNanosUnsafe()};return Rn(o({_tag:\"AttemptStart\",attempt:i.attempt,stepAttempt:i.stepAttempt,stepIndex:i.stepIndex}),i)})),end:(s,a)=>Mo(i=>{let c=On(i.monotonicTimeNanosUnsafe()-s.startNanos);return o(a._tag===\"Success\"?{_tag:\"AttemptSuccess\",attempt:s.attempt,stepAttempt:s.stepAttempt,stepIndex:s.stepIndex,duration:c}:{_tag:\"AttemptFailure\",attempt:s.attempt,stepAttempt:s.stepAttempt,stepIndex:s.stepIndex,duration:c,cause:a.cause})})}},VF=l(e=>de(e[0]),(e,t,r)=>be(()=>{let n=0,o={attempt:0,stepIndex:0},s=Bx(gg,X(()=>(o={attempt:o.attempt+1,stepIndex:n},o))),a=r?.onEvent===void 0?void 0:M0(r.onEvent,()=>o),i=a===void 0?D:u=>no(f=>oe(a.begin,p=>Mn(f(u),d=>a.end(p,d)))),c;return oe(si({while:()=>np?d:(p=!0,yf(c))),f=Cd(f,vd(u,!1))}else{let p=vd(u,!0);f=p?Cd(f,p):f}return Za(f)},step(u){c=u,n++}}),()=>yf(c))})),vd=(e,t)=>{if(t){if(e.attempts===1||!(e.schedule||e.attempts))return}else return Td({schedule:e.schedule?e.schedule:e.attempts?void 0:y5,times:e.attempts,while:e.while});return Td({schedule:e.schedule,while:e.while,times:e.attempts?e.attempts-1:void 0})},y5=HF(1);var YF=\"~effect/MutableHashMap\";var S5={[YF]:YF,[Symbol.iterator](){return this.backing[Symbol.iterator]()},toString(){return`MutableHashMap(${K(Array.from(this))})`},toJSON(){return{_id:\"MutableHashMap\",values:qt(Array.from(this))}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},$c=()=>{let e=Object.create(S5);return e.backing=new Map,e.buckets=new Map,e};var Nn=l(2,(e,t)=>{if(e.backing.has(t))return _(e.backing.get(t));if(F0(t))return v();let r=V(t),n=e.buckets.get(r);return n===void 0?v():b5(e,n,t)}),F0=e=>typeof e!=\"object\"&&typeof e!=\"function\";var b5=(e,t,r)=>{for(let n=0,o=t.length;nCe(Nn(e,t))),Kc=l(3,(e,t,r)=>{if(e.backing.has(t)||F0(t))return e.backing.set(t,r),e;let n=V(t),o=e.buckets.get(n);if(o===void 0)return e.buckets.set(n,[t]),e.backing.set(t,r),e;let s=E5(o,t);return s===void 0&&(o.push(t),s=t),e.backing.set(s,r),e}),E5=(e,t)=>{for(let r=0,n=e.length;r{if(F0(t))return e.backing.delete(t),e;let r=V(t),n=e.buckets.get(r);if(n===void 0)return e;for(let o=0,s=n.length;o(e.backing.clear(),e.buckets.clear(),e),QF=e=>e.backing.size;var I5=\"~effect/Request\",w5=Rh({_E:e=>e,_A:e=>e,_R:e=>e}),Zpe={...UO,[I5]:w5};var XF=e=>e;var e1=l(2,(e,t)=>{let r=n=>Dt(o=>{let s=r1(n,e,o,sa());return k5(n,s)});return de(t)?oe(t,r):r(t)}),t1=(e,t)=>{let r=r1(t.resolver,e,t.onExit,{context:t.context,cache:{scheduler:Me(t.context,ff)}});return()=>n1(t.resolver,r)},C5=new WeakSet,T5=e=>{if(!C5.has(e.batchKey))return new Map;let t=$c();return{get:r=>ps(Nn(t,r)),has:r=>N0(t,r),set:(r,n)=>Kc(t,r,n),delete:r=>ci(t,r)}},U0=new WeakMap,v5=(e,t,r,n)=>{let o={key:e,context:t,resolver:r,map:n,entrySet:new Set,entries:new Set,delayEffect:oe(se(s=>(o.fiber=s,o.resolver.delay)),s=>o1(o)),run:Mn(be(()=>o.resolver.runAll(Array.from(o.entries),o.key)),s=>{for(let a of o.entrySet)a.completeUnsafe(s._tag===\"Success\"?Gr(new Error(\"Effect.request: RequestResolver did not complete request\",{cause:a.request})):s);return o.entries.clear(),Se})};return o},r1=(e,t,r,n)=>{let o=U0.get(e);o||(o=T5(e),U0.set(e,o));let s,a=!1,i=XF({request:t,context:n.context,uninterruptible:!1,completeUnsafe(f){a||(a=!0,!(s&&!s.entrySet.delete(i))&&r(f))}});if(e.preCheck!==void 0&&!e.preCheck(i))return i;let c=e.batchKey(i);s=o.get(c);let u=s===void 0;if(s||(s=v5(c,n.context,e,o),o.set(c,s)),s.entrySet.add(i),s.entries.add(i),u){let f=ua(n.context)(s.delayEffect,{scheduler:n.cache.scheduler});if(a||o.get(c)!==s)return i;s.fiber=f}return s.resolver.collectWhile(s.entries)||(s.fiber.interruptUnsafe(n.id),ua(s.context)(o1(s),{scheduler:Me(s.context,ff)})),i},n1=(e,t)=>{if(t.uninterruptible)return;let r=U0.get(e);if(!r)return;let n=e.batchKey(t),o=r.get(n);if(!o||!o.entries.delete(t))return;o.entrySet.delete(t);let s;o.entries.size===0&&(r.delete(n),s=o.fiber),t.completeUnsafe(Ef()),s?.interruptUnsafe()},k5=(e,t)=>X(()=>n1(e,t));function o1(e){return e.map.has(e.key)?(e.map.delete(e.key),e.run):Se}var _5=\"effect/Metric/CurrentMetricAttributes\",R5=Te(_5,{defaultValue:()=>({})}),P5=\"effect/Metric/MetricRegistry\",D0=Te(P5,{defaultValue:()=>new Map}),s1=\"~effect/Metric\",a1=class{[s1]=s1;#e;#t;#r=\"\";id;description;attributes;constructor(t,r,n){this.id=t,this.description=r,this.attributes=n}valueUnsafe(t){return this.hook(t).get(t)}modifyUnsafe(t,r){return this.hook(r).modify(t,r)}updateUnsafe(t,r){return this.hook(r).update(t,r)}hook(t){let r=this.key(t),n=Me(t,D0),o=n.get(r);return EO(o)&&(o=this.metadata(this.createHooks()),n.set(r,o)),o.hooks}removeUnsafe(t){Me(t,D0).delete(this.key(t))}registerUnsafe(t,r){let n=this.key(t),o=Me(t,D0),s=this.metadata({get:r.get,update:Wr,modify:Wr});return o.set(n,s),{remove(){o.get(n)===s&&o.delete(n)}}}key(t){let r=Me(t,R5);if(r!==this.#e){this.#e=r;let n=F5(this.attributes,r);this.#t=Object.keys(r).length>0?n:this.attributes,this.#r=M5(this,n)}return this.#r}metadata(t){return{id:this.id,type:this.type,description:this.description,attributes:this.#t,hooks:t}}pipe(){return te(this,arguments)}};var Rf=l(2,(e,t)=>ei(r=>X(()=>e.updateUnsafe(t,r))));function M5(e,t){let r=Object.entries(t).sort((n,o)=>n[0]o[0]?1:0);return JSON.stringify([e.type,e.id,e.description,r])}function F5(e,t){return{...i1(e),...i1(t)}}function i1(e){return cs(e)&&Array.isArray(e)?e.reduce((t,[r,n])=>(B(t,r,n),t),{}):e}var N5=fs,ws=de,Eg=sd,U5=UI,D5=sM,L5=aM,$5=iM,K5=uM,ui=_n,B5=lM,No=si,Mf=XE,fi=FR,g=z,li=Tc,$0=YE,L=be,Y=X,ie=Se;var j5=GI;var Ff=Dt,Bc=Lx,H5=gM,z5=yM,W5=bM;var q5=SM,kt=DR,F=dt,Ig=QE,$e=Le,da=PR,yr=Qa,Nf=MR;var kd=Sf,J5=ZE,Un=se,G5=$O,jc=yf,V5=VE,Z5=RR,Y5=_R,C=oe,K0=JR,Yr=xs,Qr=Vp,Q5=Za,X5=MP,ao=rd,W=Fe,jt=Rn,wg=bf,pi=Zp,e8=jR,B0=mP,t8=xI,Uo=ti;var r8=bI,n8=TP,o8=vP,s8=kP,a8=OP,nt=un,i8=EP,c8=Qp,u8=Hx,f8=bP,l8=yI,p8=ca,Do=EI,d8=II,m8=wI,Ag=SI,h8=AP,f1=IP,x8=wP,g8=jx,l1=CP,y8=AI,S8=Cd,b8=P0,E8=HR,I8=PP,di=zx,w8=VF,A8=sF,C8=_P,T8=RP,v8=KP,k8=vI,O8=TI,j0=$P,mi=Af,_8=BP,H0=sI,R8=aI,P8=zR,Uf=iI,z0=mM,M8=hM,W0=xM,F8=DI,N8=LI,U8=hP,D8=dM,Cg=xP,q0=Wx,L8=td,$8=CI,K8=UP,B8=WR,As=_o,j8=ed,H8=DP,z8=LP,Hc=hI,Od=ei,W8=yg,io=Pn,q8=dP,J0=fP,G0=lP,J8=If,G8=ia,V8=pP,Cs=Lr,Z8=Bx,zc=vc,Tg=OI,vg=Vx,Wc=kc,Y8=ZP,p1=nd,Q8=_I,hi=JP,Lo=MI,X8=GP,eG=FI,_d=Po,Dn=Mn,tG=RI,rG=PI,nG=XP,oG=QP,sG=NI,co=eM,aG=Zx,V0=VP,ma=Oc,$o=no,iG=nM,cG=oM,ir=yP,uG=qF,fG=R0,lG=gI,pG=gP,dG=l(2,(e,t)=>d1(e,void 0,t)),d1=JF,mG=FM,hG=NM,xG=UM,gG=DM,yG=WM,SG=qM,bG=JM,EG=GM,IG=BM,wG=jM,AG=HM,Z0=$M,CG=$p,TG=Kp,vG=zM,kG=KM,OG=df,_G=e1,RG=t1,Df=EM,rr=$I,Lf=CM,PG=IM,MG=wM,FG=NR,NG=UR,Rd=vM,uo=ua,UG=KI,DG=kM,Y0=_M,Q0=BI,kg=OM,LG=Xx,$G=PM,KG=jI,Ts=RM,BG=eg,_e=rI,jG=LR,qc=Mo,HG=Ro,zG=Ro(),WG=Ro(\"Fatal\"),qG=Ro(\"Warn\"),X0=Ro(\"Error\"),JG=Ro(\"Info\"),GG=Ro(\"Debug\"),VG=Ro(\"Trace\"),ZG=l(2,(e,t)=>ia(e,JI,r=>new Set([...r,t]))),YG=l(e=>ws(e[0]),(e,...t)=>ia(e,iF,r=>{let n=t.length===1?{...r,...t[0]}:{...r};return t.length===1||B(n,t[0],t[1]),n})),QG=nF,XG=l(2,(e,t)=>oe(WI,r=>ia(e,cF,n=>[[t,r],...n]))),eV=l(e=>ws(e[0]),(e,t,r)=>Dn(e,n=>{let o=r===void 0?n:r(n);return Rf(t,o)})),tV=l(e=>ws(e[0]),(e,t,r)=>Qr(e,n=>{let o=r===void 0?n:r(n);return Rf(t,o)})),rV=l(e=>ws(e[0]),(e,t,r)=>Ag(e,n=>{let o=r===void 0?n:r(n);return Rf(t,o)})),nV=l(e=>ws(e[0]),(e,t,r)=>l1(e,n=>{let o=r===void 0?n:r(n);return Rf(t,o)})),oV=l(e=>ws(e[0]),(e,t,r)=>qc(n=>{let o=n.monotonicTimeNanosUnsafe();return Dn(e,()=>{let s=n.monotonicTimeNanosUnsafe(),a=W_(ct(s),ct(o)),i=r===void 0?a:r(a);return Rf(t,i)})})),Pf=class extends Et()(\"effect/Effect/Transaction\"){},sV=e=>Un(t=>{let r=ex(t.context,Pf);if(r&&!u1.has(r))return e;let n=t.getRef(Dr),o=n.currentTimeMillisUnsafe(),s={journal:new Map,retry:!1,attempt:1,retryReason:void 0,start:o,now:o,elapsed:0,elapsedSincePrevious:0},a;return $o(i=>{let c=i(e).pipe(Cs(Pf,s),f1(u=>s.retry?Px(u)?i(iV(s)):Y(()=>L0(s)):ie),ao);return C(No({while:()=>!a,body:()=>(s.attempt>1&&aV(s,n.currentTimeMillisUnsafe()),c),step(u){if(s.retry||!m1(s))return s.attempt++,s.retryReason=s.retry?\"retry\":\"conflict\",L0(s);ut(u)&&cV(t,s),L0(s),u1.add(s),a=u}}),()=>a)})}),u1=new WeakSet,aV=(e,t)=>{e.elapsedSincePrevious=t-e.now,e.now=t,e.elapsed=t-e.start},m1=e=>{for(let[t,{version:r}]of e.journal)if(t.version!==r)return!1;return!0},iV=e=>Ff(t=>{if(!m1(e))return t(ie);let r={},n=Array.from(e.journal.keys()),o=()=>{for(let a of n)a.pending.delete(r)},s=()=>{o(),t(ie)};for(let a of n)a.pending.set(r,s);return Y(o)});function cV(e,t){for(let[r,{value:n,written:o}]of t.journal)if(o){Object.is(n,r.value)||(r.version=r.version+1,r.value=n);for(let s of r.pending.values())e.currentDispatcher.scheduleTask(s,0);r.pending.clear()}}function L0(e){e.retry=!1,e.journal.clear()}var uV=C(Pf,e=>{let t=e;return t.retry=!0,co}),fV=(e,t,r)=>(...n)=>Ff(o=>{let s=!0,a;try{e(...n,(i,c)=>{let u=i?t?L(()=>F(t(i,n))):F(i):g(c);s?a??=u:o(u)})}catch(i){a=r?F(r(i,n)):yr(i)}s=!1,a&&o(a)}),lV=()=>e=>e,pV=()=>e=>e,dV=()=>e=>e,fn=GR,$f=VR,Sr=ZR,Ct=qR,Kf=YR,ew=$R;var h1=GE;var xi=Ix,x1=kR,Ko=Dx;var Bf=sa,gi=TM;var br=Symbol.for(\"effect/MutableList/Empty\"),xa=()=>({head:void 0,tail:void 0,length:0}),tw=e=>{let t=e.head;t.offset>=1024&&t===e.tail&&t.mutable&&(t.array.length-t.offset)*8<=t.offset&&(e.head=e.tail={array:t.array.slice(t.offset),mutable:!0,offset:0,next:void 0})},g1=()=>({array:[],mutable:!0,offset:0,next:void 0}),Bo=(e,t)=>{e.tail?e.tail.mutable||(e.tail.next=g1(),e.tail=e.tail.next):e.head=e.tail=g1(),e.tail.array.push(t),e.length++},rw=(e,t)=>{e.head={array:[t],mutable:!0,offset:0,next:e.head},e.tail||(e.tail=e.head),e.length++};var y1=(e,t)=>Md(e,Array.from(t),!0),Md=(e,t,r=!1)=>{if(t.length===0)return 0;let n={array:t,mutable:r,offset:0,next:void 0};return e.head?e.tail=e.tail.next=n:e.head=e.tail=n,e.length+=t.length,t.length},ha=e=>{e.head=e.tail=void 0,e.length=0},Jc=(e,t)=>{if(t=It(t),t<=0||!e.head)return[];if(t=Math.min(t,e.length),t===e.length&&e.head?.offset===0&&!e.head.next){let s=e.head.array;return ha(e),s}let r=new Array(t),n=0,o=e.head;for(;o;){for(;o.offset{if(t=It(t),t<=0||!e.head)return;if(t=Math.min(t,e.length),t===e.length&&e.head?.offset===0&&!e.head.next){ha(e);return}let r=0,n=e.head;for(;n;){let o=n.array.length-n.offset;if(r+o>t){n.offset+=t-r,e.head=n,e.length-=t,tw(e);return}r+=o,n=n.next}ha(e)},yi=e=>Jc(e,e.length),Gc=e=>{if(!e.head)return br;let t=e.head.array[e.head.offset];return e.head.mutable&&(e.head.array[e.head.offset]=void 0),e.head.offset++,e.length--,e.head.offset===e.head.array.length?e.head.next?e.head=e.head.next:ha(e):tw(e),t},S1=(e,t)=>{if(t=It(t),t<=0)return[];let r=Math.min(t,e.length),n=new Array(r),o=0,s=e.head;for(;s;){for(let a=s.offset;a{let r=[],n=e.head,o=0;for(;n;){for(let s=n.offset;snw(e,r=>r!==t);var mV=\"~effect/Queue\",hV=\"~effect/Queue/Enqueue\",xV=\"~effect/Queue/Dequeue\";var ow={_A:D,_E:D},gV={[mV]:ow,[hV]:ow,[xV]:ow,...kr,toJSON(){return{_id:\"effect/Queue\",state:this.state._tag,size:bV(this)}}},fo=e=>se(t=>{let r=Object.create(gV);return r.dispatcher=t.currentDispatcher,r.capacity=e?.capacity??Number.POSITIVE_INFINITY,r.strategy=e?.strategy??\"suspend\",r.messages=xa(),r.scheduleRunning=!1,r.state={_tag:\"Open\",takers:new Set,offers:new Set,awaiters:new Set},z(r)}),Fd=e=>fo({capacity:e});var E1=()=>fo(),Ln=l(2,(e,t)=>be(()=>Pg(e,t)?Fg:e.state._tag===\"Open\"&&e.strategy===\"suspend\"?AV(e,t):w1)),Pg=(e,t)=>e.state._tag!==\"Open\"?!1:e.messages.length>=e.capacity?e.strategy===\"sliding\"?(Gc(e.messages),Bo(e.messages,t),!0):e.capacity<=0&&e.state.takers.size>0?(Bo(e.messages,t),A1(e),!0):!1:(Bo(e.messages,t),Rg(e),!0),Vc=l(2,(e,t)=>Dt(r=>{let n=Mg(e,t);return n.length===0||e.strategy===\"dropping\"?r(We(n)):v1(e,{_tag:\"Array\",remaining:n,offset:0,resume:r})})),Mg=(e,t)=>{if(e.state._tag!==\"Open\")return wt(t);if(e.capacity===Number.POSITIVE_INFINITY||e.strategy===\"sliding\")return y1(e.messages,t),e.strategy===\"sliding\"&&Jc(e.messages,e.messages.length-e.capacity),Rg(e),[];let r=e.capacity<=0?e.state.takers.size:e.capacity-e.messages.length;if(r===0)return wt(t);let n=[],o=0;for(let s of t)oX(()=>Si(e,t))),Si=(e,t)=>{if(e.state._tag!==\"Open\")return!1;let r=Nt(t),n=oP(r,EV);return e.state.offers.size===0&&e.messages.length===0?(Ng(e,n),!0):(e.state={...e.state,_tag:\"Closing\",exit:n},Rg(e),!0)},aw=e=>cr(e,Gu(pc())),Nd=e=>Si(e,Gu(pc()));var lo=e=>X(()=>yV(e)),yV=e=>{if(e.state._tag===\"Done\")return!1;ha(e.messages);let t=e.state.offers;Ng(e,e.state._tag===\"Open\"?IV:e.state.exit);for(let r of t)k1(r);return!0};var Zc=e=>I1(e,1,Number.POSITIVE_INFINITY);var I1=l(3,(e,t,r)=>(t=It(t),r=It(r),C1(()=>wV(e,t,r)??xs(T1(e,()=>iw(e,t)),I1(e,t,r))))),ga=e=>C1(()=>SV(e)??xs(T1(e,()=>iw(e,1)),ga(e)));var SV=e=>{if(e.state._tag===\"Done\")return e.state.exit;if(e.messages.length>0){let t=Gc(e.messages);return sw(e),We(t)}else if(e.capacity<=0&&e.state.offers.size>0){let t=O1(e.state.offers);return sw(e),We(t)}};var bV=e=>e.state._tag===\"Done\"?0:e.messages.length;var w1=We(!1),Fg=We(!0),EV=ko(pc()),IV=Ef(),A1=e=>{if(!(e.state._tag===\"Done\"||e.state.takers.size===0)){for(let t of e.state.takers)if(t.ready()&&(e.state.takers.delete(t),t.resume(Ur),e.messages.length===0))break}},Rg=e=>{e.scheduleRunning||e.state._tag===\"Done\"||e.state.takers.size===0||(e.scheduleRunning=!0,e.dispatcher.scheduleTask(()=>{e.scheduleRunning=!1,A1(e)},0))},wV=(e,t,r)=>{if(e.state._tag===\"Done\")return e.state.exit;if(r<=0||t<=0)return We([]);if(!iw(e,t))return;let n=e.messages.length>0?Jc(e.messages,r):[O1(e.state.offers)];return sw(e),We(n)},C1=Yn({op:\"QueueTake\",[lt](e){let t=this[xe]();return Sp(t)?t[lt](e):t}}),iw=(e,t)=>e.messages.length>=(e.state._tag===\"Closing\"?1:Math.min(t,e.capacity||1))||e.capacity<=0&&e.state._tag!==\"Done\"&&e.state.offers.size>0,T1=(e,t)=>Dt(r=>{if(e.state._tag===\"Done\")return r(e.state.exit);if(t())return r(Ur);let n={ready:t,resume:r};return e.state.takers.add(n),X(()=>{e.state._tag!==\"Done\"&&e.state.takers.delete(n)})}),AV=(e,t)=>Dt(r=>Pg(e,t)?r(Fg):v1(e,{_tag:\"Single\",message:t,resume:r})),v1=(e,t)=>{if(e.state._tag!==\"Open\")return k1(t);let r=e.state.offers;return r.add(t),X(()=>{e.state._tag!==\"Done\"&&(r.delete(t),e.state._tag===\"Closing\"&&r.size===0&&e.messages.length===0&&Ng(e,e.state.exit))})},k1=e=>e._tag===\"Single\"?e.resume(w1):e.resume(We(e.remaining.slice(e.offset))),O1=e=>{let t=e.values().next().value;if(t._tag===\"Single\")return e.delete(t),t.resume(Fg),t.message;let r=t.remaining[t.offset++];return t.offset===t.remaining.length&&(e.delete(t),t.resume(We([]))),r},sw=e=>{if(e.state._tag===\"Done\")return Is(e.state.exit.cause);if(e.state.offers.size===0)return e.state._tag===\"Closing\"&&e.messages.length===0?(Ng(e,e.state.exit),Is(e.state.exit.cause)):!1;for(let t of e.state.offers){let r=e.capacity-e.messages.length;if(r<=0)break;if(t._tag===\"Single\")Bo(e.messages,t.message),e.state.offers.delete(t),t.resume(Fg);else{for(;t.offset{if(e.state._tag===\"Done\")return;let r=e.state;e.state={_tag:\"Done\",exit:t};for(let n of r.takers)n.resume(t);r.takers.clear();for(let n of r.awaiters)n(t);r.awaiters.clear()};var bi=Te(\"effect/crypto/WebCrypto\",{defaultValue:()=>globalThis.crypto});var Ei=class extends Et()(\"effect/crypto/SecureRandom\"){};var Ug=e=>new dw(e),lw=e=>{for(let t of e.waiters)if(t.permits<=e.free)return t},pw=(e,t,r,n=D)=>se(o=>{if(e.free>=t&&lw(e)===void 0)return e.taken+=t,r();let s={permits:t,resume:void 0},a=()=>{e.waiters.delete(s)&&e.releaseUnsafe(o,0)};e.waiters.add(s),oi(o,a);let i=n(Dt(u=>{lw(e)===s?u(Se):s.resume=u})),c=oe(i,()=>lw(e)!==s?c:(e.taken+=t,a(),r()));return c}),dw=class{waiters=new Set;taken=0;permits;constructor(t){this.permits=t}get free(){return this.permits-this.taken}take(t){return pw(this,t,()=>z(t))}takeScoped(t){return no(r=>oe(vc,n=>pw(this,t,()=>Jx(n,this.release(t)),r)))}takeIfAvailable(t){return be(()=>this.free0&&t.currentDispatcher.scheduleTask(()=>{let n=this.free;for(let o of Array.from(this.waiters)){if(!this.waiters.has(o)||o.permits>n)continue;n-=o.permits;let s=o.resume;o.resume=void 0,s?.(Se)}},0),this.free}resize(t){return se(r=>(this.permits=t,this.free<0?Se:(this.releaseUnsafe(r,0),Se)))}release(t){return se(r=>z(this.releaseUnsafe(r,t)))}get releaseAll(){return se(t=>z(this.releaseUnsafe(t,this.taken)))}withPermits(t){return r=>no(n=>pw(this,t,()=>Po(n(r),()=>{this.releaseUnsafe(sa(),t)},!0),n))}withPermit=this.withPermits(1);withPermitsIfAvailable(t){return r=>no(n=>this.free{this.releaseUnsafe(sa(),t)},!0)))}};var hw=1e4,xde=2*hw,R1=/^[+-]?\\d+$/,xw=\"~effect/BigDecimal\",CV={[xw]:xw,[re](){let e=yw(this);return Ee(Pe(String(e.value)),Lt(e.scale))},[ne](e){return gw(e)&&L1(this,e)===0},toString(){return`BigDecimal(${ya(this)})`},toJSON(){return{_id:\"BigDecimal\",value:String(this.value),scale:this.scale}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},gw=e=>A(e,xw),F1=(e,t)=>{if(!Number.isSafeInteger(t))throw new RangeError(`Scale must be a safe integer, got ${t}`);let r=Object.create(CV);return r.value=e,r.scale=t,r},N1=(e,t)=>{let r=F1(e,t);return r.normalized=r,r};var po=BigInt(0),TV=BigInt(1);var vV=BigInt(10),U1=N1(po,0);var yw=e=>{if(e.normalized===void 0)if(e.value===po)e.normalized=U1;else{let t=`${e.value}`,r=D1(t);e.normalized=N1(BigInt(t.slice(0,t.length-r)),e.scale-r)}return e.normalized},D1=e=>{let t=e.length;for(;e[t-1]===\"0\";)t--;return e.length-t};var kV=100,OV=[TV],mw=(e,t)=>e===t?0:e{let r=`${e.value{if(e.scale===t.scale)return mw(e.value,t.value);let r=M1(e),n=M1(t);if(r!==n)return rkV)return r===-1?P1(t,e):P1(e,t);let a=OV[s]??=vV**BigInt(s);return o>0?mw(e.value,t.value*a):mw(e.value*a,t.value)},jf=qa(L1);var M1=e=>e.value===po?0:e.value{if(e===\"\")return _(U1);let t,r,n=e.search(/[eE]/);if(n!==-1){let f=e.slice(n+1);if(t=e.slice(0,n),r=Number(f),t===\"\"||!Number.isSafeInteger(r)||!R1.test(f))return v()}else t=e,r=0;let o,s,a=t.search(/\\./);if(a!==-1){let f=t.slice(0,a),p=t.slice(a+1);if(!/^\\d*$/.test(p))return v();o=`${f}${p}`,s=p.length}else o=t,s=0;if(!R1.test(o))return v();let i=s-r,c=BigInt(o),u=c===po?i:i-D1(o);return i>hw||u<-hw?v():_(F1(c,i))};var ya=e=>{let t=yw(e);if(Math.abs(t.scale)>=16)return _V(t);let r=t.value0?n.padStart(t.scale+1,\"0\"):n.padEnd(n.length-t.scale,\"0\"),s=o.length-t.scale,a=t.scale>0?`${o.slice(0,s)}.${o.slice(s)}`:o;return r?`-${a}`:a},_V=e=>{if(RV(e))return\"0e+0\";let t=yw(e),r=`${t.value}`,n=t.value=0?\"+\":\"\"}${a}`};var RV=e=>e.value===po;var Ie={};An(Ie,{AeadKey:()=>Mv,AeadKeyFromBytes:()=>$ne,AeadKeyFromFormat:()=>Kne,Any:()=>Iee,Array:()=>Be,ArrayEnsure:()=>Mee,BigDecimal:()=>zB,BigDecimalFromString:()=>xre,BigInt:()=>Ul,BigIntFromString:()=>tre,Boolean:()=>Gm,BooleanFromBit:()=>cre,BooleanLiterals:()=>Sv,ByteSize:()=>Kl,ByteSizeFromBigInt:()=>yre,ByteSizeFromNumber:()=>Sre,ByteSizeFromString:()=>gre,Cause:()=>dv,CauseReason:()=>pv,Char:()=>Kte,Chunk:()=>bre,CipherKey:()=>Fv,CipherKeyFromBytes:()=>Bne,CipherKeyFromFormat:()=>jne,Class:()=>Vj,Cookie:()=>Dj,Cookies:()=>Lj,Date:()=>Ll,DateFromMillis:()=>Gte,DateFromString:()=>Jte,DateTimeUtc:()=>Bl,DateTimeUtcFromDate:()=>Tre,DateTimeUtcFromHttpDate:()=>Ore,DateTimeUtcFromMillis:()=>_re,DateTimeUtcFromString:()=>vre,DateTimeZoned:()=>ij,DateTimeZonedFromString:()=>Fre,Defect:()=>jte,DnsARecord:()=>Ij,DnsAaaaRecord:()=>wj,DnsCaaRecord:()=>Aj,DnsCnameRecord:()=>Cj,DnsMxRecord:()=>Tj,DnsNaptrRecord:()=>vj,DnsNsRecord:()=>kj,DnsPtrRecord:()=>Oj,DnsRecord:()=>Rne,DnsRecordType:()=>_ne,DnsSoaRecord:()=>_j,DnsSrvRecord:()=>Rj,DnsTlsaRecord:()=>Pj,DnsTxtRecord:()=>Mj,DomainName:()=>Ua,DomainNameFromString:()=>gj,Duration:()=>vu,DurationFromIsoString:()=>One,DurationFromMillis:()=>kne,DurationFromNanos:()=>vne,DurationFromString:()=>Rv,Enum:()=>Eee,Error:()=>Zj,ErrorInstance:()=>Bte,Exit:()=>toe,FalseLiterals:()=>SB,File:()=>UB,Finite:()=>Dl,FiniteFromString:()=>ere,FormData:()=>DB,Graph:()=>soe,HashMap:()=>aoe,HashSet:()=>ioe,Headers:()=>poe,Host:()=>yne,HostFromString:()=>Sne,HostPort:()=>Sj,HostPortFromString:()=>bne,InetAddress:()=>hj,InetAddressFromString:()=>hne,InetAddressV4:()=>dne,InetAddressV6:()=>mne,Int:()=>tn,IpAddress:()=>Wi,IpAddressFromString:()=>Tu,IpInterface:()=>lj,IpInterfaceFromString:()=>une,IpLinkLocalAddress:()=>Vre,IpLinkLocalAddressFromString:()=>Zre,IpLoopbackAddress:()=>Jre,IpLoopbackAddressFromString:()=>Gre,IpMulticastAddress:()=>Nre,IpMulticastAddressFromString:()=>Ure,IpNetwork:()=>mj,IpNetworkFromString:()=>pne,IpUnicastAddress:()=>$re,IpUnicastAddressFromString:()=>Kre,IpUnspecifiedAddress:()=>Yre,IpUnspecifiedAddressFromString:()=>Qre,Ipv4Address:()=>rh,Ipv4AddressFromString:()=>Ov,Ipv4BroadcastAddress:()=>Hre,Ipv4BroadcastAddressFromString:()=>zre,Ipv4Interface:()=>uj,Ipv4InterfaceFromString:()=>ine,Ipv4Network:()=>pj,Ipv4NetworkFromString:()=>fne,Ipv4PrivateAddress:()=>Xre,Ipv4PrivateAddressFromString:()=>ene,Ipv6Address:()=>$S,Ipv6AddressFromString:()=>cj,Ipv6Interface:()=>fj,Ipv6InterfaceFromString:()=>cne,Ipv6Network:()=>dj,Ipv6NetworkFromString:()=>lne,Ipv6UniqueLocalAddress:()=>tne,Ipv6UniqueLocalAddressFromString:()=>rne,Json:()=>BS,JsonFromUrlParamsField:()=>hoe,JsonObject:()=>qoe,KeyAgreementPrivateKey:()=>Lv,KeyAgreementPrivateKeyFromBytes:()=>Vne,KeyAgreementPrivateKeyFromFormat:()=>Zne,KeyAgreementPublicKey:()=>Dv,KeyAgreementPublicKeyFromBytes:()=>Jne,KeyAgreementPublicKeyFromFormat:()=>Gne,KeyWrapKey:()=>$v,KeyWrapKeyFromBytes:()=>Yne,KeyWrapKeyFromFormat:()=>Qne,KeyWrapPrivateKey:()=>Uj,KeyWrapPrivateKeyFromFormat:()=>eoe,KeyWrapPublicKey:()=>Nj,KeyWrapPublicKeyFromFormat:()=>Xne,Literal:()=>zt,Literals:()=>Jn,MacAddress:()=>Cu,MacAddressFromString:()=>jl,MacBroadcastAddress:()=>Wre,MacBroadcastAddressFromString:()=>qre,MacKey:()=>Pv,MacKeyFromBytes:()=>Dne,MacKeyFromFormat:()=>Lne,MacLocallyAdministeredAddress:()=>nne,MacLocallyAdministeredAddressFromString:()=>one,MacMulticastAddress:()=>Dre,MacMulticastAddressFromString:()=>Lre,MacUnicastAddress:()=>Bre,MacUnicastAddressFromString:()=>jre,MacUniversallyAdministeredAddress:()=>sne,MacUniversallyAdministeredAddressFromString:()=>ane,MutableJson:()=>Goe,Natural:()=>ts,Never:()=>iB,NonEmptyArray:()=>FS,NonEmptyString:()=>th,Null:()=>PS,NullOr:()=>yv,NullishOr:()=>lB,Number:()=>wu,NumberFromString:()=>Xte,ObjectKeyword:()=>Cee,Opaque:()=>qee,Option:()=>ku,OptionFromNullOr:()=>coe,OptionFromNullishOr:()=>foe,OptionFromOptional:()=>yoe,OptionFromOptionalKey:()=>goe,OptionFromOptionalNullOr:()=>Soe,OptionFromUndefinedOr:()=>uoe,Port:()=>Ene,PropertyKey:()=>lv,ReadonlyMap:()=>Hte,ReadonlySet:()=>zte,Record:()=>Na,RecordFromCookies:()=>loe,RecordFromUrlParams:()=>xoe,Redacted:()=>KS,RedactedFromValue:()=>boe,RegExp:()=>Wte,Result:()=>Eoe,RetryAfter:()=>$j,RetryAfterFromString:()=>moe,SchemaError:()=>Ma,ScopedIpv6Literal:()=>_v,ScopedIpv6LiteralFromString:()=>yj,SemVer:()=>zj,SemVerFromString:()=>Ioe,SemVerRange:()=>Jj,SemVerRangeFromString:()=>woe,SignaturePrivateKey:()=>Uv,SignaturePrivateKeyFromBytes:()=>Wne,SignaturePrivateKeyFromFormat:()=>qne,SignaturePublicKey:()=>Nv,SignaturePublicKeyFromBytes:()=>Hne,SignaturePublicKeyFromFormat:()=>zne,SocketAddress:()=>gne,StandardSchemaV1FailureResult:()=>ire,String:()=>H,StringForLiteralAutocomplete:()=>wee,StringFromBase64:()=>nre,StringFromBase64Url:()=>ore,StringFromHex:()=>sre,StringFromUriComponent:()=>are,Struct:()=>ve,StructWithRest:()=>Ree,Symbol:()=>cB,TaggedClass:()=>voe,TaggedError:()=>koe,TaggedStruct:()=>Vm,TaggedUnion:()=>Wee,TemplateLiteral:()=>See,TemplateLiteralParser:()=>bee,TimeZone:()=>sj,TimeZoneFromString:()=>Mre,TimeZoneNamed:()=>nj,TimeZoneNamedFromString:()=>Pre,TimeZoneOffset:()=>Rre,Tree:()=>Woe,Trim:()=>rre,Trimmed:()=>$B,TrueLiterals:()=>yB,Tuple:()=>Ds,TupleWithRest:()=>Pee,URL:()=>LS,URLFromString:()=>qte,URLSearchParams:()=>LB,Uint8Array:()=>$l,Uint8ArrayFromBase64:()=>ure,Uint8ArrayFromBase64Url:()=>fre,Uint8ArrayFromHex:()=>BB,Undefined:()=>xv,UndefinedOr:()=>NS,Union:()=>st,UniqueArray:()=>Fee,UniqueSymbol:()=>Tee,UnixPathAddress:()=>xj,UnixPathAddressFromString:()=>xne,Unknown:()=>Nl,UnknownFromJsonString:()=>Zte,UrlParams:()=>Kv,Void:()=>Aee,annotate:()=>qX,annotateEncoded:()=>JX,annotateKey:()=>GX,asserts:()=>XX,brand:()=>US,catchDecoding:()=>Lee,catchDecodingWithContext:()=>xB,catchEncoding:()=>$ee,catchEncodingWithContext:()=>gB,check:()=>Uee,declare:()=>je,declareConstructor:()=>yn,decode:()=>Kee,decodeEffect:()=>eee,decodeExit:()=>tee,decodeOption:()=>nee,decodePromise:()=>see,decodeResult:()=>oee,decodeSync:()=>aee,decodeTo:()=>J,decodeUnknownEffect:()=>OS,decodeUnknownExit:()=>QK,decodeUnknownOption:()=>ree,decodeUnknownPromise:()=>eB,decodeUnknownResult:()=>XK,decodeUnknownSync:()=>tB,encode:()=>Bee,encodeEffect:()=>iee,encodeExit:()=>cee,encodeKeys:()=>Oee,encodeOption:()=>fee,encodePromise:()=>pee,encodeResult:()=>lee,encodeSync:()=>dee,encodeTo:()=>bv,encodeUnknownEffect:()=>_S,encodeUnknownExit:()=>rB,encodeUnknownOption:()=>uee,encodeUnknownPromise:()=>oB,encodeUnknownResult:()=>nB,encodeUnknownSync:()=>sB,extendTo:()=>_ee,fieldsAssign:()=>vee,flip:()=>fv,fromBrand:()=>Dee,fromFormData:()=>Yte,fromJsonString:()=>vv,fromURLSearchParams:()=>Qte,instanceOf:()=>Au,is:()=>QX,isAscii:()=>ote,isBase64:()=>CB,isBase64Url:()=>ste,isBetween:()=>Ls,isBetweenBigDecimal:()=>hre,isBetweenBigInt:()=>Ote,isBetweenCodePoints:()=>Pte,isBetweenDate:()=>Cte,isBetweenLength:()=>Av,isBetweenProperties:()=>Lte,isBetweenSize:()=>Nte,isCapitalized:()=>lte,isEndingWith:()=>ite,isFinite:()=>dte,isGUID:()=>ete,isGreaterThan:()=>hte,isGreaterThanBigDecimal:()=>lre,isGreaterThanBigInt:()=>Tte,isGreaterThanDate:()=>Ete,isGreaterThanOrEqualTo:()=>TB,isGreaterThanOrEqualToBigDecimal:()=>pre,isGreaterThanOrEqualToBigInt:()=>vB,isGreaterThanOrEqualToDate:()=>Ite,isIncluding:()=>cte,isInt:()=>DS,isInt32:()=>Ste,isLessThan:()=>xte,isLessThanBigDecimal:()=>dre,isLessThanBigInt:()=>vte,isLessThanDate:()=>wte,isLessThanOrEqualTo:()=>gte,isLessThanOrEqualToBigDecimal:()=>mre,isLessThanOrEqualToBigInt:()=>kte,isLessThanOrEqualToDate:()=>Ate,isLowercased:()=>fte,isMaxCodePoints:()=>Rte,isMaxLength:()=>_B,isMaxProperties:()=>Dte,isMaxSize:()=>Fte,isMinCodePoints:()=>_te,isMinLength:()=>wv,isMinProperties:()=>Ute,isMinSize:()=>Mte,isMultipleOf:()=>yte,isNonEmpty:()=>OB,isPattern:()=>zi,isPropertyNames:()=>$te,isSchema:()=>RS,isSchemaError:()=>JK,isStartingWith:()=>ate,isStringBigInt:()=>Vee,isStringFinite:()=>Gee,isStringSymbol:()=>Zee,isTrimmed:()=>AB,isULID:()=>rte,isUUID:()=>Qee,isUint32:()=>bte,isUncapitalized:()=>pte,isUnique:()=>Tv,isUniqueKey:()=>RB,isUppercased:()=>ute,link:()=>ke,linkDecoding:()=>Hi,make:()=>Q,makeClassTrusted:()=>jv,makeFilter:()=>Ne,makeFilterGroup:()=>Jee,makeIsBetween:()=>eh,makeIsGreaterThan:()=>Zm,makeIsGreaterThanOrEqualTo:()=>Ym,makeIsLessThan:()=>Qm,makeIsLessThanOrEqualTo:()=>Xm,makeIsMultipleOf:()=>mte,middlewareDecoding:()=>mB,middlewareEncoding:()=>hB,mutable:()=>Nee,mutableKey:()=>xee,optional:()=>Ml,optionalKey:()=>rs,overrideToCodecIso:()=>Hoe,overrideToEquivalence:()=>Roe,overrideToFormatter:()=>Ooe,readonlyKey:()=>gee,refine:()=>dB,required:()=>hee,requiredKey:()=>mee,resolveAnnotations:()=>Voe,resolveAnnotationsKey:()=>Zoe,revealBottom:()=>WX,revealCodec:()=>VX,suspend:()=>pB,tag:()=>Fa,tagDefaultOmit:()=>zee,toCodecArrayFromSingle:()=>Doe,toCodecGoJson:()=>Loe,toCodecIso:()=>Uoe,toCodecJson:()=>Noe,toCodecStringTree:()=>oh,toDifferJsonPatch:()=>zoe,toEncoded:()=>Fl,toEncoderXml:()=>$oe,toEquivalence:()=>Poe,toFormatter:()=>_oe,toIso:()=>Koe,toIsoFocus:()=>joe,toIsoSource:()=>Boe,toJsonSchemaDocument:()=>Foe,toRepresentation:()=>Moe,toStandardJSONSchemaV1:()=>YX,toStandardSchemaV1:()=>ZX,toTaggedUnion:()=>wB,toType:()=>Sn,withArrayLengthConstraints:()=>MS,withConstructorDefault:()=>bB,withDecodingDefault:()=>IB,withDecodingDefaultKey:()=>Ev,withDecodingDefaultType:()=>Hee,withDecodingDefaultTypeKey:()=>jee});var B1=globalThis.BigInt;var j1=e=>e>B1(Number.MAX_SAFE_INTEGER)||ee.names.map(t=>[t,e])));var bw=e=>e;var Hf=e=>{throw new Error(`Invalid ByteSize: ${e}`)},W1=e=>!Number.isSafeInteger(e)||e<0?Hf(`expected a non-negative safe integer, received ${e}`):bw(BigInt(e)),Rde=BigInt(Number.MAX_SAFE_INTEGER),UV=(e,t)=>{let r=/^(\\d+)(?:\\.(\\d+))?(?:e([+-]\\d+))?$/.exec(e);if(r===null)return;let n=r[2]??\"\",o=BigInt(r[1]+n)*t,s=Number(r[3]??0)-n.length;if(s>=0)return o*BigInt(10)**BigInt(s);let a=BigInt(10)**BigInt(-s);return o%a===Sw?o/a:void 0};var q1=e=>{let t=/^\\s*(\\d+(?:\\.\\d+)?)\\s*([A-Za-z]+)\\s*$/.exec(e);if(t===null)return Hf(`unsupported syntax ${JSON.stringify(e)}`);let r=NV.get(t[2]);if(r===void 0)return Hf(`unsupported unit ${JSON.stringify(t[2])}`);let n=UV(t[1],r.factor);return n===void 0?Hf(`${JSON.stringify(e)} does not represent an integral number of bytes`):bw(n)},J1=Oo(q1),Dg=e=>{switch(typeof e){case\"bigint\":return etypeof e==\"bigint\"?Dg(e):W1(e);var V1=e=>typeof e==\"bigint\"&&e>=Sw;var Lg=e=>e,Z1=j1;var Q1=\"~effect/Chunk\";function Y1(e,t,r,n,o){for(let s=t;sKt((t,r)=>{if(t.length!==r.length)return!1;let n=Yc(t),o=Yc(r);for(let s=0;se},toString(){return`Chunk(${K(Yc(this))})`},toJSON(){return{_id:\"Chunk\",values:qt(Yc(this))}},[Je](){return this.toJSON()},[ne](e){return Kg(e)&&$V(this,e)},[re](){return wo(Yc(this))},[Symbol.iterator](){switch(this.backing._tag){case\"IArray\":return this.backing.array[Symbol.iterator]();case\"IEmpty\":return X1[Symbol.iterator]();default:return Yc(this)[Symbol.iterator]()}},pipe(){return te(this,arguments)}},Aw=e=>{let t=Object.create(KV);switch(t.backing=e,e._tag){case\"IEmpty\":{t.length=0,t.depth=0,t.left=t,t.right=t;break}case\"IConcat\":{t.length=e.left.length+e.right.length,t.depth=1+Math.max(e.left.depth,e.right.depth),t.left=e.left,t.right=e.right;break}case\"IArray\":{t.length=e.array.length,t.depth=0,t.left=Sa,t.right=Sa;break}case\"ISingleton\":{t.length=1,t.depth=0,t.left=Sa,t.right=Sa;break}case\"ISlice\":{t.length=e.length,t.depth=0,t.left=Sa,t.right=Sa;break}}return t},Kg=e=>A(e,Q1),Sa=Aw({_tag:\"IEmpty\"}),BV=()=>Sa;var jV=e=>Aw({_tag:\"ISingleton\",a:e}),Cw=e=>Kg(e)?e:zV(wt(e)),Iw=(e,t,r)=>{switch(e.backing._tag){case\"IArray\":{Y1(e.backing.array,0,t,r,e.length);break}case\"IConcat\":{Iw(e.left,t,r),Iw(e.right,t,r+e.left.length);break}case\"ISingleton\":{t[r]=e.backing.a;break}case\"ISlice\":{Y1(Yc(e.backing.chunk),e.backing.offset,t,r,e.length);break}}};var HV=e=>{switch(e.backing._tag){case\"IEmpty\":return X1;case\"IArray\":return e.backing.array;default:{let t=new Array(e.length);return Iw(e,t,0),e.backing={_tag:\"IArray\",array:t},e.left=Sa,e.right=Sa,e.depth=0,t}}},Yc=HV;var zV=e=>e.length===0?BV():e.length===1?jV(e[0]):Aw({_tag:\"IArray\",array:e});var eN=e=>e.length;var qg={};An(qg,{Aead:()=>jd,aes128Gcm:()=>dZ,aes256Gcm:()=>mZ,chacha20Poly1305:()=>hZ,fromCryptoKey:()=>IZ,isKey:()=>Nw,key:()=>Uw,layerWebCrypto:()=>EZ,layerWebCryptoWith:()=>SN,toBytes:()=>Dw,xchacha20Poly1305:()=>xZ});var tN=\"~effect/crypto/CryptoError\",ks=\"~effect/crypto/CryptoError/Reason\",Qc=class extends Ut(\"InvalidArgument\"){[ks]=ks;get message(){return this.description}},ba=class extends Ut(\"InvalidKey\"){[ks]=ks;get message(){return this.description}},wi=class extends Ut(\"DecryptionFailed\"){[ks]=ks;get message(){return\"Could not decrypt the data\"}},Ai=class extends Ut(\"Unsupported\"){[ks]=ks;get message(){return this.description}},Bg=class extends Ut(\"NotExtractable\"){[ks]=ks;get message(){return this.description}},zf=class extends Ut(\"CryptoError\"){[tN]=tN;cause=\"cause\"in this.reason?this.reason.cause:void 0;get message(){return`${this.module}.${this.method}: ${this.reason.message}`}};function rN(e){return e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name===\"Uint8Array\"&&\"BYTES_PER_ELEMENT\"in e&&e.BYTES_PER_ELEMENT===1}var jg=e=>e?`\"${e}\" `:\"\";function vw(e,t=\"\"){if(typeof e!=\"boolean\")throw new TypeError(jg(t)+\"expected boolean, got type=\"+typeof e);return e}function Wf(e,t=\"\"){if(typeof e!=\"number\")throw new TypeError(jg(t)+\"expected number, got \"+typeof e);if(!Number.isSafeInteger(e)||e<0)throw new RangeError(jg(t)+\"expected integer >= 0, got \"+e);return e}function mo(e,t,r=\"\"){if(rN(e)&&(t===void 0||e.length===t))return e;t!==void 0&&Wf(t,\"length\");let n=rN(e),o=t!==void 0?` of length ${t}`:\"\",s=n?`length=${e.length}`:`type=${typeof e}`,a=jg(r)+\"expected Uint8Array\"+o+\", got \"+s;throw n?new RangeError(a):new TypeError(a)}var nN=(e,t)=>{if(e===null||typeof e!=\"object\"||Array.isArray(e))throw new TypeError(t===\"object\"?\"expected valid options object\":`\"${t}\" expected object, got type=${typeof e}`)};function WV(e,t){return nN(e,\"defaults\"),nN(t,\"opts\"),Object.assign(e,t)}function oN(e,t=!0){if(e.destroyed)throw new Error(\"hash was destroyed\");if(t&&e.finished)throw new Error(\"digest() was already called\")}function qV(e,t){mo(e,void 0,\"output\");let r=t.outputLen;if(!(e.length>=r))throw new RangeError('\"output\" expected length >= '+r)}function Ea(e){return new Uint32Array(e.buffer,e.byteOffset,Math.floor(e.byteLength/4))}function _s(...e){for(let t=0;t>>8&65280|e>>>24&255}function VV(e){for(let t=0;te:VV;function ZV(e,t){return!e.byteLength||!t.byteLength?!1:e.buffer===t.buffer&&e.byteOffsetUint8Array.from(e.split(\"\"),t=>t.charCodeAt(0)),eZ=jo(Ea(cN(\"expand 16-byte k\"))),tZ=jo(Ea(cN(\"expand 32-byte k\")));function Ye(e,t){return e<>>32-t}var Dd=64,rZ=16,Ow=2**32-1,sN=Uint32Array.of();function nZ(e,t,r,n,o,s,a,i){let c=o.length,u=new Uint8Array(Dd),f=Ea(u),p=Os&&Hg(o)&&Hg(s),d=p?Ea(o):sN,m=p?Ea(s):sN;if(!Os){for(let h=0;h=Ow)throw new Error(\"arx: counter overflow\");let y=Math.min(Dd,c-h);for(let S=0,b;S=Ow)throw new Error(\"arx: counter overflow\");let y=Math.min(Dd,c-h);if(p&&y===Dd){let S=h/4;if(h%4!==0)throw new Error(\"arx: invalid block position\");for(let b=0,x;b{mo(i,void 0,\"key\"),mo(c,void 0,\"nonce\"),mo(u,void 0,\"data\");let d=u.length,m=f!==void 0;if(f=kw(d,f,!1),m&&YV(u,f),Wf(p),p<0||p>=Ow)throw new Error(\"arx: counter overflow\");let h=[],y=i.length,S,b;if(y===32)h.push(S=zg(i)),b=tZ;else if(y===16&&r)S=new Uint8Array(32),S.set(i),S.set(i,16),b=eZ,h.push(S);else throw mo(i,32,\"arx key\"),new Error(\"invalid key size\");(!Os||!Hg(c))&&h.push(c=zg(c));let x=Ea(S);if(n){if(c.length!==24)throw new Error(\"arx: extended nonce must be 24 bytes\");let T=c.subarray(0,16);if(Os)n(b,x,Ea(T),x);else{let P=jo(Uint32Array.from(b));n(P,x,Ea(T),x),_s(P),jo(x)}c=c.subarray(16)}else Os||jo(x);let w=16-o;if(w!==c.length)throw new Error(`arx: nonce must be ${w} or 16 bytes`);if(w!==12){let T=new Uint8Array(12);T.set(c,s?0:12-c.length),c=T,h.push(c)}let I=jo(Ea(c));try{return nZ(e,b,x,I,u,f,p,a),f}finally{_s(...h)}}}function _r(e,t){return e[t++]&255|(e[t++]&255)<<8}var _w=class{blockLen=16;outputLen=16;buffer=new Uint8Array(16);r=new Uint16Array(10);h=new Uint16Array(10);pad=new Uint16Array(8);pos=0;finished=!1;destroyed=!1;constructor(t){t=zg(mo(t,32,\"key\"));let r=_r(t,0),n=_r(t,2),o=_r(t,4),s=_r(t,6),a=_r(t,8),i=_r(t,10),c=_r(t,12),u=_r(t,14);this.r[0]=r&8191,this.r[1]=(r>>>13|n<<3)&8191,this.r[2]=(n>>>10|o<<6)&7939,this.r[3]=(o>>>7|s<<9)&8191,this.r[4]=(s>>>4|a<<12)&255,this.r[5]=a>>>1&8190,this.r[6]=(a>>>14|i<<2)&8191,this.r[7]=(i>>>11|c<<5)&8065,this.r[8]=(c>>>8|u<<8)&8191,this.r[9]=u>>>5&127;for(let f=0;f<8;f++)this.pad[f]=_r(t,16+2*f)}process(t,r,n=!1){let o=n?0:2048,{h:s,r:a}=this,i=a[0],c=a[1],u=a[2],f=a[3],p=a[4],d=a[5],m=a[6],h=a[7],y=a[8],S=a[9],b=_r(t,r+0),x=_r(t,r+2),w=_r(t,r+4),I=_r(t,r+6),T=_r(t,r+8),P=_r(t,r+10),G=_r(t,r+12),he=_r(t,r+14),me=s[0]+(b&8191),E=s[1]+((b>>>13|x<<3)&8191),R=s[2]+((x>>>10|w<<6)&8191),N=s[3]+((w>>>7|I<<9)&8191),O=s[4]+((I>>>4|T<<12)&8191),M=s[5]+(T>>>1&8191),U=s[6]+((T>>>14|P<<2)&8191),pe=s[7]+((P>>>11|G<<5)&8191),He=s[8]+((G>>>8|he<<8)&8191),ze=s[9]+(he>>>5|o),ee=0,Qe=ee+me*i+E*(5*S)+R*(5*y)+N*(5*h)+O*(5*m);ee=Qe>>>13,Qe&=8191,Qe+=M*(5*d)+U*(5*p)+pe*(5*f)+He*(5*u)+ze*(5*c),ee+=Qe>>>13,Qe&=8191;let qe=ee+me*c+E*i+R*(5*S)+N*(5*y)+O*(5*h);ee=qe>>>13,qe&=8191,qe+=M*(5*m)+U*(5*d)+pe*(5*p)+He*(5*f)+ze*(5*u),ee+=qe>>>13,qe&=8191;let et=ee+me*u+E*c+R*i+N*(5*S)+O*(5*y);ee=et>>>13,et&=8191,et+=M*(5*h)+U*(5*m)+pe*(5*d)+He*(5*p)+ze*(5*f),ee+=et>>>13,et&=8191;let De=ee+me*f+E*u+R*c+N*i+O*(5*S);ee=De>>>13,De&=8191,De+=M*(5*y)+U*(5*h)+pe*(5*m)+He*(5*d)+ze*(5*p),ee+=De>>>13,De&=8191;let xt=ee+me*p+E*f+R*u+N*c+O*i;ee=xt>>>13,xt&=8191,xt+=M*(5*S)+U*(5*y)+pe*(5*h)+He*(5*m)+ze*(5*d),ee+=xt>>>13,xt&=8191;let vt=ee+me*d+E*p+R*f+N*u+O*c;ee=vt>>>13,vt&=8191,vt+=M*i+U*(5*S)+pe*(5*y)+He*(5*h)+ze*(5*m),ee+=vt>>>13,vt&=8191;let vr=ee+me*m+E*d+R*p+N*f+O*u;ee=vr>>>13,vr&=8191,vr+=M*c+U*i+pe*(5*S)+He*(5*y)+ze*(5*h),ee+=vr>>>13,vr&=8191;let is=ee+me*h+E*m+R*d+N*p+O*f;ee=is>>>13,is&=8191,is+=M*u+U*c+pe*i+He*(5*S)+ze*(5*y),ee+=is>>>13,is&=8191;let Ws=ee+me*y+E*h+R*m+N*d+O*p;ee=Ws>>>13,Ws&=8191,Ws+=M*f+U*u+pe*c+He*i+ze*(5*S),ee+=Ws>>>13,Ws&=8191;let Hu=ee+me*S+E*y+R*h+N*m+O*d;ee=Hu>>>13,Hu&=8191,Hu+=M*p+U*f+pe*u+He*c+ze*i,ee+=Hu>>>13,Hu&=8191,ee=(ee<<2)+ee|0,ee=ee+Qe|0,Qe=ee&8191,ee=ee>>>13,qe+=ee,s[0]=Qe,s[1]=qe,s[2]=et,s[3]=De,s[4]=xt,s[5]=vt,s[6]=vr,s[7]=is,s[8]=Ws,s[9]=Hu}finalize(){let{h:t,pad:r}=this,n=new Uint16Array(10),o=t[1]>>>13;t[1]&=8191;for(let i=2;i<10;i++)t[i]+=o,o=t[i]>>>13,t[i]&=8191;t[0]+=o*5,o=t[0]>>>13,t[0]&=8191,t[1]+=o,o=t[1]>>>13,t[1]&=8191,t[2]+=o,n[0]=t[0]+5,o=n[0]>>>13,n[0]&=8191;for(let i=1;i<10;i++)n[i]=t[i]+o,o=n[i]>>>13,n[i]&=8191;n[9]-=8192;let s=(o^1)-1;for(let i=0;i<10;i++)n[i]&=s;s=~s;for(let i=0;i<10;i++)t[i]=t[i]&s|n[i];t[0]=(t[0]|t[1]<<13)&65535,t[1]=(t[1]>>>3|t[2]<<10)&65535,t[2]=(t[2]>>>6|t[3]<<7)&65535,t[3]=(t[3]>>>9|t[4]<<4)&65535,t[4]=(t[4]>>>12|t[5]<<1|t[6]<<14)&65535,t[5]=(t[6]>>>2|t[7]<<11)&65535,t[6]=(t[7]>>>5|t[8]<<8)&65535,t[7]=(t[8]>>>8|t[9]<<5)&65535;let a=t[0]+r[0];t[0]=a&65535;for(let i=1;i<8;i++)a=(t[i]+r[i]|0)+(a>>>16)|0,t[i]=a&65535;_s(n)}update(t){oN(this),mo(t),t=zg(t);let{buffer:r,blockLen:n}=this,o=t.length;for(let s=0;s>>0,t[s++]=n[a]>>>8}digest(){let{buffer:t,outputLen:r}=this;this.digestInto(t);let n=t.slice(0,r);return this.destroy(),n}};function Rw(e,t,r,n,o,s=20){let a=e[0],i=e[1],c=e[2],u=e[3],f=t[0],p=t[1],d=t[2],m=t[3],h=t[4],y=t[5],S=t[6],b=t[7],x=o,w=r[0],I=r[1],T=r[2],P=a,G=i,he=c,me=u,E=f,R=p,N=d,O=m,M=h,U=y,pe=S,He=b,ze=x,ee=w,Qe=I,qe=T;for(let De=0;De{e.update(t);let r=t.length%16;r&&e.update(iZ.subarray(r))},cZ=new Uint8Array(32);function iN(e,t,r,n,o){o!==void 0&&mo(o,void 0,\"AAD\");let s=e(t,r,cZ),a=XV(n.length,o?o.length:0,!0),i=new _w(s);o&&aN(i,o),aN(i,n),i.update(a);let c=i.digest();return _s(s,a),c}var fN=e=>(t,r,n)=>({encrypt(s,a){let i=s.length;a=kw(i+16,a,!1),a.set(s);let c=a.subarray(0,-16);e(t,r,c,c,1);let u=iN(e,t,r,c,n);return a.set(u,i),_s(u),a},decrypt(s,a){a=kw(s.length-16,a,!1);let i=s.subarray(0,-16),c=s.subarray(-16),u=iN(e,t,r,i,n);if(!QV(c,u)){_s(u);return}return a.set(s.subarray(0,-16)),e(t,r,a,a,1),_s(u),a}}),lN=fN(sZ),pN=fN(aZ);var fZ=()=>new Error(\"crypto.subtle is unavailable; browsers expose it only in secure contexts\"),Ia=(e,t,r)=>F(new zf({module:e,method:t,reason:r})),Ci=(e,t,r)=>Ia(e,t,new ba({description:r})),$d=(e,t)=>Ia(e,t,new Bg({description:\"The CryptoKey is not extractable\"})),Pw=(e,t)=>r=>Ia(e,t,r.reason),Ld=class{reason;constructor(t){this.reason=t}};var qf=(e,t,r,n,o)=>dN(e,t,`${e}.layerWebCrypto`,r,n,o),dN=(e,t,r,n,o,s)=>{let a=lZ(t,r,n,o,s);if(a===void 0)throw o;return new zf({module:e,method:t,reason:a})},lZ=(e,t,r,n,o)=>{if(n instanceof Ld)return n.reason;switch(A(n,\"name\")?n.name:void 0){case\"DataError\":return new ba({description:\"Invalid key data\",cause:n});case\"InvalidAccessError\":return new ba({description:`The key cannot be used for ${e}`,cause:n});case\"NotSupportedError\":return new Ai({description:`${t} does not provide ${r}`,cause:n});case\"OperationError\":return o?.();default:return}},wa=(e,t,r,n,o,s=a=>qf(e,t,r,a))=>L(()=>{let a=n?.subtle;return a===void 0?yr(fZ()):fi({try:()=>o(a),catch:s})}),Kd=(e,t,r,n)=>bi.use(o=>wa(e,t,r,o,n,s=>dN(e,t,\"crypto.subtle\",r,s)));var mN=Symbol(\"~effect/crypto/Key/material\"),Gf=e=>new Uint8Array(e),Ho=e=>e[mN],$r=(e,t)=>({[e]:e,toJSON(){return{_id:t,algorithm:this.algorithm.name}},toString(){return K(this.toJSON())},[Je](){return this.toJSON()}}),hN=(e,t,r)=>Rh(Object.create(e,{algorithm:{value:t,enumerable:!0},[mN]:{value:r}})),zo=(e,t,r)=>hN(e,t,{_tag:\"Bytes\",bytes:r}),Vf=e=>t=>t.length===e.keyLength?void 0:`Expected a ${e.keyLength}-byte key for ${e.name}, not ${t.length} bytes`,ln=(e,t,r,n,o,s)=>L(()=>{if(!(o instanceof Uint8Array))return Ci(e,t,\"Expected the key as a Uint8Array\");let a=s(o);return a===void 0?g(zo(r,n,Gf(o))):Ci(e,t,a)}),Bd=(e,t)=>r=>{let n=r.length;return n===t*8?void 0:`Expected a ${t*8}-bit ${e} key, not ${n} bits`},pZ=(e,t)=>{if(!A(e,\"type\")||!A(e,\"algorithm\")||!A(e,\"usages\")||!Array.isArray(e.usages))return\"Expected a CryptoKey\";if(e.algorithm.name!==t.name)return`Expected a ${t.name} key, not ${e.algorithm.name}`;if(e.type!==t.type)return`Expected a ${t.type} key, not ${e.type}`;let r=t.check?.(e.algorithm);if(r!==void 0)return r;let n=e.usages;if(t.usagePolicy===\"all\"){if(!t.usages.every(o=>n.includes(o)))return`Expected a key with the usages ${t.usages.join(\" and \")}, not ${n.join(\", \")||\"none\"}`}else if(!t.usages.some(o=>n.includes(o)))return`Expected a key with one of the usages ${t.usages.join(\", \")}`},Mw=(e,t)=>{let r=t.algorithm.modulusLength;return A(e,\"modulusLength\")&&r!==void 0&&e.modulusLength!==r?{...e,modulusLength:r}:e},Ti=(e,t,r,n,o,s)=>L(()=>{let a=pZ(o,s);return a===void 0?g(hN(r,Mw(n,o),{_tag:\"CryptoKey\",cryptoKey:o})):Ci(e,t,a)}),vi=async(e,t)=>new Uint8Array(await e.exportKey(\"raw\",t)),Rs=(e,t,r)=>L(()=>{let n=Ho(t);return n._tag===\"Bytes\"?g(Gf(n.bytes)):n.cryptoKey.extractable?Kd(e,\"toBytes\",t.algorithm.name,o=>r(o,n.cryptoKey)):$d(e,\"toBytes\")}),ki=e=>{let t=new WeakMap;return async(r,n)=>{let o=Ho(n);if(o._tag===\"CryptoKey\")return o.cryptoKey;let s=t.get(n);return s===void 0&&(s=await e(r,o.bytes,n.algorithm),t.set(n,s)),s}};var xN=\"~effect/crypto/Aead/Key\",dZ={name:\"aes128Gcm\",keyLength:16,nonceLength:12,implementation:void 0},mZ={name:\"aes256Gcm\",keyLength:32,nonceLength:12,implementation:void 0},gN=e=>({encrypt:(t,r,n,o)=>e(t,r,o).encrypt(n),decrypt:(t,r,n,o)=>e(t,r,o).decrypt(n)}),hZ={name:\"chacha20Poly1305\",keyLength:32,nonceLength:12,implementation:gN(lN)},xZ={name:\"xchacha20Poly1305\",keyLength:32,nonceLength:24,implementation:gN(pN)},Fw=$r(xN,\"Aead.Key\"),Nw=e=>A(e,xN),jd=class extends Et()(\"effect/crypto/Aead\"){},Wg=(e,t)=>Ia(\"Aead\",e,t),yN=()=>Wg(\"decrypt\",new wi),gZ=2**36-32,yZ=16,SZ=(e,t,r,n)=>{let o=t.algorithm;if(n.nonce.length!==o.nonceLength)return Wg(e,new Qc({description:`${o.name} nonces must contain exactly ${o.nonceLength} bytes`}));if(e===\"encrypt\"){if(o.implementation===void 0&&r.length>gZ)return Wg(e,new Qc({description:\"AES-GCM plaintext cannot exceed 2^36 - 32 bytes\"}))}else if(r.length{let s=Ho(r);if(s._tag!==\"Bytes\")return Wg(e,new ba({description:`${r.algorithm.name} keys must hold bytes`}));let a=o.aad??new Uint8Array(0);return e===\"encrypt\"?Y(()=>t.encrypt(s.bytes,o.nonce,n,a)):L(()=>{let i=t.decrypt(s.bytes,o.nonce,n,a);return i===void 0?yN():g(i)})},SN=e=>pa(jd,kt(function*(){let t=yield*Ei,r=yield*bi,n=ki((c,u)=>c.importKey(\"raw\",u,\"AES-GCM\",!1,[\"encrypt\",\"decrypt\"])),o=e.implementations,s=c=>{let u=o?.[c.algorithm.name];return u!==void 0&&Ho(c)._tag===\"Bytes\"?u:c.algorithm.implementation},a=(c,u,f,p)=>{let d={name:\"AES-GCM\",iv:p.nonce,tagLength:128,...p.aad===void 0?{}:{additionalData:p.aad}};return wa(\"Aead\",c,u.algorithm.name,r,async m=>new Uint8Array(await m[c](d,await n(m,u),f)),m=>qf(\"Aead\",c,u.algorithm.name,m,c===\"decrypt\"?()=>new wi:void 0))},i=c=>(u,f,p)=>L(()=>{let d=SZ(c,u,f,p);if(d!==void 0)return d;let m=s(u);return m===void 0?a(c,u,f,p):bZ(c,m,u,f,p)});return jd.of({generateKey:c=>W(t.randomBytes(c.keyLength),u=>zo(Fw,c,u)),encrypt:i(\"encrypt\"),decrypt:i(\"decrypt\")})})),EZ=SN({}),Uw=(e,t)=>ln(\"Aead\",\"key\",Fw,e,t,Vf(e)),IZ=(e,t)=>e.implementation!==void 0?Ci(\"Aead\",\"fromCryptoKey\",`${e.name} keys cannot be CryptoKeys`):Ti(\"Aead\",\"fromCryptoKey\",Fw,e,t,{type:\"secret\",name:\"AES-GCM\",usages:[\"encrypt\",\"decrypt\"],usagePolicy:\"all\",check:Bd(\"AES-GCM\",e.keyLength)}),Dw=e=>Rs(\"Aead\",e,vi);var Jg={};An(Jg,{Cipher:()=>Hd,aes128Cbc:()=>CZ,aes128Ctr:()=>wZ,aes256Cbc:()=>TZ,aes256Ctr:()=>AZ,fromCryptoKey:()=>OZ,isKey:()=>$w,key:()=>Kw,layerWebCrypto:()=>kZ,toBytes:()=>Bw});var IN=\"~effect/crypto/Cipher/Key\",wZ={name:\"aes128Ctr\",mode:\"AES-CTR\",keyLength:16},AZ={name:\"aes256Ctr\",mode:\"AES-CTR\",keyLength:32},CZ={name:\"aes128Cbc\",mode:\"AES-CBC\",keyLength:16},TZ={name:\"aes256Cbc\",mode:\"AES-CBC\",keyLength:32},Lw=$r(IN,\"Cipher.Key\"),$w=e=>A(e,IN),Hd=class extends Et()(\"effect/crypto/Cipher\"){},bN=(e,t)=>Ia(\"Cipher\",e,t),EN=16,vZ=(e,t)=>e.mode===\"AES-CTR\"?{name:\"AES-CTR\",counter:t,length:128}:{name:\"AES-CBC\",iv:t},kZ=pa(Hd,kt(function*(){let e=yield*Ei,t=yield*bi,r=ki((o,s,a)=>o.importKey(\"raw\",s,a.mode,!1,[\"encrypt\",\"decrypt\"])),n=o=>(s,a,i)=>L(()=>{if(i.iv.length!==EN)return bN(o,new Qc({description:\"IVs must contain exactly 16 bytes\"}));let c=s.algorithm.mode===\"AES-CBC\";return o===\"decrypt\"&&c&&(a.length===0||a.length%EN!==0)?bN(o,new wi):wa(\"Cipher\",o,s.algorithm.name,t,async u=>new Uint8Array(await u[o](vZ(s.algorithm,i.iv),await r(u,s),a)),u=>qf(\"Cipher\",o,s.algorithm.name,u,o===\"decrypt\"&&c?()=>new wi:void 0))});return Hd.of({generateKey:o=>W(e.randomBytes(o.keyLength),s=>zo(Lw,o,s)),encrypt:n(\"encrypt\"),decrypt:n(\"decrypt\")})})),Kw=(e,t)=>ln(\"Cipher\",\"key\",Lw,e,t,Vf(e)),OZ=(e,t)=>Ti(\"Cipher\",\"fromCryptoKey\",Lw,e,t,{type:\"secret\",name:e.mode,usages:[\"encrypt\",\"decrypt\"],usagePolicy:\"all\",check:Bd(e.mode,e.keyLength)}),Bw=e=>Rs(\"Cipher\",e,vi);var wN=e=>Uint8Array.of(48,46,2,1,0,48,5,6,3,43,101,e,4,34,4,32),AN=wN(112),CN=wN(110),jw=32,Hw={\"P-256\":32,\"P-384\":48,\"P-521\":66},Zf=(e,t)=>r=>{if(r.length!==jw)return t===\"private\"&&r.length===64?`Expected the 32-byte ${e} seed, not the 64-byte seed\\u2016public key form: pass its first 32 bytes`:`Expected a ${jw}-byte ${e} ${t} key, not ${r.length} bytes`},Gg=e=>t=>{let r=1+2*Hw[e];return t.length!==r?`Expected a ${r}-byte uncompressed ${e} point, not ${t.length} bytes`:t[0]===4?void 0:`Expected an uncompressed ${e} point, starting with 0x04`},Vg=e=>t=>{let r=t.namedCurve;return r===e?void 0:`Expected a ${e} key, not ${r}`},Zg=e=>t=>{let r=t.hash?.name;return r===e?void 0:`Expected a key for ${e}, not ${r}`};var _Z=(e,t)=>{let r=new Uint8Array(e.length+t.length);return r.set(e),r.set(t,e.length),r},TN=(e,t,r,n)=>e.importKey(\"pkcs8\",r.seedPrefix===void 0?t:_Z(r.seedPrefix,t),r.importParams,n,r.privateUsages),vN=(e,t,r)=>e.importKey(r.publicFormat,t,r.importParams,!0,r.publicUsages),RZ=async(e,t,r)=>{let n=new Uint8Array(await e.exportKey(\"pkcs8\",t)),o=r.seedPrefix;if(o===void 0)return n;if(n.length!==o.length+jw||!o.every((s,a)=>n[a]===s))throw new Ld(new Ai({description:`${r.name} private key was exported in an unexpected PKCS#8 form`}));return n.slice(o.length)},PZ=async(e,t,r)=>new Uint8Array(await e.exportKey(r.publicFormat,t)),zw=(e,t,r,n)=>n===\"private\"?RZ(e,t,r):PZ(e,t,r),Yf=(e,t)=>Rs(e.module,t,(r,n)=>zw(r,n,e.specOf(t.algorithm),e.isPrivateKey(t)?\"private\":\"public\"));var _N=\"~effect/crypto/KeyAgreement/PrivateKey\",RN=\"~effect/crypto/KeyAgreement/PublicKey\";var PN=$r(_N,\"KeyAgreement.PrivateKey\"),MN=$r(RN,\"KeyAgreement.PublicKey\"),Ww=e=>A(e,_N),FN=e=>A(e,RN),UZ=e=>e._tag===\"X25519\"?{name:\"X25519\",importParams:{name:\"X25519\"},privateUsages:[\"deriveBits\"],publicUsages:[],seedPrefix:CN,publicFormat:\"raw\"}:{name:\"ECDH\",importParams:{name:\"ECDH\",namedCurve:e.namedCurve},privateUsages:[\"deriveBits\"],publicUsages:[],seedPrefix:void 0,publicFormat:\"raw\",check:Vg(e.namedCurve)},qw={module:\"KeyAgreement\",specOf:UZ,privateKeyProto:PN,publicKeyProto:MN,isPrivateKey:Ww};var NN=(e,t)=>ln(\"KeyAgreement\",\"privateKey\",PN,e,t,Zf(\"X25519\",\"private\")),UN=(e,t)=>ln(\"KeyAgreement\",\"publicKey\",MN,e,t,e._tag===\"Ecdh\"?Gg(e.namedCurve):Zf(\"X25519\",\"public\"));var Jw=e=>Yf(qw,e);var Ca=e=>DZ(typeof e==\"string\"?$N.encode(e):e),Xc=e=>{let t=KZ(e),r=t.length;if(r%4!==0)return q(new ro({kind:\"Decode\",module:\"Base64\",input:t,message:`Length must be a multiple of 4, but is ${r}`}));let n=t.indexOf(\"=\");if(n!==-1&&(nms($9(e,t,r));function K9(e){let t=e2(e.name,e.valueEncoded,e.options);if(t!==void 0)throw t;let r=e.name+\"=\"+e.valueEncoded;if(e.options===void 0)return r;let n=e.options;if(n.maxAge!==void 0){let o=hs(ct(n.maxAge));r+=\"; Max-Age=\"+Math.trunc(o)}if(n.domain!==void 0&&!n.hostOnly&&(r+=\"; Domain=\"+n.domain),n.path!==void 0&&(r+=\"; Path=\"+n.path),n.priority!==void 0)switch(n.priority){case\"low\":r+=\"; Priority=Low\";break;case\"medium\":r+=\"; Priority=Medium\";break;case\"high\":r+=\"; Priority=High\";break}if(n.expires!==void 0&&(r+=\"; Expires=\"+n.expires.toUTCString()),n.httpOnly&&(r+=\"; HttpOnly\"),n.secure&&(r+=\"; Secure\"),n.partitioned&&(r+=\"; Partitioned\"),n.sameSite!==void 0)switch(n.sameSite){case\"lax\":r+=\"; SameSite=Lax\";break;case\"strict\":r+=\"; SameSite=Strict\";break;case\"none\":r+=\"; SameSite=None\";break}return r}var r2=e=>{let t={},r=Object.values(e.cookies);for(let n=0;nObject.values(e.cookies).map(K9);var B9=e=>{try{return decodeURIComponent(e)}catch{return e}};var su=new WeakMap,o2=e=>{if(su.has(e))return su.get(e);throw new Error(\"Unable to get redacted value\"+(e.label?` with label: \"${e.label}\"`:\"\"))};var s2=\"~effect/Redacted\",Xf=e=>A(e,s2),Ta=(e,t)=>{let r=Object.create(z9);return t?.label&&(r.label=t.label),su.set(r,e),r},z9={[s2]:{_A:e=>e},label:void 0,...kr,toJSON(){return this.toString()},toString(){return``},[re](){return V(su.get(this))},[ne](e){return Xf(e)&&Z(su.get(this),su.get(e))}},Mi=o2;var a2=e=>Kt((t,r)=>e(Mi(t),Mi(r)));var $A=Symbol.for(\"~effect/http/Headers\"),c2=e=>A(e,$A),KA=Object.defineProperties(Object.create(null),{[$A]:{value:$A},[Gs]:{value(e){return q9(this,Me(e,J9))}},toJSON:{value(){return Ao(this)}},[ne]:{value(e){return HA(this,e)}},[re]:{value(){return mp(this)}},toString:{value:$t.toString},[Je]:{value:$t[Je]}});var HA=T_(Wa()),W9=Object.create(KA),u2=e=>{if(e===void 0)return W9;if(Symbol.iterator in e){let r=Object.create(KA);for(let[n,o]of e)r[n.toLowerCase()]=o;return r}let t=Object.create(KA);for(let[r,n]of Object.entries(e))Array.isArray(n)?t[r.toLowerCase()]=n.join(\", \"):n!==void 0&&(t[r.toLowerCase()]=n);return t};var q9=l(2,(e,t)=>{let r={...e},n=o=>{if(typeof o==\"string\"){let s=o.toLowerCase();s in e&&(r[s]=Ta(e[s]))}else for(let s in e)s.search(o)!==-1&&(r[s]=Ta(e[s]))};if(Array.isArray(t))for(let o=0;o{let r=e.toLowerCase();for(let n=0;n[\"authorization\",\"cookie\",\"set-cookie\",\"x-api-key\"]}),i2=\"~effect/http/Headers/HeaderParseError\",BA=class extends Np{},hy=class e extends Ut(\"HeaderParseError\"){static fromReason(t,r){return new e({reason:new BA({_tag:t,input:r})})}[i2]=i2;get message(){return`${this.reason._tag}: ${JSON.stringify(this.reason.input)}`}};var G9=[\"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\",\"dec\"],V9=[/^(?:mon|tue|wed|thu|fri|sat|sun), (?\\d{2}) (?[a-z]{3}) (?\\d{4}) (?\\d{2}):(?\\d{2}):(?\\d{2}) gmt$/i,/^(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday), (?\\d{2})-(?[a-z]{3})-(?\\d{2}) (?\\d{2}):(?\\d{2}):(?\\d{2}) gmt$/i,/^(?:mon|tue|wed|thu|fri|sat|sun) (?[a-z]{3}) (? \\d|\\d{2}) (?\\d{2}):(?\\d{2}):(?\\d{2}) (?\\d{4})$/i],l2=e=>{for(let t of V9){let r=t.exec(e)?.groups;if(r===void 0)continue;let n=G9.indexOf(r.month.toLowerCase()),o=Number(r.hour),s=Number(r.minute),a=Number(r.second);if(n===-1||o>23||s>59||a>60)return;let i=Number(r.year);r.year.length===2&&(i+=i<70?2e3:1900);let c=Number(r.day),u=new Date(0);return u.setUTCFullYear(i,n,c),u.getUTCFullYear()!==i||u.getUTCMonth()!==n||u.getUTCDate()!==c?void 0:u.getTime()+((o*60+s)*60+a)*1e3}},p2=e=>{let t=l2(e.trim());return t===void 0?q(hy.fromReason(\"InvalidHttpDate\",e)):j(Vd(t))},zA=e=>cy(e).toUTCString();var Z9=e=>({_tag:\"DateTime\",dateTime:e}),Y9=/^\\d+$/,jA=BigInt(1e9),d2=e=>{let t=e.trim();if(Y9.test(t)){let n=Number(t),o=Number.isSafeInteger(n*1e3)?uf(n):On(BigInt(t)*jA);return j({_tag:\"Duration\",duration:o})}let r=l2(t);return r===void 0?q(hy.fromReason(\"InvalidRetryAfter\",e)):j(Z9(Vd(r)))},m2=e=>e._tag===\"Duration\"?String((yc(e.duration)+jA-BigInt(1))/jA):zA(e.dateTime);var nm=e=>typeof e==\"string\"?e:Mi(e);var WA=\"~effect/http/UrlParams\",qA=e=>A(e,WA),Q9={...kr,[WA]:WA,[Symbol.iterator](){return this.params[Symbol.iterator]()},[Gs](e){return{_id:\"UrlParams\",params:Object.fromEntries(t7(this,Me(e,n7)))}},toJSON(){return Ao(this)},[ne](e){return JA(this,e)},[re](){return wo(this.params.flat())}},xy=e=>{let t=Object.create(Q9);return t.params=e,t},y2=e=>{if(qA(e))return e;let t=S2(e),r=[];for(let n=0;n{let t=typeof e[Symbol.iterator]==\"function\"?wt(e):Object.entries(e),r=[];for(let[n,o]of t)if(Array.isArray(o))for(let s=0;sXf(e)?e:String(e),JA=Kt((e,t)=>X9(e.params,t.params)),X9=__(S_([Wa(),xp()]));var b2=l(2,(e,t)=>hE(e.params,([r])=>r===t).pipe(Vt(([,r])=>nm(r))));var e7=e=>{let t={};for(let[r,n]of e.params){let o=nm(n);if(!Object.hasOwn(t,r))B(t,r,o);else{let s=t[r];typeof s==\"string\"?B(t,r,[s,o]):s.push(o)}}return t},E2=e7,t7=l(2,(e,t)=>{let r=Array.isArray(t)?t:[t];return e.params.map(([n,o])=>[n,typeof o==\"string\"&&r7(n,r)?Ta(o):o])}),r7=f2;var n7=Te(\"effect/http/UrlParams/CurrentRedactedNames\",{defaultValue:()=>[\"X-Amz-Signature\",\"X-Amz-Credential\",\"X-Amz-Security-Token\",\"AWSAccessKeyId\",\"Signature\",\"sig\",\"X-Goog-Signature\"]});var GA=\"~effect/Graph\",VA=e=>A(e,GA),I2=e=>e;var s7=(e,t,r)=>(e===\"directed\"?t.source===r.source&&t.target===r.target:t.source===r.source&&t.target===r.target||t.source===r.target&&t.target===r.source)&&Z(t.data,r.data),a7=(e,t)=>e===\"directed\"?V(t):lr(Ee(V(t.data),i7(t.source,t.target))),i7=(e,t)=>Ee(0,V(e))+Ee(0,V(t)),c7=Pe(\"Graph\"),u7={[GA]:{_N:e=>e,_E:e=>e},[Symbol.iterator](){return this.nodes[Symbol.iterator]()},[Je](){return this.toJSON()},[ne](e){if(A(e,GA)){let t=I2(e);if(this.nodes.size!==t.nodes.size||this.edges.size!==t.edges.size||this.type!==t.type)return!1;for(let[r,n]of this.nodes)if(!t.nodes.has(r)||!Z(n,t.nodes.get(r)))return!1;for(let[r,n]of this.edges){let o=t.edges.get(r);if(o===void 0||!s7(this.type,n,o))return!1}return!0}return!1},[re](){let e=c7;e=e^Pe(this.type),e=e^Lt(this.nodes.size),e=e^Lt(this.edges.size);for(let[t,r]of this.nodes)e^=Ee(V(t),V(r));for(let[t,r]of this.edges)e^=Ee(V(t),a7(this.type,r));return lr(e)},toJSON(){return{_id:\"Graph\",nodeCount:this.nodes.size,edgeCount:this.edges.size,type:this.type}},toString(){return`Graph(${this.type}, ${this.nodes.size}, ${this.edges.size})`},pipe(){return te(this,arguments)}},f7=(e,t)=>{let r=Object.create(u7);return r.type=e,r.mutable=t,r.transforming=!1,r.nodes=new Map,r.edges=new Map,r.adjacency=new Map,r.reverseAdjacency=new Map,r.nextNodeIndex=0,r.nextEdgeIndex=0,r.acyclic=_(!0),r};var om=e=>{let t=I2(e);return{type:e.type,nodes:Array.from(t.nodes,([r,n])=>({index:r,data:n})).sort((r,n)=>r.index-n.index),edges:Array.from(t.edges,([r,n])=>({index:r,source:n.source,target:n.target,data:n.data})).sort((r,n)=>r.index-n.index)}},gy=e=>{let t=f7(e.type,!1);for(let r of e.nodes)t.nodes.set(r.index,r.data),t.adjacency.set(r.index,[]),t.reverseAdjacency.set(r.index,[]);for(let r of e.edges)t.edges.set(r.index,{source:r.source,target:r.target,data:r.data}),t.adjacency.get(r.source).push(r.index),t.reverseAdjacency.get(r.target).push(r.index),e.type===\"undirected\"&&(t.adjacency.get(r.target).push(r.index),t.reverseAdjacency.get(r.source).push(r.index));return t.nextNodeIndex=e.nodes.length===0?0:e.nodes[e.nodes.length-1].index+1,t.nextEdgeIndex=e.edges.length===0?0:e.edges[e.edges.length-1].index+1,t.acyclic=v(),t};function va(e){return e.checks?e.checks[e.checks.length-1].annotations:e.annotations}function yy(e){return t=>va(t)?.[e]}var pn=\"~structural\",au=\"~identifier\",sm=\"~sentinels\",Sy=\"~constructor\",w2=[\"title\",\"description\",\"default\",\"examples\",\"readOnly\",\"writeOnly\",\"format\",\"contentEncoding\",\"contentMediaType\",\"contentSchema\"],el=yy(\"identifier\"),ZA=yy(au),YA=yy(\"title\");var am=on(e=>{let t=va(e)?.identifier;return typeof t==\"string\"?t:e.getExpected(am)}),A2=new Set([sm,pn,\"representation\",\"arbitraryConstraint\",\"toJsonSchema\",\"toCode\",\"toEquivalence\",\"toFormatter\",\"toCodec\",\"toCodecJson\",\"toCodecStringTree\",\"toCodecIso\",\"toCodecArbitrary\"]);var Ae=Symbol();var Er=Vr,dn=Er(Ae),ot=Er(Ae),im=e=>e===Ae?v():_(e),QA=e=>e._tag===\"None\"?dn:Er(e.value);var lm=\"~effect/SchemaIssue/Issue\";function eC(e){return A(e,lm)&&e[lm]===lm}function p7(e){return Object.hasOwn(e,\"input\")}var $n=class{[lm]=lm;constructor(t,r){r?.reportInput===!0&&t!==Ae&&(this.input=t)}},C2=class extends $n{_tag=\"Filter\";filter;issue;constructor(e,t,r,n){super(r,n),this.filter=e,this.issue=t}},T2=class extends $n{_tag=\"Encoding\";ast;issue;constructor(e,t,r,n){super(r,n),this.ast=e,this.issue=t}},Ot=class extends $n{_tag=\"Pointer\";path;issue;constructor(e,t){super(),this.path=e,this.issue=t}},Ni=class extends $n{_tag=\"MissingKey\";annotations;constructor(e){super(),this.annotations=e}},tC=class extends $n{_tag=\"UnexpectedKey\";ast;constructor(e,t,r){super(t,r),this.ast=e}},Ht=class extends $n{_tag=\"Composite\";ast;issues;constructor(e,t,r,n){super(r,n),this.ast=e,this.issues=t}},_t=class extends $n{_tag=\"InvalidType\";ast;constructor(e,t,r){super(t,r),this.ast=e}},fe=class extends $n{_tag=\"InvalidValue\";annotations;constructor(e,t,r){super(t,r),this.annotations=e}};function mn(e,t,r,n,o){return new Ht(e,[new Ot([t],r)],n,o)}var iu=class extends $n{_tag=\"Forbidden\";annotations;constructor(e,t,r){super(t,r),this.annotations=e}},pm=class extends $n{_tag=\"AnyOf\";ast;issues;constructor(e,t,r,n){super(r,n),this.ast=e,this.issues=t}},v2=class extends $n{_tag=\"OneOf\";ast;successes;constructor(e,t,r,n){super(r,n),this.ast=e,this.successes=t}};function XA(e,t,r){if(eC(e))return e;if(typeof e==\"string\")return new fe({message:e},t,r);let n=typeof e.issue==\"string\"?new fe({message:e.issue},t,r):e.issue;return new Ot(e.path,n)}function k2(e,t,r){if(e!==void 0)return typeof e==\"boolean\"?e?void 0:new fe(void 0,t,r):XA(e,t,r)}function O2(e,t,r,n){return Array.isArray(t)?yt(t)?t.length===1?XA(t[0],r,n):new Ht(e,kn(t,o=>XA(o,r,n)),r,n):void 0:k2(t,r,n)}var _2=e=>{let t=rl(e);if(t!==void 0)return t;switch(e._tag){case\"InvalidType\":return tl(am(e.ast),e);case\"InvalidValue\":{let r=M2(e);if(r!==void 0)return tl(r,e);let n=by(e);return n===void 0?\"Expected a valid value\":`Invalid data ${n}`}case\"MissingKey\":return\"Missing key\";case\"UnexpectedKey\":{let r=by(e);return r===void 0?\"Expected no excess property\":`Unexpected key with value ${r}`}case\"Forbidden\":return\"Forbidden operation\";case\"OneOf\":{let r=by(e);return r===void 0?\"Expected exactly one member to match\":`Expected exactly one member to match the input ${r}`}}},R2=e=>rl(e)??rl(e.issue);function P2(e){return t=>({issues:um(t,[],e?.leafHook??_2,e?.checkHook??R2)})}function by(e){return p7(e)?K(e.input):void 0}function M2(e){let t=e.annotations?.expected;return typeof t==\"string\"?t:void 0}function tl(e,t){let r=by(t);return r===void 0?`Expected ${e}`:`Expected ${e}, got ${r}`}function F2(e,t){let r=t(e);if(r!==void 0||e.issue._tag!==\"InvalidValue\")return r;let n=M2(e.issue);return n===void 0?tl(N2(e.filter),e):tl(n,e.issue)}function um(e,t,r,n,o){switch(e._tag){case\"Filter\":return um(e.issue,t,r,n,o??F2(e,n));case\"Encoding\":return um(e.issue,t,r,n,o);case\"Pointer\":return um(e.issue,[...t,...e.path],r,n,o);case\"Composite\":case\"AnyOf\":return e._tag===\"Composite\"||e.issues.length>0?e.issues.flatMap(s=>um(s,t,r,n,o)):[{path:t,message:o??rl(e)??tl(am(e.ast),e)}];default:return[{path:t,message:o??r(e)}]}}function N2(e){let t=e.annotations?.expected;if(typeof t==\"string\")return t;switch(e._tag){case\"Filter\":return\"\";case\"FilterGroup\":return e.checks.map(r=>N2(r)).join(\" & \")}}function d7(){return e=>fm(e,\"\")}var U2=d7();function fm(e,t,r){let n;switch(e._tag){case\"Filter\":return fm(e.issue,t,r??F2(e,R2));case\"Encoding\":return fm(e.issue,t,r);case\"Pointer\":return fm(e.issue,t+Ph(e.path),r);case\"Composite\":case\"AnyOf\":{if(e._tag===\"Composite\"||e.issues.length>0)return e.issues.map(o=>fm(o,t,r)).join(`\n`);n=r??rl(e)??tl(am(e.ast),e);break}default:n=r??_2(e);break}return t?`${n}\n at ${t}`:n}function rl(e){if(e._tag===\"Pointer\"||e._tag===\"Composite\")return;if(e._tag===\"Encoding\")return rl(e.issue);let r=(e._tag===\"Filter\"?e.filter.annotations:\"annotations\"in e?e.annotations:e.ast.annotations)?.[e._tag===\"MissingKey\"?\"messageMissingKey\":e._tag===\"UnexpectedKey\"?\"messageUnexpectedKey\":\"message\"];if(typeof r==\"string\")return r}function dm(e){let t;for(let r of e.reasons){if(!ai(r)||!eC(r.error))return;t??=r.error}return t}function xo(e,t){let r=dm(e);if(r===void 0)throw new Error(t,{cause:e});return r}var L2=(e,t,r)=>{switch(e._tag){case\"Passthrough\":return g(t);case\"Transform\":return g(Vt(t,e.transform));case\"TransformOptional\":return g(e.transform(t));case\"TransformEffect\":return ge(t)?li:fn(e.transform(t.value,r),_);case\"TransformOptionalEffect\":return e.transform(t,r)}};var mm=e=>Object.assign(Object.create(Pb),e),Ey=(e,t)=>rC((r,n)=>Ct(L2(e,r,n),o=>L2(t,o,n))),Iy=l(2,(e,t)=>{if(e._tag===\"Passthrough\")return t;if(t._tag===\"Passthrough\")return e;switch(e._tag){case\"Transform\":switch(t._tag){case\"Transform\":return le(r=>t.transform(e.transform(r)));case\"TransformOptional\":return ka(r=>t.transform(Vt(r,e.transform)));case\"TransformEffect\":return Rt((r,n)=>t.transform(e.transform(r),n));case\"TransformOptionalEffect\":return Ey(e,t)}case\"TransformOptional\":switch(t._tag){case\"Transform\":return ka(r=>Vt(e.transform(r),t.transform));case\"TransformOptional\":return ka(r=>t.transform(e.transform(r)));case\"TransformEffect\":case\"TransformOptionalEffect\":return Ey(e,t)}case\"TransformEffect\":switch(t._tag){case\"Transform\":return Rt((r,n)=>fn(e.transform(r,n),t.transform));case\"TransformOptional\":case\"TransformOptionalEffect\":return Ey(e,t);case\"TransformEffect\":return Rt((r,n)=>Ct(e.transform(r,n),o=>t.transform(o,n)))}case\"TransformOptionalEffect\":return Ey(e,t)}});function m7(e){return rC((t,r)=>F(e(t,r)))}function cu(e){return m7((t,r)=>{let n={message:e(t)};return Ce(t)?new iu(n,t.value,r):new iu(n)})}var $2=cu(()=>\"Encoding is not supported\"),h7=mm({_tag:\"Passthrough\"});function hn(){return h7}function le(e){return mm({_tag:\"Transform\",transform:e})}function Rt(e){return mm({_tag:\"TransformEffect\",transform:e})}function ka(e){return mm({_tag:\"TransformOptional\",transform:e})}function rC(e){return mm({_tag:\"TransformOptionalEffect\",transform:e})}function nC(){return ka(()=>v())}function oC(e){return rC(t=>{let r=hc(t,cs);return Ce(r)?g(r):fn(e,_)})}function uu(){return le(globalThis.String)}function wy(){return le(globalThis.Number)}function K2(){return Rt((e,t)=>{try{return g(globalThis.BigInt(e))}catch{return F(new fe({expected:\"a value that can be converted to a bigint\"},e,t))}})}function sC(){return le(e=>new globalThis.Date(e))}function B2(){return le(KF)}function j2(e){return Rt((t,r)=>Nf({try:()=>JSON.parse(t,e?.reviver),catch:()=>new fe({expected:\"a valid JSON string\"},t,r)}))}function H2(e){return Rt((t,r)=>Nf({try:()=>{let n=JSON.stringify(t,e?.replacer,e?.space);if(n===void 0)throw new TypeError(\"Value cannot be represented as JSON\");return n},catch:()=>new fe({expected:\"a JSON-serializable value\"},t,r)}))}function z2(e){let t=e?.separator??\",\",r=e?.keyValueSeparator??\"=\",n=e?.trim??!1,o=e?.keepEmptyValues??!1;return le(s=>s.split(t).reduce((a,i)=>{let c,u;if(r===\"\")c=i.slice(0,1),u=i.slice(1,2);else{let f=i.indexOf(r);if(f===-1)return a;c=i.slice(0,f),u=i.slice(f+r.length)}return n&&(c=c.trim(),u=u.trim()),c===\"\"||u===\"\"&&!o||B(a,c,u),a},{}))}function W2(e){let t=e?.separator??\",\",r=e?.keyValueSeparator??\"=\";return le(n=>Object.entries(n).map(([o,s])=>`${o}${r}${s}`).join(t))}function q2(e){let t=e?.separator??\",\";return le(r=>r===\"\"?[]:r.split(t))}function aC(){return le(Ca)}function Ay(e){return le(e?.padding?jN:ey)}function Cy(){return le(gx)}function J2(){return Rt((e,t)=>$f(jc(Xc(e)),()=>new fe({expected:\"a valid Base64 string\"},e,t)))}function G2(){return Rt((e,t)=>mr(LN(e),{onFailure:()=>F(new fe({expected:\"a valid Base64 string\"},e,t)),onSuccess:g}))}function V2(){return Rt((e,t)=>mr(Wd(e),{onFailure:()=>F(new fe({expected:\"a valid Base64Url string\"},e,t)),onSuccess:g}))}function Z2(){return Rt((e,t)=>mr(HN(e),{onFailure:()=>F(new fe({expected:\"a valid Base64Url string\"},e,t)),onSuccess:g}))}function Y2(){return Rt((e,t)=>mr(CE(e),{onFailure:()=>F(new fe({expected:\"a valid hexadecimal string\"},e,t)),onSuccess:g}))}function Q2(){return Rt((e,t)=>mr(nR(e),{onFailure:()=>F(new fe({expected:\"a valid hexadecimal string\"},e,t)),onSuccess:g}))}function X2(){return le(encodeURIComponent)}function eD(){return Rt((e,t)=>{try{return g(globalThis.decodeURIComponent(e))}catch{return F(new fe({expected:\"a valid URI component\"},e,t))}})}function tD(){return le(e=>sD(Array.from(e.entries())))}var x7=aD(e=>typeof e==\"string\"||typeof Blob<\"u\"&&e instanceof Blob);function rD(){return le(e=>{let t=new FormData;return typeof e==\"object\"&&e!==null&&x7(e).forEach(([n,o])=>{t.append(n,o)}),t})}function nD(){return le(e=>sD(Array.from(e.entries())))}var g7=aD(qr);function oD(){return le(e=>typeof e==\"object\"&&e!==null?new URLSearchParams(g7(e)):new URLSearchParams)}function y7(e){if(e===\"\")return[\"\"];let t=e.replace(/\\[([^\\]\\r\\n\\u2028\\u2029]*)(\\])?/g,(o,s,a)=>a?`.${s}`:o),r=t.split(\".\"),n=t.startsWith(\".\")?1:0;return r.slice(n).map(o=>of(o)?globalThis.Number(o):o)}var S7=20;function sD(e){let t={},r=new WeakSet,n=new WeakSet,o=new Map;e.forEach(([s,a])=>{let i=y7(s),c=t;for(let u=0;u{let r=[];function n(o,s){if(e(s))r.push([o,s]);else if(Array.isArray(s))s.every(e)?s.forEach(i=>{r.push([o,i])}):s.forEach((i,c)=>{n(`${o}[${c}]`,i)});else if(typeof s==\"object\"&&s!==null)for(let[a,i]of Object.entries(s))n(`${o}[${a}]`,i)}for(let[o,s]of Object.entries(t))n(o,s);return r}}var iD=Symbol.for(\"~effect/Schema/content\");function cD(e,t){return Object.defineProperty(e,iD,{value:t}),e}function uD(e){return e[iD]}var Ty=class extends ja{_tag=\"Middleware\";decode;encode;constructor(e,t){super(),this.decode=e,this.encode=t}flip(){return new Ty(this.encode,this.decode)}},hm=\"~effect/SchemaTransformation/Transformation\",Ke=class extends ja{[hm]=hm;_tag=\"Transformation\";decode;encode;constructor(e,t){super(),this.decode=e,this.encode=t}flip(){return new Ke(this.encode,this.decode)}};function b7(e){return A(e,hm)&&e[hm]===hm}var vy=e=>b7(e)?e:new Ke(e.decode,e.encode);function mt(e){return new Ke(Rt(e.decode),Rt(e.encode))}function Ge(e){return new Ke(le(e.decode),le(e.encode))}function ky(e){return new Ke(ka(e.decode),ka(e.encode))}function lD(){return new Ke(B2(),hn())}function pD(e){return new Ke(z2(e),W2(e))}var E7=new Ke(hn(),hn());function ol(){return E7}var sl=new Ke(wy(),uu()),Oy=new Ke(K2(),uu()),iC=new Ke(sC(),le(qb)),dD=new Ke(sC(),le(e=>e.getTime()));var cC=mt({decode:(e,t)=>Zt(J1(e),{onNone:()=>F(new fe({expected:\"a valid ByteSize string\"},e,t)),onSome:g}),encode:e=>g(`${e} ${e===BigInt(1)?\"byte\":\"bytes\"}`)}),mD=mt({decode:(e,t)=>Zt(Ew(e),{onNone:()=>F(new fe({expected:\"a non-negative bigint byte count\"},e,t)),onSome:g}),encode:e=>g(Lg(e))}),hD=mt({decode:(e,t)=>Zt(Ew(e),{onNone:()=>F(new fe({expected:\"a non-negative safe-integer byte count\"},e,t)),onSome:g}),encode:(e,t)=>Zt(Z1(e),{onNone:()=>F(new fe({expected:\"a ByteSize representable as a safe integer\"},e,t)),onSome:g})}),I7=e=>fr(e)&&typeof e.message==\"string\",xD=e=>{let r=Object.hasOwn(e,\"cause\")?new Error(e.message,{cause:yD(e.cause)}):new Error(e.message);return typeof e.name==\"string\"&&e.name!==\"Error\"&&(r.name=e.name),typeof e.stack==\"string\"&&(r.stack=e.stack),r},w7=e=>{try{let t=nc(e);return t===void 0?K(e):JSON.parse(t)}catch{return K(e)}},A7=(e,t,r)=>{let n={name:e.name,message:typeof e.message==\"string\"?e.message:\"\"};return t?.includeStack&&typeof e.stack==\"string\"&&(n.stack=e.stack),!t?.excludeCause&&e.cause!==void 0&&(n.cause=r(e.cause)),n},gD=e=>{let t=new WeakSet,r=n=>{if(wO(n)){if(t.has(n))return\"[Circular]\";t.add(n);let o=A7(n,e,r);return t.delete(n),o}return w7(n)};return r},yD=e=>I7(e)?xD(e):e,SD=e=>Ge({decode:xD,encode:t=>gD(e)(t)}),bD=e=>Ge({decode:yD,encode:gD(e)});function ED(){return Ge({decode:oE,encode:Zh})}function ID(){return Ge({decode:nE,encode:ps})}function wD(e){return Ge({decode:vp,encode:e?.onNoneEncoding===null?Zh:ps})}function AD(){return ky({decode:_,encode:mc})}function CD(){return ky({decode:e=>e.pipe(hc(cs),_),encode:mc})}var uC=mt({decode:(e,t)=>URL.canParse(e)?g(new URL(e)):F(new fe({expected:\"a valid URL string\"},e,t)),encode:e=>g(e.href)});var fC=new Ke(J2(),aC()),TD=new Ke(G2(),aC()),vD=new Ke(Z2(),Ay()),kD=new Ke(Q2(),Cy()),OD=new Ke(eD(),X2());function _D(e){return new Ke(j2(e??{}),cD(H2(e),{mediaType:\"application/json\",preserveSchema:e?.reviver===void 0&&e?.replacer===void 0}))}var RD=new Ke(tD(),rD()),PD=new Ke(nD(),oD());function Ui(e){return t=>t._tag===e}var fl=Ui(\"Declaration\");var C7=Ui(\"Never\");var il=Ui(\"Literal\"),pC=Ui(\"UniqueSymbol\");var My=Ui(\"Arrays\"),bC=Ui(\"Objects\"),Fy=Ui(\"Union\"),gm=Ui(\"Suspend\"),Tt=class{to;transformation;constructor(e,t){this.to=e,this.transformation=t}},Ns={},Fs=class{isOptional;isMutable;constructorDefault;annotations;constructor(e,t,r=void 0,n=void 0){this.isOptional=e,this.isMutable=t,this.constructorDefault=r,this.annotations=n}},MD=\"~effect/Schema\",Pt=class{[MD]=MD;annotations;checks;encoding;context;constructor(t=void 0,r=void 0,n=void 0,o=void 0){this.annotations=t,this.checks=r,this.encoding=n,this.context=o}toString(){return`<${this._tag}>`}},ll=class extends Pt{_tag=\"Declaration\";typeParameters;run;encodingChecks;encodingRun;constructor(e,t,r,n,o,s,a,i){super(r,n,o,s),this.typeParameters=e,this.run=t,this.encodingChecks=a,this.encodingRun=i}getParser(){let e;return(t,r)=>{if(t===Ae)return dn;e??=this.run(this.typeParameters);try{return e(t,this,r)}catch(n){return yr(n)}}}_rebuild(e,t,r,n,o){let s=lu(this.typeParameters,e);return s===this.typeParameters&&t===this.checks&&r===this.encodingChecks&&n===this.run&&o===this.encodingRun?this:new ll(s,n,this.annotations,t,void 0,this.context,r,o)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks,this.run,this.encodingRun)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks,this.encodingRun??this.run,this.run)}getExpected(){let e=this.annotations?.expected;return typeof e==\"string\"?e:\"\"}},T7=class extends Pt{_tag=\"Null\";getParser(){return Ky(this,null)}getExpected(){return\"null\"}},ym=new T7;var v7=class extends Pt{_tag=\"Undefined\";getParser(){return Ky(this,void 0)}toCodecJson(){return ft(this,[BD])}getExpected(){return\"undefined\"}},BD=new Tt(ym,new Ke(le(()=>{}),le(()=>null))),EC=new v7;var k7=class extends Pt{_tag=\"Void\";getParser(){let e=Er(void 0);return t=>t===Ae?dn:e}toCodecJson(){return ft(this,[BD])}getExpected(){return\"void\"}},jD=new k7;var O7=class extends Pt{_tag=\"Never\";getParser(){return Vo(this,IO)}getExpected(){return\"never\"}},pl=new O7,_7=class extends Pt{_tag=\"Any\";getParser(){return Vo(this,Ub)}getExpected(){return\"any\"}},HD=new _7,R7=class extends Pt{_tag=\"Unknown\";getParser(){return Vo(this,Ub)}getExpected(){return\"unknown\"}},Jo=new R7,P7=class extends Pt{_tag=\"ObjectKeyword\";getParser(){return Vo(this,pp)}getExpected(){return\"object | array | function\"}},zD=new P7,WD=class extends Pt{_tag=\"Enum\";enums;constructor(e,t,r,n,o){super(t,r,n,o);for(let[,s]of e)if(typeof s==\"number\"&&!globalThis.Number.isFinite(s))throw new Error(`A numeric enum value must be finite, got ${K(s)}`);this.enums=e}getParser(){let e=new Set(this.enums.map(([,t])=>t));return Vo(this,t=>e.has(t))}toCodecStringTree(){if(this.enums.some(([e,t])=>typeof t==\"number\")){let e=Object.fromEntries(this.enums.map(([t,r])=>[globalThis.String(r),r]));return ft(this,[new Tt(new Xr(Object.keys(e).map(t=>new Kn(t))),new Ke(le(t=>e[t]),uu()))])}return this}getExpected(){return this.enums.map(([e,t])=>JSON.stringify(t)).join(\" | \")}};function lC(e){return typeof e==\"number\"?`parts[${e}]`:e}function dC(e,t,r){if(r.has(e))return!0;if(e.encoding)throw new Error(`TemplateLiteral parts cannot have an encoding at ${lC(t)}`);let n;switch(e._tag){case\"String\":case\"Number\":case\"BigInt\":n=!0;break;case\"Literal\":n=!e.checks;break;case\"TemplateLiteral\":{let o=lC(t);n=!e.checks&&e.parts.every((s,a)=>dC(s,`${o}.parts[${a}]`,r));break}case\"Union\":{let o=lC(t);n=!e.checks&&e.types.every((s,a)=>dC(s,`${o}.types[${a}]`,r));break}default:return!1}return n&&r.add(e),n}var IC=class extends Pt{_tag=\"TemplateLiteral\";parts;encodedParts;literals;suffixLengths;constructor(e,t,r,n,o){super(t,r,n,o);let s=[],a=[],i=new Set;for(let u=0;u=0;u--)c[u]=c[u+1]+(a[u]?.length??0);this.parts=e,this.encodedParts=s,this.literals=a,this.suffixLengths=c}getParser(e){let t=new jn(!1,this.parts.map(LC),[]),r=e(Oa(xn,t,JD(this)));return(n,o)=>{if(n===Ae)return dn;let s=r(n,o);return s._tag===\"Success\"?ot:Sr(s,{onSuccess:()=>n,onFailure:a=>new Ht(this,[a],n,o)})}}getExpected(){return\"string\"}matchPart(e,t){return hL(this,e,t)===void 0?void 0:e}};function qD(e){let t=on(o=>{if(o._tag!==\"Union\")return o;let s=lu(o.types,t);return(o.options?.mode??\"anyOf\")===\"anyOf\"&&s===o.types?o:new Xr(s,o.options===void 0?void 0:{...o.options,mode:\"anyOf\"},o.annotations,o.checks,void 0,o.context)}),r=new IC(e.map(o=>t(gn(o)))),n=new jn(!1,e.map(LC),[]);return Oa(r,n,JD(r))}function JD(e){return new Ke(Rt((t,r)=>{let n=hL(e,t,r);return n?g(n):F(new fe({expected:\"a string matching template literal parts\"},t,r))}),le(t=>t.join(\"\")))}var GD=class extends Pt{_tag=\"UniqueSymbol\";symbol;constructor(e,t,r,n,o){super(t,r,n,o),this.symbol=e}getParser(){return Ky(this,this.symbol)}toCodecStringTree(){let e=globalThis.Symbol.keyFor(this.symbol);return ft(this,[new Tt(e===void 0?pl:new Kn(globalThis.String(this.symbol)),yL.transformation)])}getExpected(){return globalThis.String(this.symbol)}},Kn=class extends Pt{_tag=\"Literal\";literal;constructor(e,t,r,n,o){if(super(t,r,n,o),typeof e==\"number\"&&!globalThis.Number.isFinite(e))throw new Error(`A numeric literal must be finite, got ${K(e)}`);this.literal=e}getParser(){return Ky(this,this.literal)}matchPart(e,t){return e===globalThis.String(this.literal)?this.literal:void 0}toCodecJson(){return typeof this.literal==\"bigint\"?FD(this):this}toCodecStringTree(){return typeof this.literal==\"string\"?this:FD(this)}getExpected(){return typeof this.literal==\"string\"?JSON.stringify(this.literal):globalThis.String(this.literal)}};function FD(e){let t=globalThis.String(e.literal);return ft(e,[new Tt(new Kn(t),new Ke(le(()=>e.literal),le(()=>t)))])}var M7=class extends Pt{_tag=\"String\";getParser(){return Vo(this,qr)}matchPart(e,t){let r=this.checks;return r&&!t.disableChecks&&Zo(r,e,void 0,this,t)?void 0:e}getExpected(){return\"string\"}},xn=new M7,F7=class extends Pt{_tag=\"Number\";getParser(){return Vo(this,lp)}matchKey(e,t){return this._match(Q7,e,t)}matchPart(e,t){return this._match(gC,e,t)}_match(e,t,r){if(!e.test(t))return;let n=globalThis.Number(t);return r.disableChecks||!this.checks?n:Zo(this.checks,n,void 0,this,r)?void 0:n}toCodecJson(){return this.checks&&(mC(this.checks,\"effect/schema/isFinite\")||mC(this.checks,\"effect/schema/isInt\"))?this:ft(this,[W7])}toCodecStringTree(){return this.toCodecJson()===this?ft(this,[X7]):ft(this,[eY])}getExpected(){return\"number\"}};function mC(e,t){return e.some(r=>r.annotations?.representation?.id===t||r._tag===\"FilterGroup\"&&mC(r.checks,t))}var wC=new F7,N7=class extends Pt{_tag=\"Boolean\";getParser(){return Vo(this,Th)}getExpected(){return\"boolean\"}},VD=new N7,U7=class extends Pt{_tag=\"Symbol\";getParser(){return Vo(this,Nb)}matchKey(e,t){return t.disableChecks||!this.checks?e:Zo(this.checks,e,void 0,this,t)?void 0:e}toCodecStringTree(){return ft(this,[yL])}getExpected(){return\"symbol\"}},ZD=new U7,D7=class extends Pt{_tag=\"BigInt\";getParser(){return Vo(this,bO)}matchPart(e,t){if(!yC.test(e))return;let r=globalThis.BigInt(e);return t.disableChecks||!this.checks?r:Zo(this.checks,r,void 0,this,t)?void 0:r}toCodecStringTree(){return ft(this,[rY])}getExpected(){return\"bigint\"}},YD=new D7,jn=class extends Pt{_tag=\"Arrays\";isMutable;elements;rest;encodingChecks;constructor(e,t,r,n,o,s,a,i){super(n,o,s,a),this.isMutable=e,this.elements=t,this.rest=r,this.encodingChecks=i;let c=!1;for(let u=0;u1)throw new Error(\"A required element cannot follow an optional element. ts(1257)\");for(let u=1;u=f?o[p-f+1]:o[0]}let c=f=>{let{input:p,len:d,options:m}=f;if(r.rest.length===0&&d>s)for(let h=s;h{let d=f.length,m={ast:r,getParser:i,input:f,len:d,tailThreshold:Math.max(s,d-a),output:[],issues:void 0,options:p},h=r.rest.length===0?s:Math.max(d,s+a),y=p.concurrency===void 0?1:ad(p.concurrency),S=y===1?$7(m,f,0,h):K7(m,f,{concurrency:y,end:h});if(!S)return c(m);if(Ve(S))return Ct(S,()=>c(m));let b=!0;return L(()=>b?(b=!1,C(S,()=>c(m))):u(f,p))};return(f,p)=>{if(f===Ae)return dn;try{return Array.isArray(f)?(n||(n=r.elements.map(d=>({ast:d,parser:t(d)})),o=r.rest.map(d=>({ast:d,parser:t(d)}))),u(f,p)):F(new _t(r,f,p))}catch(d){return yr(d)}}}_rebuild(e,t,r){let n=lu(this.elements,e),o=lu(this.rest,e);return n===this.elements&&o===this.rest&&t===this.checks&&r===this.encodingChecks?this:new jn(this.isMutable,n,o,this.annotations,t,void 0,this.context,r)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks)}getExpected(){return\"array\"}};function L7(e,t,r,n){if(r._tag===\"Failure\")return Ry(e,e.ast,n,r);let o=r===ot?t:r[xe];if(o!==Ae)e.output[n]=o;else{let s=e.getParser(e.tailThreshold,n);if(nr(s.ast))return;let a=new Ot([n],new Ni(s.ast.context?.annotations));if(e.options.errors===\"all\")e.issues?e.issues.push(a):e.issues=[a];else return la(new Ht(e.ast,[a],e.input,e.options))}}var QD={onItem(e,t,r){let n=r{if(n.cause.reasons.length===0)return n;let o=dm(n.cause);if(o===void 0)return Fn(fa(n.cause,a=>new Ht(t,[new Ot([r],a)],e.input,e.options)));let s=new Ot([r],o);if(e.options.errors===\"all\")e.issues?e.issues.push(s):e.issues=[s];else return la(new Ht(t,[s],e.input,e.options))},Sm=\"[+-]?(?:\\\\d+(?:\\\\.\\\\d+)?|\\\\.\\\\d+)(?:[Ee][+-]?\\\\d+)?\";function Ms(e,t,r=Ns){let n,o;function s(a){switch(a._tag){case\"String\":case\"TemplateLiteral\":return(n??=Object.keys(e)).filter(i=>a.matchPart(i,r)!==void 0);case\"Number\":return(n??=Object.keys(e)).filter(i=>a.matchKey(i,r)!==void 0);case\"Symbol\":return(o??=Object.getOwnPropertySymbols(e)).filter(i=>Object.prototype.propertyIsEnumerable.call(e,i)&&a.matchKey(i,r)!==void 0);case\"Union\":return[...new Set(a.types.flatMap(s))];default:return[]}}return s(DC(gn(t)))}var AC=class{name;type;constructor(e,t){this.name=e,this.type=t}};function XD(e){switch(e._tag){case\"String\":case\"Number\":case\"Symbol\":case\"TemplateLiteral\":return!0;case\"Union\":return e.types.every(XD);default:return!1}}function eL(e){let t=pu(e);switch(t._tag){case\"String\":case\"Number\":case\"Symbol\":case\"TemplateLiteral\":return!0;case\"Union\":return t.types.every(eL);default:return!1}}function B7(e){return XD(e)&&eL(e)}var CC=class{parameter;type;constructor(e,t){if(!B7(e))throw new Error(`Invalid index signature parameter ${e._tag}`);if(this.parameter=e,this.type=t,nr(t)||t.encoding!==void 0&&nr(gn(t)))throw new Error(\"Cannot use `Schema.optionalKey` or `Schema.optional` with index signatures. Index signatures already allow keys to be absent; use `Schema.UndefinedOr` to allow `undefined` values.\")}},bm=class extends Pt{_tag=\"Objects\";propertySignatures;indexSignatures;encodingChecks;constructor(e,t,r,n,o,s,a){super(r,n,o,s),this.propertySignatures=e,this.indexSignatures=t,this.encodingChecks=a}getParser(e,t=e){let r=this,n=r.propertySignatures.length,o=r.indexSignatures.length;if(!n&&!o)return Vo(r,kh);let s,a,i=()=>(s||(s=r.propertySignatures.map(p=>({parser:t(p.type),name:p.name,type:p.type})),a=o?r.indexSignatures.map(p=>({is:p,parserKey:e(DC(p.parameter)),parserValue:t(p.type)})):void 0),s),c=()=>{let p=new Set(r.propertySignatures.map(S=>typeof S.name==\"number\"?globalThis.String(S.name):S.name)),d=(S,b,x,w,I)=>{if(I._tag===\"Failure\")return Ry(S,r,b,I)??Bt;let T=I===ot?w:I[xe];if(x!==Ae&&T!==Ae){if(n&&(p.has(b)||p.has(typeof x==\"number\"?globalThis.String(x):x)))return Bt;B(S.out,x,T)}return Bt},m=(S,b,x,w)=>{if(!w){let G=x.parserKey(b,S.options);if(!Ve(G))return C(ao(G),he=>m(S,b,x,he));w=G}if(w._tag===\"Failure\")return Ry(S,r,b,w)??Bt;let I=w===ot?b:w[xe],T=S.input[b],P=x.parserValue(T,S.options);return Ve(P)?d(S,b,I,T,P):C(ao(P),G=>d(S,b,I,T,G))},h=(S,b,x)=>{let w=S.input[b],I=x.parserValue(w,S.options);return Ve(I)?d(S,b,b,w,I):C(ao(I),T=>d(S,b,b,w,T))},y=o?Qx()({onItem:(S,[b,x])=>x.is.parameter===xn?h(S,b,x):m(S,b,x),step:(S,b,x)=>x._tag===\"Failure\"?x:void 0}):void 0;return ew(function*(S,b){if(S===Ae)return Ae;if(!(typeof S==\"object\"&&S!==null&&!Array.isArray(S)))return yield*F(new _t(r,S,b));i();let x=S,w={},I={ast:r,input:x,out:w,issues:void 0,options:b},T=b.errors===\"all\",P=b.onExcessProperty===\"error\",G=b.concurrency===void 0?1:ad(b.concurrency),he=o&&P?r.indexSignatures.map(me=>Ms(x,me.parameter,b)):void 0;if(P){let me=he?new Set(p):p;if(he)for(let R of he)for(let N of R)me.add(N);let E=Reflect.ownKeys(x);for(let R=0;R{let h=s[d];return C(ao(m),y=>{let S={...p,out:{...p.out}},b=hC(S,h,y);if(b)return b;let x=()=>Er(S.out),w=ND(S,s.slice(d+1));return w?Ct(w,x):x()})};return(p,d)=>{if(p===Ae)return dn;if(d.errors===\"all\"||d.onExcessProperty!==void 0||d.concurrency!==void 0&&ad(d.concurrency)!==1)return(u??=c())(p,d);if(!(typeof p==\"object\"&&p!==null&&!Array.isArray(p)))return F(new _t(r,p,d));let m=i(),h=p,y={},S={ast:r,input:h,out:y,issues:void 0,options:d};try{for(let b=0;b{let i=e(a.type);return i===a.type?a:new AC(a.name,i)}),s=lu(this.indexSignatures,a=>{let i=t(a.parameter),c=e(a.type);return i===a.parameter&&c===a.type?a:new CC(i,c)});return o===this.propertySignatures&&s===this.indexSignatures&&r===this.checks&&n===this.encodingChecks?this:new bm(o,s,this.annotations,r,void 0,this.context,n)}flip(e){return this._rebuild(e,e,this.encodingChecks,this.checks)}recur(e,t=e){return this._rebuild(e,t,this.checks,this.encodingChecks)}getExpected(){return this.propertySignatures.length===0&&this.indexSignatures.length===0?\"object | array\":\"object\"}};function hC(e,t,r){if(r._tag===\"Failure\")return Ry(e,e.ast,t.name,r);if(r===ot)return;let n=r[xe];if(n!==Ae){B(e.out,t.name,n);return}if(delete e.out[t.name],!nr(t.type)){let o=new Ot([t.name],new Ni(t.type.context?.annotations));if(e.options.errors===\"all\"){e.issues?e.issues.push(o):e.issues=[o];return}else return la(new Ht(e.ast,[o],e.input,e.options))}}var tL={onItem(e,t){if(!al(e.input,t.name))return t.parser(Ae,e.options);let r=e.input[t.name];return B(e.out,t.name,r),t.parser(r,e.options)},step:hC},ND=Yx()(tL),j7=Qx()(tL);function TC(e,t){return e?t?[...e,...t]:e:t}function Ny(e,t,r){return new bm(Reflect.ownKeys(e).map(n=>new AC(n,e[n].ast)),[],r,t)}function Em(e){return e.ast}function vC(e,t=void 0){return new jn(!1,e.map(r=>r.ast),[],void 0,t)}function Uy(e,t,r){return new Xr(e.map(Em),t,void 0,r)}function rL(e,t){if(e.encoding||t.some(s=>s.encoding))throw new Error(\"StructWithRest does not support encodings\");let r=e.propertySignatures,n=e.indexSignatures,o=e.checks;for(let s of t){for(let a of s.propertySignatures)if(r.some(i=>i.name===a.name))throw new Error(`Duplicate identifier: ${JSON.stringify(a.name)}. ts(2300)`);r=r.concat(s.propertySignatures),n=n.concat(s.indexSignatures),o=TC(o,s.checks)}return new bm(r,n,void 0,o)}function nL(e,t){if(e.encoding)throw new Error(\"TupleWithRest does not support encodings\");return new jn(e.isMutable,e.elements,t,void 0,e.checks)}function oL(e){if(e.encoding)throw new Error(\"mutable does not support encodings\");return new jn(!0,e.elements,e.rest,e.annotations,e.checks,void 0,e.context,e.encodingChecks)}var kC=qs(e=>{for(;;){if(gm(e))return Jo;let t=e.encoding;if(!t)return e.recur?.(kC,D)??e;if(t.some(r=>r.transformation._tag===\"Middleware\"&&r.transformation.decode!==D))return Jo;e=t[t.length-1].to}});function sL(e){switch(e._tag){case\"Null\":return[\"null\"];case\"Undefined\":return[\"undefined\"];case\"String\":case\"TemplateLiteral\":return[\"string\"];case\"Number\":return[\"number\"];case\"Boolean\":return[\"boolean\"];case\"Symbol\":case\"UniqueSymbol\":return[\"symbol\"];case\"BigInt\":return[\"bigint\"];case\"Arrays\":return[\"array\"];case\"ObjectKeyword\":return[\"object\",\"array\",\"function\"];case\"Objects\":return e.propertySignatures.length||e.indexSignatures.length?[\"object\"]:[\"string\",\"number\",\"boolean\",\"symbol\",\"bigint\",\"object\",\"array\",\"function\"];case\"Enum\":return Array.from(new Set(e.enums.map(([,t])=>typeof t)));case\"Literal\":return[typeof e.literal];case\"Union\":return Array.from(new Set(e.types.flatMap(sL)));default:return[\"null\",\"undefined\",\"string\",\"number\",\"boolean\",\"symbol\",\"bigint\",\"object\",\"array\",\"function\"]}}function cl(e){switch(e._tag){default:return[];case\"Declaration\":{let t=e.annotations?.[sm];return Array.isArray(t)?t:[]}case\"Objects\":return e.propertySignatures.flatMap(t=>{let r=t.type;if(!nr(r)){if(il(r))return[{key:t.name,literal:r.literal}];if(pC(r))return[{key:t.name,literal:r.symbol}]}return[]});case\"Arrays\":return e.elements.flatMap((t,r)=>{if(!nr(t)){if(il(t))return[{key:r,literal:t.literal}];if(pC(t))return[{key:r,literal:t.symbol}]}return[]});case\"Union\":{if(e.types.length===0)return[];let t=e.types.map(r=>cl(kC(r)));return t[0].filter(r=>t.every(n=>n.some(o=>o.key===r.key&&o.literal===r.literal)))}case\"Suspend\":return cl(e.thunk())}}var UD=new WeakMap,_y=Object.freeze([]),DD=e=>e===null?\"null\":Array.isArray(e)?\"array\":typeof e,al=(e,t)=>t===\"__proto__\"?Object.hasOwn(e,t):t in e;function Im(e){let t=UD.get(e);if(t)return t;let r,n=0,o,s,a=!0,i=[];for(let f=0;fc[f]??=Object.freeze(o?.[f]??_y);if(a&&s)s.forEach(Object.freeze),t=f=>s.get(f)??_y;else if(r?.size===1&&!o){let[f,[p]]=r.entries().next().value,d=new Map;for(let[h,y]of p)d.set(h,Object.freeze(Array.from(y)));let m=Object.freeze(e.map((h,y)=>y));t=(h,y)=>{if(pp(h)){let S=al(h,f)?h[f]:void 0;if(S!==void 0)return d.get(S)??_y;if(y)return m}return _y}}else if(r){let f;for(let p of r)(!f||p[1][0].size>f[1][0].size)&&p[1][1].size===n&&(f=p);t=(p,d)=>{let m=DD(p);if(!pp(p))return u(m);let h=new Set(o?.[m]),y;if(f){let[S,[b]]=f,x=al(p,S),w=x?p[S]:void 0;if(x&&(!d||w!==void 0)){let I=b.get(w);if(!I)return u(m);for(let T of I)h.add(T);y=S}}if(y===void 0)for(let[S,[b,x]]of r){let w=al(p,S),I=w?p[S]:void 0;if(w&&(!d||I!==void 0)){let T=b.get(I);if(T)for(let P of T)h.add(P)}else if(d)for(let T of x)h.add(T)}for(let[S,[b,x]]of r){if(S===y)continue;let w=al(p,S),I=w?p[S]:void 0;if(w&&(!d||I!==void 0)){let T=b.get(I);for(let P of h)x.has(P)&&!T?.has(P)&&h.delete(P)}}return Array.from(h).sort((S,b)=>S-b)}}else t=f=>{let p=u(DD(f));return s?p.filter(d=>i[d]===void 0||i[d]===f):p};return UD.set(e,t),t}var Xr=class extends Pt{_tag=\"Union\";types;options;encodingChecks;constructor(e,t,r,n,o,s,a){super(r,n,o,s),this.types=e,this.options=t,this.encodingChecks=a}getParser(e,t){let r=this,n=t!==void 0,o=[],s=i=>o[i]??=e(r.types[i]),a;return(i,c)=>{if(i===Ae)return dn;let u=(a??=Im(r.types))(i,n);if(u.length===0)return F(new pm(r,[],i,c));if(u.length===1){let f=s(u[0])(i,c);return f._tag===\"Success\"?f:Ve(f)?aL(r,f.cause,i,c):H7(r,f,i,c)}return iL(r,s,u,i,c)}}_rebuild(e,t,r){let n=lu(this.types,e);return n===this.types&&t===this.checks&&r===this.encodingChecks?this:new Xr(n,this.options,this.annotations,t,void 0,this.context,r)}recur(e){return this._rebuild(e,this.checks,this.encodingChecks)}flip(e){return this._rebuild(e,this.encodingChecks,this.checks)}matchPart(e,t){for(let r of this.types){let n=r.matchPart(e,t);if(n!==void 0)return n}}getExpected(e){let t=this.annotations?.expected;if(typeof t==\"string\")return t;if(this.types.length===0)return\"never\";let r=this.types.map(n=>{let o=gn(n);switch(o._tag){case\"Arrays\":{let s=o.elements.filter(il);if(s.length>0)return`${$D(o.isMutable)}[ ${s.map(a=>e(a)+KD(a.context?.isOptional)).join(\", \")}, ... ]`;break}case\"Objects\":{let s=o.propertySignatures.filter(a=>il(a.type));if(s.length>0)return`{ ${s.map(a=>`${$D(a.type.context?.isMutable)}${us(a.name)}${KD(a.type.context?.isOptional)}: ${e(a.type)}`).join(\", \")}, ... }`;break}}return e(o)});return Array.from(new Set(r)).join(\" | \")}};function aL(e,t,r,n){let o=dm(t);return o?la(new pm(e,[o],r,n)):Fn(t)}function H7(e,t,r,n){return nt(t,o=>aL(e,o,r,n))}function iL(e,t,r,n,o){let s={ast:e,parser:t,input:n,out:void 0,successes:e.options?.mode===\"oneOf\"?[]:void 0,issues:void 0,options:o},a=z7(s,r);if(!a)return s.out?s.out:F(new pm(e,s.issues??[],n,o));if(Ve(a))return LD(a,s);let i=!0;return L(()=>i?(i=!1,LD(a,s)):iL(e,t,r,n,o))}function LD(e,t){return Ct(e,r=>t.out===ot?g(t.input):t.out?t.out:F(new pm(t.ast,t.issues??[],t.input,t.options)))}var z7=Yx()({onItem(e,t){return e.parser(t)(e.input,e.options)},step(e,t,r){if(r._tag===\"Failure\"){let n=dm(r.cause);if(n===void 0)return r;e.issues?e.issues.push(n):e.issues=[n]}else{if(e.out&&e.successes)return e.successes.push(e.ast.types[t]),la(new v2(e.ast,e.successes,e.input,e.options));if(e.out=r,e.successes)e.successes.push(e.ast.types[t]);else return Bt}}}),cL=new Xr([new Kn(\"Infinity\"),new Kn(\"-Infinity\"),new Kn(\"NaN\")]);function $D(e){return e?\"\":\"readonly \"}function KD(e){return e?\"?\":\"\"}var OC=class extends Pt{_tag=\"Suspend\";thunk;constructor(e,t,r,n,o){if(r)throw new Error(\"Cannot add checks to Suspend\");super(t,void 0,n,o);let s;this.thunk=()=>s??=e()}getParser(e){let t;return(r,n)=>(t??=e(this.thunk()))(r,n)}recur(e){return new OC(()=>e(this.thunk()),this.annotations,void 0,void 0,this.context)}getExpected(e){return e(this.thunk())}},Py=class extends ja{_tag=\"Filter\";run;annotations;aborted;constructor(e,t=void 0,r=!1){super(),this.run=e,this.annotations=t,this.aborted=r}annotate(e){return new Py(this.run,{...this.annotations,...e},this.aborted)}abort(){return new Py(this.run,this.annotations,!0)}and(e,t){return new fu([this,e],t)}},fu=class extends ja{_tag=\"FilterGroup\";checks;annotations;constructor(e,t=void 0){super(),this.checks=e,this.annotations=t}annotate(e){return new fu(this.checks,{...this.annotations,...e})}and(e,t){return new fu([this,e],t)}};function Dy(e,t,r=!1){return new Py((n,o,s)=>O2(o,e(n,o,s),n,s),t,r)}function Ly(e,t){return new Py((r,n,o)=>e(r)?void 0:new fe(void 0,r,o),t,!0)}function _C(e){return Dy(t=>globalThis.Number.isFinite(t),{expected:\"a finite number\",representation:{id:\"effect/schema/isFinite\",payload:null},toJsonSchema:()=>({type:\"number\"}),toCode:()=>({runtime:\"Schema.isFinite()\"}),arbitraryConstraint:{number:\"finite\"},...e})}var RC=Us(wC,[_C()]),W7=new Tt(new Xr([RC,cL]),new Ke(wy(),le(e=>globalThis.Number.isFinite(e)?e:globalThis.String(e))));function wm(e,t){let r=new globalThis.RegExp(e),n={source:r.source,flags:r.flags};return Dy(o=>(r.lastIndex=0,r.test(o)),{expected:`a string matching the RegExp ${n.source}`,representation:{id:\"effect/schema/isPattern\",payload:n},toJsonSchema:()=>[{},!0],arbitraryConstraint:{patterns:[n]},...t})}var xC=new WeakMap;function Am(e,t){let r=Object.assign(Object.create(Object.getPrototypeOf(e)),e,t);return Reflect.ownKeys(t).every(n=>n===\"context\"||n===\"encoding\")&&xC.set(r,Di(e)),r}function Di(e){let t=xC.get(e);if(t!==void 0)return t;if(e.encoding===void 0)return e;let r=Object.assign(Object.create(Object.getPrototypeOf(e)),e,{encoding:void 0});return xC.set(e,r),r}function ft(e,t){return e.encoding===t?e:Am(e,{encoding:t})}function Hn(e,t){if(e.context===t)return e;let r=Di(e);return r.context===t&&r.encoding===e.encoding?r:Am(e,{context:t})}function pu(e){return e.encoding?pu(e.encoding[e.encoding.length-1].to):e}function Go(e,t){if(e.checks){let r=e.checks[e.checks.length-1];return Cm(e,sx(e.checks.slice(0,-1),r.annotate(t)))}return Am(e,{annotations:{...e.annotations,...t}})}function Cm(e,t){if(e._tag===\"Suspend\"&&t)throw new Error(\"Cannot add checks to Suspend\");return e.checks===t?e:Am(e,{checks:t})}function Us(e,t){return Cm(e,TC(e.checks,t))}function dl(e,t){let r=t(e.to);return r===e.to?e:new Tt(r,e.transformation)}function PC(e,t){let r=e,n=r[r.length-1],o=dl(n,t);return o===n?e:sx(e.slice(0,e.length-1),o)}function MC(e){return t=>t.encoding?ft(t,PC(t.encoding,e)):t}function FC(e,t){return MC(r=>Hn(r,t))(e)}function ml(e){function t(r){return r.encoding?ft(r,PC(r.encoding,t)):e(r)}return on(t)}function du(e,t){function r(n){if(n.encoding){let o=n.encoding[n.encoding.length-1];return t?.stopAt?.(o)?n:ft(n,PC(n.encoding,r))}return e(n)}return qs(r)}function uL(e,t){return NC(e,t,Mt(e))}function fL(e,t){return NC(gn(e),t,e)}function NC(e,t,r){let n=new Tt(e,t);return ft(r,r.encoding?[...r.encoding,n]:[n])}function lu(e,t){let r;for(let n=0;n{let t=e.context?e.context.isOptional===!1?new Fs(!0,e.context.isMutable,e.context.constructorDefault,e.context.annotations):e.context:new Fs(!0,!1);return q7(Hn(e,t))}),q7=MC(mu),lL=on(e=>mu(new Xr([e,EC]))),UC=qs(e=>{let t=e.context?e.context.isMutable===!1?new Fs(e.context.isOptional,!0,e.context.constructorDefault,e.context.annotations):e.context:new Fs(!1,!0);return J7(Hn(e,t))}),J7=MC(UC);function pL(e,t){let r=e.context?new Fs(e.context.isOptional,e.context.isMutable,t,e.context.annotations):new Fs(!1,!1,t);return Hn(e,r)}function Oa(e,t,r){return NC(e,r,t)}function G7(e){let t=[],r=[];function n(s){t.includes(s)||t.push(s)}function o(s){switch(s._tag){case\"Literal\":vh(s.literal)&&n(s.literal);return;case\"UniqueSymbol\":n(s.symbol);return;case\"Enum\":for(let[,a]of s.enums)n(a);return;case\"Never\":return;case\"Union\":for(let a=0;anew AC(o,t)),n.map(o=>new CC(o,t)))}function nr(e){return e.context?.isOptional??!1}function dL(e){return e.context?.isMutable??!1}function mL(e){return e.annotations?.[pn]===!0||e._tag===\"FilterGroup\"&&e.checks.every(mL)}function V7(e){function t(n){return mL(n)?[n]:n._tag===\"FilterGroup\"?n.checks.flatMap(t):[]}let r=e.flatMap(t);return Mr(r)?r:void 0}function Z7(e){let t=!0;function r(n){return t=t&&!n.encoding&&!gm(n),t&&\"recur\"in n&&n.recur(r),n}return\"recur\"in e&&e.recur(r),t}var Mt=qs(e=>{let t=Di(e);if(t!==e){let n=Mt(t);return n===t&&e.encoding===void 0?e:Hn(n,e.context)}let r=\"recur\"in e?e.recur(Mt):e;if(\"encodingChecks\"in r&&r.encodingChecks){let n=Z7(e)?r.encodingChecks:My(r)||bC(r)||fl(r)&&r.typeParameters.length>0?V7(r.encodingChecks):void 0;return Am(r,{encodingChecks:void 0,checks:TC(r.checks,n)})}return r}),gn=qs(e=>Mt(Bn(e)));function Y7(e,t){let r=t,n=r.length,o=r[n-1],s=[new Tt(Bn(ft(e,void 0)),r[0].transformation.flip())];for(let i=1;i{if(e.encoding)return Y7(e,e.encoding);let t=Di(e);if(t!==e){let r=Bn(t);return r===t?e:Hn(r,e.context)}return\"flip\"in e?e.flip(Bn):\"recur\"in e?e.recur(Bn):e});function Ky(e,t){let r=t===0?ot:Er(t);return(n,o)=>n===Ae?dn:n===t?r:F(new _t(e,n,o))}function Vo(e,t){return(r,n)=>r===Ae?dn:t(r)?ot:F(new _t(e,r,n))}function hL(e,t,r){let n=e.encodedParts,o=e.literals,s=t.length;for(let u=0;us)return;let a=new Array(n.length),i;function c(u,f){if(u===n.length)return f===s;if(i?.has(u*(s+1)+f))return!1;let p=n[u];if(u===n.length-1){let d=t.slice(f);if(p.matchPart(d,r)!==void 0)return a[u]=d,!0}else if(p._tag===\"Literal\"){let d=o[u];if(t.startsWith(d,f)&&c(u+1,f+d.length))return a[u]=d,!0}else{let d=s-e.suffixLengths[u+1],m=o[u+1],h=m===void 0?d:t.lastIndexOf(m,d);for(;h>=f;){let y=t.slice(f,h);if(p.matchPart(y,r)!==void 0&&c(u+1,h))return a[u]=y,!0;if(h===0)break;h=m===void 0?h-1:t.lastIndexOf(m,h-1)}}return i??=new Set,i.add(u*(s+1)+f),!1}return c(0,0)?a:void 0}var DC=du(e=>{switch(e._tag){default:return e;case\"Number\":return e.toCodecStringTree();case\"Union\":return e.recur(DC)}}),By=du(e=>{switch(e._tag){default:return e;case\"Symbol\":case\"UniqueSymbol\":return e.toCodecStringTree();case\"Union\":return e.recur(By)}}),LC=du(e=>{switch(e._tag){default:return e;case\"Number\":case\"Literal\":case\"BigInt\":return e.toCodecStringTree();case\"Union\":return e.recur(LC)}}),xL=\"[\\\\s\\\\S]*?\",gC=new globalThis.RegExp(`^${Sm}$`),Q7=new globalThis.RegExp(`^(?:${Sm}|Infinity|-Infinity|NaN)$`);function $C(e){return wm(gC,{expected:\"a string representing a finite number\",representation:{id:\"effect/schema/isStringFinite\",payload:null},toJsonSchema:()=>({pattern:gC.source}),...e})}var gL=Us(xn,[$C()]),X7=new Tt(gL,sl),eY=new Tt(new Xr([gL,cL]),sl),tY=\"-?\\\\d+\",yC=new globalThis.RegExp(`^${tY}$`);function KC(e){return wm(yC,{expected:\"a string representing a bigint\",representation:{id:\"effect/schema/isStringBigInt\",payload:null},toJsonSchema:()=>({pattern:yC.source}),...e})}var BC=Us(xn,[KC({expected:\"a string representing a bigint\"})]),rY=new Tt(BC,Oy),nY=\"Symbol\\\\(([\\\\s\\\\S]*)\\\\)\",SC=new globalThis.RegExp(`^${nY}$`),oY=Us(xn,[jC()]),yL=new Tt(oY,new Ke(le(e=>globalThis.Symbol.for(SC.exec(e)[1])),Rt((e,t)=>globalThis.Symbol.keyFor(e)!==void 0?g(globalThis.String(e)):F(new iu({message:\"cannot serialize to string, Symbol is not registered\"},e,t)))));function jC(e){return wm(SC,{expected:\"a string representing a symbol\",representation:{id:\"effect/schema/isStringSymbol\",payload:null},toJsonSchema:()=>({pattern:SC.source}),...e})}function Zo(e,t,r,n,o){for(let s=0;s0;){let o=n[n.length-1],s=o.keys;if(typeof s==\"number\"){if(o.index(e,t,r)=>hl(e)?ot:F(new _t(t,e,r)),{representation:{id:\"effect/schema/Json\",payload:null},expected:\"JSON value\",toCodecJson:()=>{},toCodecStringTree:()=>zC}),EL=Go(ul,{representation:{id:\"effect/schema/MutableJson\",payload:null}}),HC=new Tt(ul,ol()),IL=new Tt(new Xr([new jn(!1,[],[ul]),new bm([],[new CC(xn,ul)])]),ol());function iY(e){return bL(e,aY)}var cY=new ll([],()=>(e,t,r)=>iY(e)?ot:F(new _t(t,e,r)),{expected:\"StringTree\",toCodecStringTree:()=>{}}),zC=new Tt(cY,ol());var Hy=(e,t,r)=>e===ot?r(t):Ct(e,r);function AL(e){let t=uY(e);return(r,n,o)=>{try{return t(r,n,o)}catch(s){return yr(s)}}}function uY(e){if(e._tag===\"Middleware\")return(r,n,o)=>{let s=r===ot?e.decode(Er(im(n)),o):e.decode(fn(r,im),o);return wL(s)};let t=e.decode;switch(t._tag){case\"Passthrough\":return(r,n)=>r===ot?Er(n):r;case\"Transform\":{let r=n=>n===Ae?dn:Er(t.transform(n));return(n,o)=>Hy(n,o,r)}case\"TransformOptional\":{let r=n=>QA(t.transform(im(n)));return(n,o)=>Hy(n,o,r)}case\"TransformEffect\":return(r,n,o)=>Hy(r,n,s=>s===Ae?dn:t.transform(s,o));case\"TransformOptionalEffect\":return(r,n,o)=>Hy(r,n,s=>wL(t.transform(im(s),o)))}}var wL=e=>Ct(e,QA),CL=(e,t,r,n)=>nt(n,o=>da(()=>fa(o,s=>new T2(e,s,t,r))));function fY(e,t){let r=AL(e.link.transformation),n;return(o,s)=>{if(o===Ae)return dn;if(e.isConstructed(o))return ot;let a=(n??=t(e.link.to))(o,s);return r(a,o,s)}}function lY(e,t){let r=e.context.constructorDefault;return(n,o)=>{if(n!==Ae&&n!==void 0)return t(n,o);let s=r;if(Ve(s)&&s._tag===\"Success\"){let a=t(s[xe],o);return a===ot?s:a}return Ct(CL(e,n,o,s),a=>{let i=t(a,o);return i===ot?Er(a):i})}}function WC(e,t){let r=t(e);return e.context?.constructorDefault===void 0?r:lY(e,r)}function vm(e,t,r,n,o){if(e._tag===\"Declaration\")for(let h of e.typeParameters)t(h);let s=r?jy(e):void 0,a=s?fY(s,t):n??e.getParser(t,r),i=e.checks,c=e.encoding,u=c?.map(h=>AL(h.transformation)),f=e.encodingChecks;if(!c&&!i&&!f)return a;let p,d=(h,y)=>{let S=a(h,y);try{if(f&&!y.disableChecks)if(Ve(S)){if(S._tag===\"Success\"){let b=S===ot?h:S[xe];if(h!==Ae&&b!==Ae){let x=Zo(f,h,void 0,e,y);x&&(S=F(new Ht(e,x,h,y)))}}}else S=C(S,b=>{if(h!==Ae&&b!==Ae){let x=Zo(f,h,void 0,e,y);if(x)return F(new Ht(e,x,h,y))}return g(b)});if(i&&!y.disableChecks)if(Ve(S)){if(S._tag===\"Success\"){let b=S===ot?h:S[xe];if(b===Ae)return S;let x=Zo(i,b,void 0,e,y);x&&(S=F(new Ht(e,x,b,y)))}}else S=C(S,b=>{if(b!==Ae){let x=Zo(i,b,void 0,e,y);if(x)return F(new Ht(e,x,b,y))}return g(b)});return S}catch(b){return yr(b)}},m=o===void 0?d:o(d);return c?(h,y)=>{let S=p??=c.map(w=>t(w.to)),b=h,x=S[S.length-1](h,y);for(let w=c.length-1;w>=0;w--)if(x=u[w](x,b,y),w!==0){let I=S[w-1];x._tag===\"Success\"?(b=x[xe],x=I(b,y)):x=Ct(x,T=>{let P=I(T,y);return P===ot?Er(T):P})}if(x._tag===\"Success\"){let w=x[xe],I=m(w,y);return I===ot?x:I}return x=CL(e,h,y,x),Ct(x,w=>{let I=m(w,y);return I===ot?Er(w):I})}:m}var qy=Symbol(),TL=new WeakMap,vL,xl=!1;var dY=e=>xl?Wy(en,e,\"parser\"):en(e).parser,kL=e=>xl?Wy(en,e,\"makeEffect\"):en(e).makeEffect,mY=e=>WC(e,kL),zy=class{ast;constructor(t){this.ast=t}get decodeEffect(){return this.cachedDecodeEffect??=vm(this.ast,dY)}get parser(){return this.decodeEffect}get makeEffect(){return this.cachedMakeEffect??=vm(this.ast,kL,mY)}},qC=class extends zy{compiled;resolve;constructor(t,r,n){super(t),this.compiled=r,this.resolve=n}save(t,r){return Object.defineProperty(this,t,{value:r}),r}operation(t){let r=this.compiled;return typeof r==\"function\"?r(this.ast,this.resolve,t):r?.[t]}get is(){return this.save(\"is\",this.operation(\"is\"))}get decode(){return this.save(\"decode\",this.operation(\"decode\"))}get make(){return this.save(\"make\",this.operation(\"make\"))}get compiledMakeEffect(){return this.save(\"compiledMakeEffect\",this.operation(\"makeEffect\"))}get decodeEffect(){return this.save(\"decodeEffect\",this.operation(\"decodeEffect\")??vm(this.ast,t=>Wy(this.resolve,t,\"parser\")))}get parser(){let t=this.decode;return t===void 0?this.decodeEffect:this.save(\"parser\",hY(t,()=>this.decodeEffect))}get makeEffect(){let t=this.compiledMakeEffect;if(t!==void 0)return this.save(\"makeEffect\",t);let r=n=>Wy(this.resolve,n,\"makeEffect\");return this.save(\"makeEffect\",vm(this.ast,r,n=>WC(n,r)))}};function hY(e,t){let r;return(n,o)=>{if(n!==Ae)try{let s=e(n,o);if(s!==qy)return s===n?ot:Er(s)}catch(s){return yr(s)}return(r??=t())(n,o)}}function Wy(e,t,r){let n=e(t);if(n.compiled===void 0||Object.hasOwn(n,r))return n[r];let o;return(s,a)=>(o??=n[r])(s,a)}function en(e){let t=TL.get(e);if(t!==void 0)return t;let r=vL===void 0?new zy(e):new qC(e,vL(e,en),en);return TL.set(e,r),r}function VC(e){let t=e.ast,r;return(n,o)=>(r??=tT(AY,Mt(t)))(n,o?.disableChecks?o?.parseOptions?{...o.parseOptions,disableChecks:!0}:{disableChecks:!0}:o?.parseOptions)}function Gy(e){let t=VC(e);return(r,n)=>{let o=Ts(t(r,n));return ut(o)?_(o.value):(xo(o.cause,\"Option adapter can only return none for schema issues\"),v())}}function OL(e){return IY(Mt(e.ast))}function km(e){return Om(e.ast)}function gY(e){if(!xl){let o=gl(Yy(e));return s=>{let a=o(s,Ns);return ut(a)?!0:(xo(a.cause,\"Type guard adapter can only return false for schema issues\"),!1)}}let t=en(e),r=t.is;if(r!==void 0)return o=>{try{return r(o,Ns)}catch(s){return xo(Rc(s),\"Type guard adapter can only return false for schema issues\"),!1}};let n=t.parser;return o=>{let s=Ts(eT(n(o,Ns),o));return ut(s)?!0:(xo(s.cause,\"Type guard adapter can only return false for schema issues\"),!1)}}function Om(e){let t=Mt(e),r=n=>(r=gY(t),r(n));return n=>r(n)}function _L(e){let t=Yy(e);return(r,n)=>{let o=Ts(t(r,n));if(!ut(o))return xo(o.cause,\"Issue adapter can only return schema issues\")}}function RL(e,t){let r=Mt(e.ast),n=en(r).parser(t,Ns),o=Ts(eT(n,t));if(oo(o)){let s=xo(o.cause,\"Assertion adapter can only throw schema issues\");throw new Error(\"Schema validation failed\",{cause:s})}}function St(e,t){let r=Yy(e.ast);return t===void 0?r:(n,o)=>r(n,XC(t,o))}var ZC=St;function PL(e,t){return gl(St(e,t))}function YC(e,t){return $L(St(e,t))}var ML=YC;function FL(e,t){return KL(St(e,t))}function yY(e,t){return xl?BL(e.ast,t):rT(St(e,t))}var Vy=yY;function hu(e,t){let r=Yy(Bn(e.ast));return t===void 0?r:(n,o)=>r(n,XC(t,o))}var NL=hu;function UL(e,t){return gl(hu(e,t))}function QC(e,t){return $L(hu(e,t))}var DL=QC;function LL(e,t){return KL(hu(e,t))}function SY(e,t){return xl?BL(Bn(e.ast),t):rT(hu(e,t))}var Zy=SY,XC=(e,t)=>t?{...e,...t}:e,Jy=e=>e===Ae?F(new fe):g(e);function Yy(e){return tT(wY,e)}function eT(e,t){return e===ot?g(t):Ve(e)?e[xe]===Ae?Jy(Ae):e:Ct(e,Jy)}function tT(e,t){let r;return(n,o)=>{let s=(r??=e(t))(n,o??Ns);return s===ot?g(n):Ve(s)?s[xe]===Ae?Jy(Ae):s:Ct(s,Jy)}}function gl(e){return(t,r)=>Ts(e(t,r))}function $L(e){let t=gl(e);return(r,n)=>{let o=t(r,n);return ut(o)?_(o.value):(xo(o.cause,\"Option adapter can only return none for schema issues\"),v())}}function KL(e){let t=gl(e);return(r,n)=>{let o=t(r,n);return ut(o)?j(o.value):q(xo(o.cause,\"Result adapter can only return schema issues\"))}}function BL(e,t){let r;return(n,o)=>(r??=bY(en(e),t))(n,o)}function bY(e,t){let r=e.decode,n,o=r===void 0?(s,a=Ns)=>(n??=JC(e))(s,a):(s,a=Ns)=>{if(s===Ae)return(n??=JC(e))(s,a);let i;try{i=r(s,a)}catch(c){throw xo(Rc(c),\"Sync adapter can only throw schema issues\"),c}return i!==qy?i:(n??=JC(e))(s,a)};return t===void 0?o:(s,a)=>o(s,XC(t,a))}function JC(e){return rT(tT(()=>e.decodeEffect,e.ast))}function rT(e){let t=gl(e);return(r,n)=>{let o=t(r,n);if(ut(o))return o.value;let s=xo(o.cause,\"Sync adapter can only throw schema issues\");throw new Error(\"Schema validation failed\",{cause:s})}}function EY(e,t){let r=Ts(e);if(ut(r))return r.value;let n=xo(r.cause,t);throw new Error(\"Schema validation failed\",{cause:n})}var jL=\"Constructor adapter can only throw schema issues\";function HL(e){throw new Error(jL,{cause:Rc(e)})}function IY(e){let t;return(r,n)=>GC(t??=en(e),r,n)}function GC(e,t,r){let n=r?.disableChecks?r.parseOptions?{...r.parseOptions,disableChecks:!0}:{disableChecks:!0}:r?.parseOptions??Ns,o=e.make;if(o!==void 0&&t!==Ae){let s;try{s=o(t,n)}catch(a){HL(a)}if(s!==qy&&s!==Ae)return s}return EY(eT(e.makeEffect(t,n),t),jL)}function zL(e,t,r,n){let o=en(e),s=jy(e);if(s===void 0||o.make!==void 0||o.compiledMakeEffect!==void 0)return GC(o,t,r);if(s.isConstructed(t))return t;let a=GC((o.resolve??en)(s.link.to),t,r);try{return n(a)}catch(i){HL(i)}}var wY=e=>en(e).parser,AY=e=>en(e).makeEffect;var Qy=\"~effect/Schema/Schema\",WL=Symbol(),CY={[Qy]:Qy,get make(){let e=OL(this);return Object.defineProperty(this,\"make\",{value:e,enumerable:!0}),e},get makeEffect(){let e=VC(this);return Object.defineProperty(this,\"makeEffect\",{value:e,enumerable:!0}),e},get makeOption(){let e=Gy(this);return Object.defineProperty(this,\"makeOption\",{value:e,enumerable:!0}),e},pipe(){return te(this,arguments)},annotate(e){return this.rebuild(Go(this.ast,e))},annotateKey(e){return this.rebuild(Tm(this.ast,e))},check(...e){return this.rebuild(Us(this.ast,e))},rebuild(e){return Wn(e,this[WL])}};function Wn(e,t){function r(){}let n=Object.setPrototypeOf(r,CY);return t&&(Object.hasOwn(t,\"name\")||Object.hasOwn(t,\"length\")||Object.hasOwn(t,\"__proto__\"))?Object.defineProperties(n,Object.getOwnPropertyDescriptors({...t})):Object.assign(n,t),n[WL]=t,n.ast=e,n}function JL(e){switch(e){case\"$defs\":case\"properties\":case\"patternProperties\":case\"dependentSchemas\":return\"map\";case\"allOf\":case\"anyOf\":case\"oneOf\":case\"prefixItems\":return\"array\";case\"not\":case\"additionalProperties\":case\"propertyNames\":case\"unevaluatedProperties\":case\"items\":case\"contains\":case\"unevaluatedItems\":case\"if\":case\"then\":case\"else\":case\"contentSchema\":return\"schema\"}}function nT(e){return e.replace(/~/g,\"~0\").replace(/\\//g,\"~1\")}function _m(e){return e.replace(/~1/g,\"/\").replace(/~0/g,\"~\")}function oT(e){return encodeURI(nT(e)).replace(/#/g,\"%23\")}function sT(e){if(e.length===0||e===\"#\")return\"\";if(!e.startsWith(\"#\"))return;let t=e.slice(1);try{if(encodeURI(t).replace(/%25/g,\"%\").replace(/#/g,\"%23\")!==t)return;let r=decodeURIComponent(t);return r.startsWith(\"/\")&&!/~(?:[^01]|$)/.test(r)?r:void 0}catch{return}}function GL(e){let t=sT(e);return t===void 0?void 0:t.length===0?[]:t.slice(1).split(\"/\").map(_m)}function VL(e){return e.reduce((t,r)=>`${t}/${oT(r)}`,\"#\")}var iT=\"http://json-schema.org/draft-07/schema#\",Xy=\"https://json-schema.org/draft/2020-12/schema\";function ZL(e,t){return e===t||e===(t.endsWith(\"#\")?t.slice(0,-1):`${t}#`)}function XL(e){return kY(e)}function kY(e,t){return{dialect:\"draft-07\",...MY(e,HY,void 0,t)}}function OY(e,t){return r(e,!1,!0);function r(n,o,s=!1){if(!fr(n))return n;let a=o||!s&&r$(n.$id),i={};for(let c of Object.keys(n)){let u=n[c],f=u;switch(JL(c)){case\"map\":f=cT(u,p=>r(p,a))??u;break;case\"array\":f=Array.isArray(u)?u.map(p=>r(p,a)):u;break;case\"schema\":f=r(u,a)}B(i,c,f)}return t(i,a),i}}function e$(e,t){return OY(e,r=>{_Y(r,t)})}function _Y(e,t){typeof e.$ref==\"string\"&&B(e,\"$ref\",t(e.$ref,\"$ref\")),typeof e.$dynamicRef==\"string\"&&B(e,\"$dynamicRef\",t(e.$dynamicRef,\"$dynamicRef\"))}function cT(e,t){if(!fr(e))return;let r={};for(let n of Object.keys(e))B(r,n,t(e[n],n));return r}function RY(e,t,r){let n=new Map,o=[],s=aT;function a(d,m=[],h=[]){if(m.length===0&&t?.trackIds){let y=fr(d)?f(d):void 0;s=YL(y,aT)??aT}return u(d,m,h,{sourceRoot:[],targetRoot:[],uri:s})}function i(){for(let[d,m,h]of o){let y=m,S=t$(m,h);if(S!==void 0){let b=GL(S.hash);if(S.hash=\"\",b!==void 0){let x=n.get(QL(S.href,b));x!==void 0&&(y=PY(m,x))}}B(d,\"$ref\",y)}}let c=r(a);return i(),c;function u(d,m,h,y){if(typeof d==\"boolean\")return p(m,h,y),t?.booleanAdapter?.(d)??d;if(!fr(d))return d;let S=y,b=f(d);if(m.length>0&&t?.trackIds&&r$(b)){let I=YL(b,y.uri);I!==void 0&&(S={parent:y,sourceRoot:m,targetRoot:h,uri:I})}p(m,h,S);let x=S.uri,w={isDocumentRoot:m.length===0,schema(I,T,P=T){return u(I,[...m,T],[...h,P],S)},schemaAt(I,T,P){return u(I,[...m,...T],[...h,...P],S)},schemaArray(I,T,P=T){return Array.isArray(I)?I.map((G,he)=>u(G,[...m,T,String(he)],[...h,P,String(he)],S)):I},schemaMap(I,T,P=T){return fr(I)?cT(I,(G,he)=>u(G,[...m,T,he],[...h,P,he],S)):I},reference(I,T){typeof T==\"string\"?o.push([I,T,x]):B(I,\"$ref\",T)}};return e(d,w)}function f(d){return t?.ignoreRefSiblings===!0&&typeof d.$ref==\"string\"?void 0:d.$id}function p(d,m,h){h.parent!==void 0&&p(d,m,h.parent),n.set(QL(h.uri,d.slice(h.sourceRoot.length)),m.slice(h.targetRoot.length))}}var aT=\"https://effect.invalid/.json-schema/\";function t$(e,t){return URL.canParse(e,t)?new URL(e,t):void 0}function YL(e,t){if(typeof e!=\"string\")return;let r=t$(e,t);if(r!==void 0)return r.hash=\"\",r.href}function PY(e,t){let r=e.indexOf(\"#\");return r===-1&&t.length===0?e:`${r===-1?e:e.slice(0,r)}${VL(t)}`}function QL(e,t){return`${e}\\0${JSON.stringify(t)}`}function r$(e){return typeof e==\"string\"&&e.length>0&&e[0]!==\"#\"}function MY(e,t,r,n){return RY(t,{...r,trackIds:!0},o=>({schema:o(e.schema),definitions:cT(e.definitions,(s,a)=>o(s,[...n??[\"$defs\"],a],[...n??[\"definitions\"],a]))}))}var FY=new Set([\"properties\",\"patternProperties\"]),NY=new Set([\"allOf\",\"anyOf\",\"oneOf\"]),UY=new Set([\"not\",\"additionalProperties\",\"propertyNames\",\"contains\",\"if\",\"then\",\"else\",\"contentSchema\"]);function DY(e,t,r,n,o,s=FY){let a;if(s.has(t))a=n.schemaMap(r,t);else if(NY.has(t))a=n.schemaArray(r,t);else if(o.has(t))a=n.schema(r,t);else return!1;return B(e,t,a),!0}var n$=[\"$anchor\",\"$defs\",\"$dynamicAnchor\",\"$dynamicRef\",\"$vocabulary\",\"contentSchema\",\"dependentRequired\",\"dependentSchemas\",\"maxContains\",\"minContains\",\"prefixItems\",\"unevaluatedItems\",\"unevaluatedProperties\"],Sge=[...n$,\"deprecated\"],bge=[...n$,\"$comment\",\"$id\",\"$schema\",\"const\",\"contains\",\"contentEncoding\",\"contentMediaType\",\"else\",\"examples\",\"if\",\"patternProperties\",\"propertyNames\",\"then\"],LY=/^[A-Za-z_][-A-Za-z0-9._]*$/,$Y=/^[A-Za-z][-A-Za-z0-9._:]*$/;function xu(e,t,r){throw new Error(`Cannot convert JSON Schema keyword \"${e}\" to ${t}: ${r}`)}function KY(e,t,r,n){for(let o of t)Object.hasOwn(e,o)&&xu(o,r,`it is not active in ${n} but would become active in the target`)}var BY=[\"additionalItems\",\"definitions\",\"dependencies\"];function jY(e,t,r,n,o){r.isDocumentRoot?B(e,\"$schema\",ZL(t,Xy)?n:t):ZL(t,Xy)||xu(\"$schema\",o,\"an embedded resource cannot declare a different dialect\")}function HY(e,t){KY(e,BY,\"Draft-07\",\"Draft 2020-12\");let r={},n,o,s;for(let a of Object.keys(e)){let i=e[a];if(!DY(r,a,i,t,UY))switch(a){case\"$ref\":n=i;break;case\"$schema\":jY(r,i,t,iT,\"Draft-07\");break;case\"$id\":case\"$anchor\":break;case\"$defs\":B(r,\"definitions\",t.schemaMap(i,a,\"definitions\"));break;case\"prefixItems\":o=i;break;case\"items\":s=i;break;case\"dependentRequired\":case\"dependentSchemas\":case\"minContains\":case\"maxContains\":break;case\"$dynamicRef\":case\"$dynamicAnchor\":case\"$vocabulary\":case\"unevaluatedProperties\":case\"unevaluatedItems\":xu(a,\"Draft-07\",\"the target dialect has no equivalent\");case\"required\":case\"enum\":if(Array.isArray(i)&&i.length===0)break;B(r,a,i);break;default:B(r,a,i)}}if(zY(r,o,s,t),Object.hasOwn(e,\"contains\")){let a=e.minContains,i=e.maxContains;(a!==void 0&&a!==1||i!==void 0)&&xu(\"minContains/maxContains\",\"Draft-07\",\"contains cardinality cannot be represented\"),Object.hasOwn(e,\"minContains\")&&B(r,\"minContains\",a)}else Object.hasOwn(e,\"minContains\")&&B(r,\"minContains\",e.minContains),Object.hasOwn(e,\"maxContains\")&&B(r,\"maxContains\",e.maxContains);return qY(e,r,t,\"draft-07\"),JY(e,r,\"$id\",\"Draft-07\"),Array.isArray(e.enum)&&e.enum.length===0&&o$(r,{not:{}}),WY(r,n,t),r}function zY(e,t,r,n){if(t===void 0){r!==void 0&&B(e,\"items\",n.schema(r,\"items\"));return}B(e,\"items\",n.schemaArray(t,\"prefixItems\",\"items\")),r!==void 0&&B(e,\"additionalItems\",n.schema(r,\"items\",\"additionalItems\"))}function WY(e,t,r){if(t!==void 0)if(typeof t==\"string\"&&Object.keys(e).length>0){let n={};r.reference(n,t),o$(e,n)}else r.reference(e,t)}function qY(e,t,r,n){let o=fr(e.dependentRequired)?e.dependentRequired:void 0,s=fr(e.dependentSchemas)?e.dependentSchemas:void 0;if(o===void 0&&s===void 0)return;let a={},i=new Set([...Object.keys(o??{}),...Object.keys(s??{})]);for(let c of i){let u=o?.[c],f=s?.[c],p=n===\"draft-04\"&&Array.isArray(u)&&u.length===0;f===void 0?p||B(a,c,u):u===void 0||p?B(a,c,r.schemaAt(f,[\"dependentSchemas\",c],[\"dependencies\",c])):B(a,c,{allOf:[r.schemaAt(f,[\"dependentSchemas\",c],[\"dependencies\",c,\"allOf\",\"0\"]),{required:u}]})}Object.keys(a).length>0&&B(t,\"dependencies\",a)}function o$(e,t){Array.isArray(e.allOf)?e.allOf.push(t):B(e,\"allOf\",[t])}function JY(e,t,r,n){let o=e.$id,s=e.$anchor;if(s===void 0){o!==void 0&&B(t,r,o);return}(typeof s!=\"string\"||!LY.test(s))&&xu(\"$anchor\",n,\"the anchor is not valid\"),$Y.test(s)||xu(\"$anchor\",n,\"the anchor cannot be represented as a plain-name fragment identifier\"),o===void 0?B(t,r,`#${s}`):xu(\"$anchor\",n,\"it cannot be combined with the schema $id\")}function tS(e){return Wn(yl(e.ast),{schema:e})}var yl=i$(VY);function i$(e,t){let r=on(o=>{let s=Hn(o,void 0),a=e(s,n);return a===s?null:a}),n=du(o=>{let s=r(Di(o));if(s===null)return o;let a=Hn(s,o.context);return o.context===void 0?a:FC(a,c$(o.context))},t);return n}function c$(e){return e.constructorDefault===void 0?e:new Fs(e.isOptional,e.isMutable,void 0,e.annotations)}function u$(e){if(e.propertySignatures.some(t=>typeof t.name!=\"string\"))throw new globalThis.Error(\"Objects property names must be strings\",{cause:e})}function f$(e){return t=>{let r=[...t].sort((o,s)=>e(gn(o))-e(gn(s)));return r.some((o,s)=>o!==t[s])?r:t}}var GY=f$(e=>{switch(e._tag){case\"BigInt\":case\"Symbol\":case\"UniqueSymbol\":return 0;default:return 1}});function VY(e,t){switch(e._tag){case\"Declaration\":{let r=e.annotations?.toCodecJson??e.annotations?.toCodec;if(!Jr(r))return ft(e,[HC]);let n=e.typeParameters.map(s=>Wn(gn(s))),o=r(n);return o===void 0?e:ft(e,[dl(o,t)])}case\"Unknown\":return ft(e,[HC]);case\"ObjectKeyword\":return ft(e,[IL]);case\"Undefined\":case\"Void\":case\"Literal\":case\"Number\":return e.toCodecJson();case\"UniqueSymbol\":case\"Symbol\":case\"BigInt\":return e.toCodecStringTree();case\"Objects\":return u$(e),e.recur(t,By);case\"Union\":{let r=GY(e.types);return r!==e.types?new Xr(r,e.options,e.annotations,e.checks,e.encoding,e.context,e.encodingChecks).recur(t):e.recur(t)}case\"Arrays\":case\"Suspend\":return e.recur(t)}return e}function rS(e){return Wn(l$(Mt(e.ast)))}var l$=on(e=>{let t=ZY(e,l$);return t!==e&&e.context!==void 0?FC(t,c$(e.context)):t});function ZY(e,t){switch(e._tag){case\"Declaration\":{let r=e.annotations?.toCodecIso??e.annotations?.toCodec;if(Jr(r)){let n=r(e.typeParameters.map(o=>Wn(o)));return ft(e,[dl(n,t)])}return e}case\"Arrays\":case\"Objects\":case\"Union\":case\"Suspend\":return e.recur(t)}return e}function nS(e){return Wn(tQ(e.ast),{schema:e})}function p$(e){return Wn(h$(e.ast))}var YY=f$(e=>{switch(e._tag){case\"Null\":case\"Boolean\":case\"Number\":case\"BigInt\":case\"Symbol\":case\"UniqueSymbol\":return 0;default:return 1}});function QY(e,t,r){switch(e._tag){case\"Declaration\":{let n=e.typeParameters.map(u=>Wn(t(gn(u)))),o=e.annotations?.toCodecStringTree;if(Jr(o)){let u=o(n);return u===void 0?e:ft(e,[dl(u,t)])}let s=e.annotations?.toCodecJson,a=Jr(s)?s(n):void 0,i=a===void 0?e.annotations?.toCodec:void 0,c=a??(Jr(i)?i(n):void 0);return c===void 0?r(e):ft(e,[dl(c,t)])}case\"Null\":return ft(e,[XY]);case\"Boolean\":return ft(e,[eQ]);case\"Unknown\":case\"ObjectKeyword\":return ft(e,[zC]);case\"Enum\":case\"Number\":case\"Literal\":case\"UniqueSymbol\":case\"Symbol\":case\"BigInt\":return e.toCodecStringTree();case\"Objects\":return u$(e),e.recur(t,By);case\"Union\":{let n=YY(e.types);return n!==e.types?new Xr(n,e.options,e.annotations,e.checks,e.encoding,e.context,e.encodingChecks).recur(t):e.recur(t)}case\"Arrays\":case\"Suspend\":return e.recur(t)}return e}var XY=new Tt(new Kn(\"null\"),new Ke(le(()=>null),le(()=>\"null\"))),eQ=new Tt(new Xr([new Kn(\"true\"),new Kn(\"false\")]),new Ke(le(e=>e===\"true\"),uu())),d$=new Ke(le(e=>typeof e==\"string\"?[e]:e),hn()),m$=e=>e.transformation===d$,tQ=i$((e,t)=>QY(e,t,r=>{throw new globalThis.Error(\"Missing structural codec for StringTree\",{cause:r})}),{stopAt:m$}),a$=e=>nr(e)?mu(Jo):Jo,h$=du(e=>{let t=iQ(e);if(My(t)){let r=Oa(new Xr([new jn(t.isMutable,t.elements.map(a$),t.rest.map(a$)),xn],{mode:\"anyOf\"}),t,d$);return nr(e)?mu(r):r}return t},{stopAt:m$});function x$(e){return Wn(rQ(e.ast),{schema:e})}var rQ=qs(e=>oS(eS(yl(e)))),eS=du(e=>{switch(e._tag){case\"Objects\":return e.recur(t=>nQ(eS(t)),D);case\"Arrays\":return e.recur(t=>oS(eS(t)));case\"Declaration\":case\"Union\":case\"Suspend\":return e.recur(eS)}return e}),nQ=ml(e=>nr(e)?g$(e):oS(e)),g$=ml(e=>gm(e)?e.recur(g$):aQ(e)||y$(e)?e:uT(e,fT(pl,S$))),oS=ml(e=>gm(e)?e.recur(oS):My(e)&&e.elements.length===0&&e.rest.length===1?uT(e,fT(Cm(oQ,e.checks),b$)):bC(e)&&e.propertySignatures.length===0&&e.indexSignatures.length>0?uT(e,fT(Cm(sQ,e.checks),E$)):e);function y$(e){let t=pu(e);switch(t._tag){case\"Union\":return t.checks===void 0&&t.types.some(y$);case\"Null\":case\"Unknown\":case\"Any\":case\"Declaration\":return km(Wn(Hn(t,void 0)))(null)}return!1}function uT(e,t){return Hn(new Xr([Hn(e,void 0),t]),e.context)}var lT=e=>new Ke(e,cu(()=>\"Go nil values are never encoded\")),S$=lT(ka(()=>v())),b$=lT(le(()=>[])),E$=lT(le(()=>({}))),oQ=new jn(!1,[],[]),sQ=$y(xn,pl);function fT(e,t){return Oa(ym,e,t)}function aQ(e){if(!Fy(e))return!1;let t=e.types[e.types.length-1].encoding?.[0].transformation;return t===S$||t===b$||t===E$}function iQ(e){return e._tag===\"Declaration\"||e._tag===\"Arrays\"||e._tag===\"Objects\"||e._tag===\"Union\"||e._tag===\"Suspend\"?e.recur(h$):e}var Ige=globalThis.RegExp;var _a=e=>e.replace(/[/\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\");function gu(e,t){return t.length>0&&(e+=`\n at ${Ph(t)}`),new Error(e)}function I$(e){return`#/$defs/${oT(e)}`}var cQ=new Set([...A2,au,...w2]);function sS(e,t){if(e===void 0)return;let r={};for(let i of[\"title\",\"description\",\"format\",\"contentEncoding\",\"contentMediaType\"]){let c=e[i];typeof c==\"string\"&&(r[i]=c)}for(let i of[\"readOnly\",\"writeOnly\"]){let c=e[i];typeof c==\"boolean\"&&(r[i]=c)}let n=e.expected;r.description===void 0&&t?.generateDescriptions===!0&&typeof n==\"string\"&&(r.description=n);let o=e.default;hl(o)&&(r.default=o);let s=e.examples;Array.isArray(s)&&hl(s)&&(r.examples=s);let a=e.contentSchema;if(hl(a)&&(r.contentSchema=a),t?.includeAnnotationKey!==void 0)for(let[i,c]of Object.entries(e))cQ.has(i)||!t.includeAnnotationKey(i)||hl(c)&&B(r,i,c);return Object.keys(r).length===0?void 0:r}function w$(e){let t=e.type===\"number\"||e.type===\"integer\"?e.type:void 0,r=e;if(t!==void 0&&(r={...e},delete r.type),Array.isArray(r.allOf)){let n=[],o=!1;for(let s of r.allOf){let a=w$(s);a.type!==void 0&&(o=!0,(t===void 0||a.type===\"integer\")&&(t=a.type)),Object.keys(a.schema).length>0&&n.push(a.schema)}if(o){let{allOf:s,...a}=r;r=n.length===0?a:{...a,allOf:n}}}return{type:t,schema:r}}function uQ(e){if(!Array.isArray(e.anyOf)||e.anyOf.length!==2||e.anyOf[0]?.type!==\"number\")return!1;let t=e.anyOf[1];return t?.type===\"string\"&&Array.isArray(t.enum)&&t.enum.length===3&&t.enum.includes(\"NaN\")&&t.enum.includes(\"Infinity\")&&t.enum.includes(\"-Infinity\")}var A$=\"|type|format|pattern|multipleOf|minimum|maximum|exclusiveMinimum|exclusiveMaximum|minLength|maxLength|minItems|maxItems|uniqueItems|minProperties|maxProperties|propertyNames|\";function aS(e,t){return Object.keys(e).every(r=>t.includes(`|${r}|`))}function fQ(e,t){return typeof e.$ref!=\"string\"&&t.every(r=>!Object.hasOwn(e,r))}var lQ=\"|minimum|exclusiveMinimum|minLength|minItems|minProperties|\",pQ=\"|maximum|exclusiveMaximum|maxLength|maxItems|maxProperties|\";function dQ(e,t,r){if(typeof e.$ref==\"string\")return;let n={...e,...t};for(let o of r){if(!Object.hasOwn(e,o))continue;let s=e[o],a=t[o];if(typeof s!=\"number\"||typeof a!=\"number\")return;if(lQ.includes(`|${o}|`))n[o]=Math.max(s,a);else if(pQ.includes(`|${o}|`))n[o]=Math.min(s,a);else return}return typeof n.minimum==\"number\"&&typeof n.exclusiveMinimum==\"number\"&&delete n[n.exclusiveMinimum>=n.minimum?\"minimum\":\"exclusiveMinimum\"],typeof n.maximum==\"number\"&&typeof n.exclusiveMaximum==\"number\"&&delete n[n.exclusiveMaximum<=n.maximum?\"maximum\":\"exclusiveMaximum\"],n}var mT=\"|title|description|default|examples|readOnly|writeOnly|\",mQ=A$+mT;function iS(e,t,r){if(Object.keys(e).length===0)return t;let n=Object.keys(t);if(n.length===0)return e;let o=e.type===\"number\"||e.type===\"integer\"?e.type:void 0,s=uQ(e);if(o!==void 0||s){let i=w$(t);if(i.type!==void 0){let c=o===\"integer\"||i.type===\"integer\"?\"integer\":\"number\",u={...e,type:c};s&&delete u.anyOf;let f=Object.keys(i.schema);return f.length===0?u:aS(i.schema,mT)&&fQ(u,f)?{...u,...i.schema}:iS(u,i.schema,r)}}if(r){let i=dQ(e,t,n);if(i!==void 0)return i}let a=Array.isArray(t.allOf)&&n.length===1?t.allOf:[t];return Array.isArray(e.allOf)?{...e,allOf:[...e.allOf,...a]}:typeof e.$ref==\"string\"?{allOf:[e,...a]}:{...e,allOf:a}}function dT(e,t=new Set){return typeof e==\"boolean\"?e:t.has(e)?!0:(t.add(e),e.every(r=>dT(r,t)))}function hQ(e){return Array.isArray(e)}function xQ(e,t,r,n){let o=`^(?:${Sm}|Infinity|-Infinity|NaN)$`,s=new Map,a=new Map,i=new WeakMap,c=new Map,u=new Map,f=Object.keys(r);for(let E of f)S(E,[\"references\",E]);let p=kn(e,(E,R)=>I(E,t[R],[]));for(let{branches:E,schemas:R}of c.values())if(!dT(E))for(let N of R)Array.isArray(N.oneOf)&&(N.anyOf=N.oneOf,delete N.oneOf);for(let E of f){let R=r[E],N=x(R);if(N===void 0)continue;let O=s.get(E).schema,M=u.get(N),U=M?.find(pe=>Z(s.get(pe).schema,O));U===void 0?M===void 0?u.set(N,[E]):M.push(E):a.set(E,U)}let d=kn(p,b),m={};for(let E of f)a.has(E)||B(m,E,b(s.get(E).schema));return{dialect:\"draft-2020-12\",schemas:d,definitions:m};function h(E){return Array.isArray(E.oneOf)&&c.get(E.oneOf)?.schemas.push(E),E}function y(E,R,N){let O=I(E.type,[...R,\"type\"],N),M=sS(E.annotations,n);return M===void 0?O:h(iS(O,M))}function S(E,R){if(!Object.hasOwn(r,E))throw gu(`Invalid reference ${E}`,[...R,\"$ref\"]);let N=s.get(E);if(N!==void 0)return N;let O={schema:{},dependencies:[]};return s.set(E,O),O.schema=I(r[E],[\"references\",E],O.dependencies),O}function b(E){return e$(E,R=>{let N=sT(R);if(N===void 0){if(/^#(?:\\/|%2f)/i.test(R))throw new Error(`Invalid JSON Pointer URI fragment ${JSON.stringify(R)}`);return R}if(!N.startsWith(\"/$defs/\"))return R;let O=N.indexOf(\"/\",7),M=a.get(_m(N.slice(7,O<0?void 0:O)));return M===void 0?R:R.replace(/^#(?:\\/|%2f).*?(?:\\/|%2f).*?(?=\\/|%2f|$)/i,I$(M))})}function x(E){if(E._tag===\"Reference\")return;let R=E.checks.length===0?E.annotations:E.checks[E.checks.length-1].annotations;return typeof R?.identifier!=\"string\"&&typeof R?.[au]==\"string\"?R[au]:void 0}function w(E,R,N,O){let M=E.annotations,U=M?.toJsonSchema;if(U!==void 0){let ee=E.representation?.schemas?.map((vr,is)=>I(vr,[...N,\"representation\",\"schemas\",is],O))??[],Qe=U({type:R,schemas:ee}),qe=hQ(Qe);qe&&O.push(!1);let et=qe?Qe[0]:Qe,De=sS(M,n),xt=De===void 0?et:{...et,...De},vt=De===void 0?A$:mQ;return[xt,E._tag===\"Filter\"&&aS(xt,vt)&&(De===void 0||aS(De,mT))?!0:void 0]}if(E._tag===\"Filter\"){O.push(!1);return}let pe=E.checks.flatMap((ee,Qe)=>{let qe=w(ee,R,[...N,\"checks\",Qe],O);return qe===void 0?[]:[qe[0]]});if(pe.length===0)return;let He=sS(M,n),ze={allOf:pe};return[He===void 0?ze:{...ze,...He}]}function I(E,R,N){if(E._tag===\"Reference\")return N.push(S(E.$ref,R).dependencies),{$ref:I$(E.$ref)};let O=i.get(E);if(O!==void 0)return N.push(O.dependencies),O.schema;let M=[];N.push(M);let U={...T(E,R,M),...sS(E.annotations,n)};if(E._tag===\"String\"&&E.content!==void 0){let pe=E.content;U.contentMediaType=pe.mediaType,delete U.contentSchema,pe.schema!==void 0&&(U.contentSchema=I(pe.schema,[...R,\"content\",\"schema\"],[]))}for(let pe=0;pe({type:typeof U,enum:[U],title:M}));return O.length===0?{not:{}}:{anyOf:O}}case\"TemplateLiteral\":{let{exact:O,pattern:M}=me(E.parts);return O||N.push(!1),{type:\"string\",pattern:M}}case\"Arrays\":{let O={type:\"array\"},M=E.elements.length,U=E.elements.map((pe,He)=>(pe.isOptional&&M--,y(pe,[...R,\"elements\",He],N)));if(U.length>0?(O.prefixItems=U,O.maxItems=E.elements.length,M>0&&(O.minItems=M)):O.items=!1,E.rest.length===1){delete O.maxItems;let pe=I(E.rest[0],[...R,\"rest\",0],N);Object.keys(pe).length>0?O.items=pe:delete O.items}else E.rest.length>1&&(delete O.maxItems,delete O.items,O.minItems=M+E.rest.length-1,N.push(!1));return O}case\"Objects\":return P(E,R,N);case\"Union\":{let O=[],M=E.types.map((U,pe)=>I(U,[...R,\"types\",pe],O));if(N.push(O),M.length===0)return{not:{}};if(E.options?.mode===\"oneOf\")return c.set(M,{branches:O,schemas:[]}),{oneOf:M};if(M.length>1){let U=yQ(M);if(U!==void 0)return U}return{anyOf:M.flatMap(U=>Array.isArray(U.anyOf)&&Object.keys(U).length===1?U.anyOf:[U])}}}}function P(E,R,N){let{indexSignatures:O,propertySignatures:M}=E;if(M.length===0&&O.length===0)return{not:{type:\"null\"}};let U={type:\"object\"},pe={},He=[];for(let[De,xt]of M.entries()){let vt=[...R,\"propertySignatures\",De];if(typeof xt.name!=\"string\")throw gu(\"Objects property names must be strings\",[...vt,\"name\"]);B(pe,xt.name,y(xt,vt,N)),xt.isOptional||He.push(xt.name)}M.length>0&&(U.properties=pe),He.length>0&&(U.required=He);let ze=O.map((De,xt)=>{let vt=[...R,\"indexSignatures\",xt],vr=I(De.type,[...vt,\"type\"],N),is=Z(vr,{not:{}})?!1:vr,Ws=he(De.parameter,[...vt,\"parameter\"],new Set);return Ws===void 0&&N.push(!1),{type:is,patterns:Ws}}),ee={};for(let{patterns:De,type:xt}of ze)for(let vt of De??[]){let vr=ee[vt];B(ee,vt,vr===void 0?xt:vr===!1||xt===!1?!1:h(iS(vr,xt)))}let Qe=Object.keys(ee).length>0;Qe&&(U.patternProperties=ee);let qe=ze.filter(({patterns:De})=>De?.length===0).map(({type:De})=>De),et=ze.some(({patterns:De})=>De===void 0);if(et&&n?.onExcessProperty===\"error\"){let De=[];M.length>0&&De.push({enum:Object.keys(pe)});for(let[vt,vr]of O.entries())De.push(G(vr.parameter,[...R,\"indexSignatures\",vt,\"parameter\"],N,new Set));U.propertyNames=De.length===1?De[0]:{anyOf:De};let xt=ze.map(({type:vt})=>vt);U.additionalProperties=xt.length===1?xt[0]:{anyOf:xt},qe.length>0&&(U.allOf=qe.map(vt=>({type:\"object\",additionalProperties:vt})))}else qe.length===0?U.additionalProperties=et||n?.onExcessProperty!==\"error\":qe.length===1&&M.length===0&&!Qe?U.additionalProperties=qe[0]:U.allOf=qe.map(De=>({type:\"object\",additionalProperties:De}));return typeof U.additionalProperties==\"object\"&&U.additionalProperties!==null&&Object.keys(U.additionalProperties).length===0&&delete U.additionalProperties,U}function G(E,R,N,O){switch(E._tag){case\"Number\":return{type:\"string\",pattern:o};case\"Reference\":return O.has(E.$ref)?{type:\"string\"}:G(r[E.$ref],[\"references\",E.$ref],N,new Set(O).add(E.$ref));case\"Union\":return{anyOf:E.types.map(M=>G(M,R,N,O))};default:return I(E,R,N)}}function he(E,R,N){switch(E._tag){case\"Reference\":{if(S(E.$ref,R),N.has(E.$ref))return;let O=new Set(N).add(E.$ref);return he(r[E.$ref],[\"references\",E.$ref],O)}case\"String\":{if(E.checks.length===0)return[];if(E.checks.length!==1||E.checks[0]._tag!==\"Filter\"||E.checks[0].annotations?.toJsonSchema===void 0)return;let O=[],M=I(E,R,O);return dT(O)&&M.type===\"string\"&&typeof M.pattern==\"string\"&&aS(M,\"|type|pattern|title|description|default|examples|readOnly|writeOnly|\")?[M.pattern]:void 0}case\"TemplateLiteral\":{if(E.checks.length>0)return;let{exact:O,pattern:M}=me(E.parts);return O?[M]:void 0}case\"Union\":{if(E.types.length===0||E.checks.length>0||E.options?.mode===\"oneOf\")return;let O=[];for(let M=0;M0&&(N=!1),U._tag){case\"Reference\":{if(!Object.hasOwn(r,U.$ref))throw gu(`Invalid reference ${U.$ref}`,[]);if(R.has(U.$ref))throw gu(`Invalid recursive TemplateLiteral part ${U.$ref}`,[]);R.add(U.$ref);let pe=M(r[U.$ref]);return R.delete(U.$ref),pe}case\"Literal\":return _a(globalThis.String(U.literal));case\"String\":return xL;case\"Number\":return Sm;case\"BigInt\":return\"-?\\\\d+\";case\"TemplateLiteral\":return U.parts.map(M).join(\"\");case\"Union\":return U.types.length===0?\"(?!)\":(U.options?.mode===\"oneOf\"&&(N=!1),`(?:${U.types.map(M).join(\"|\")})`);default:throw gu(`Invalid TemplateLiteral part ${U._tag}`,[])}}}}function gQ(e){return e===\"string\"||e===\"number\"||e===\"boolean\"||e===\"array\"||e===\"object\"||e===\"null\"||e===\"integer\"}function yQ(e){let t,r=[];for(let n of e){if(Object.keys(n).length!==2||n.type===void 0||!Array.isArray(n.enum)||n.enum.length===0)return;if(t===void 0)t=n.type;else if(n.type!==t)return;for(let s of n.enum){if(r.includes(s))return;r.push(s)}}return{type:t,enum:r}}function cS(e,t){let r=xQ([e.representation],[[\"representation\"]],e.references,t);return{dialect:r.dialect,schema:r.schemas[0],definitions:r.definitions}}var SQ=({identifier:e})=>e;function hT(e){return e===void 0?void 0:{annotations:e}}function Pm(e,t){let{references:r,representations:n}=bQ([e],t);return{representation:n[0],references:r}}function bQ(e,t){let r={},n=new Set,o=new Map;for(let x of e)f(x);let s=t?.referencePolicy??SQ;for(let x of o.values())for(let w of x){let I=s({ast:w.ast,occurrences:w.occurrences,identifier:w.identifier});if(I!==void 0){let T=I===w.identifier||!I.endsWith(\"_\")?\"_\":\"\";w.reference=i(I,T)}else w.isRecursive&&(w.reference=i(`${w.ast._tag}_`,\"\"))}return{representations:kn(e,m),references:r};function i(x,w){let I=x,T=0;for(;n.has(I);)I=`${x}${w}${++T}`;return n.add(I),I}function c(x,w,I){let T=w.fallback;return T!==void 0?ZA(x)===T?x:Go(x,{[au]:T}):I===w.identifier?x:Go(x,{identifier:I})}function u(x,w=x.encoding?.length??0){let I=x,T;for(;I.encoding!==void 0&&w>0;){let R=I.encoding[w-1];if(R.to.encoding===void 0&&R.to._tag===\"String\"){let N=uD(R.transformation.encode);N!==void 0&&(T={mediaType:N.mediaType,schema:N.preserveSchema?u(I,w-1):void 0})}I=R.to,w=I.encoding?.length??0}let P=Di(I),G=el(I),he=G===void 0?(I!==x?el(x):void 0)??ZA(I):void 0;he!==void 0&&(G=`${he}Encoded`);let me=o.get(P);me===void 0&&(me=[],o.set(P,me));let E=me.find(R=>R.identifier===G&&R.content?.mediaType===T?.mediaType&&R.content?.schema===T?.schema);return E===void 0&&(E={ast:P,identifier:G,fallback:he,content:T,occurrences:0},me.push(E)),E}function f(x){return p(u(x)),x}function p(x){let w=x.ast;if(x.occurrences++,x.visiting){x.isRecursive=!0;return}if(!(x.occurrences>1)){switch(x.visiting=!0,x.content?.schema!==void 0&&p(x.content.schema),d(w.checks),w._tag){default:\"recur\"in w&&w.recur(f);break;case\"TemplateLiteral\":w.parts.forEach(f);break;case\"Suspend\":f(w.thunk());break}x.visiting=!1}}function d(x){x?.forEach(w=>{w.annotations?.representation?.schemas?.forEach(I=>f(Mt(I))),w._tag===\"FilterGroup\"&&d(w.checks)})}function m(x){return h(u(x))}function h(x){let w=x.ast,I=x.reference;if(I!==void 0){if(!x.emitted){x.emitted=!0;let T=x.identifier===void 0?w:c(w,x,I),P=y(T,x.content);B(r,I,P)}return{_tag:\"Reference\",$ref:I}}return y(w,x.content)}function y(x,w){let I={checks:x.checks?.map(S)??[],...x._tag===\"Declaration\"?b(x.annotations):hT(x.annotations)};switch(x._tag){case\"Declaration\":return{_tag:x._tag,typeParameters:x.typeParameters.map(m),...I};default:return{_tag:x._tag,...w===void 0?void 0:{content:{mediaType:w.mediaType,...w.schema===void 0?void 0:{schema:h(w.schema)}}},...I};case\"Literal\":return{_tag:x._tag,literal:x.literal,...I};case\"UniqueSymbol\":return{_tag:x._tag,symbol:x.symbol,...I};case\"Enum\":return{_tag:x._tag,enums:x.enums,...I};case\"TemplateLiteral\":return{_tag:x._tag,parts:x.parts.map(m),...I};case\"Arrays\":return{_tag:x._tag,elements:x.elements.map(T=>{let P=pu(T),G=P.context?.annotations;return{isOptional:nr(P),type:m(T),...hT(G)}}),rest:x.rest.map(m),...I};case\"Objects\":return{_tag:x._tag,propertySignatures:x.propertySignatures.map(T=>{let P=pu(T.type),G=P.context?.annotations;return{name:T.name,type:m(T.type),isOptional:nr(P),isMutable:dL(P),...hT(G)}}),indexSignatures:x.indexSignatures.map(T=>({parameter:m(T.parameter),type:m(T.type)})),...I};case\"Union\":return{_tag:x._tag,types:x.types.map(m),...x.options===void 0?{}:{options:x.options},...I};case\"Suspend\":return{_tag:x._tag,...I,checks:[],thunk:m(x.thunk())}}}function S(x){return{...x._tag===\"Filter\"?{_tag:x._tag,aborted:x.aborted}:{_tag:x._tag,checks:kn(x.checks,S)},...b(x.annotations,!0)}}function b(x,w=!1){if(x===void 0)return;let{representation:I,...T}=x,P=w&&I?.schemas!==void 0?{...I,schemas:I.schemas.map(G=>m(Mt(G)))}:I;return{...P===void 0?void 0:{representation:P},...Object.keys(T).length===0?void 0:{annotations:T}}}}function v$(e){return ut(e)?e.value:{issues:[{message:n0(e.cause)}]}}function O$(e,t){let r=St(e),n={errors:\"all\",...t?.parseOptions},o=P2(t);return _$(e,{validate:a=>{let i=new bc(\"sync\"),c=Rd(q0(r(a,n),{onFailure:o,onSuccess:f=>({value:f})}),{scheduler:i});c.currentDispatcher?.flush();let u=c.pollUnsafe();return u?v$(u):new Promise(f=>{c.addObserver(p=>{f(v$(p))})})}})}function _$(e,t){let r={version:1,vendor:\"effect\",...Object.hasOwn(e,\"~standard\")?e[\"~standard\"]:void 0,...t},n=typeof e==\"function\"?Function.prototype.bind.call(e,void 0):Object.create(Object.getPrototypeOf(e));return Object.defineProperties(n,{...Object.getOwnPropertyDescriptors(e),ast:{value:e.ast,enumerable:!0,configurable:!0},\"~standard\":{value:r,writable:!0,enumerable:!0,configurable:!0}})}function EQ(e){let t=Pm(yl(e));return cS(t)}function k$(e,t){let r=EQ(e);if(t===\"draft-2020-12\"){let n={$schema:Xy,...r.schema};return Object.keys(r.definitions).length>0&&(n.$defs=r.definitions),n}else if(t===\"draft-07\"){let n=XL(r),o={$schema:iT,...n.schema};return Object.keys(n.definitions).length>0&&(o.definitions=n.definitions),o}throw new globalThis.Error(`Unsupported target: ${t}`)}function R$(e){return _$(e,{jsonSchema:{input(t){return k$(e.ast,t.target)},output(t){return k$(Mt(e.ast),t.target)}}})}function M$(e,t){let r=[];return xT(e,t,\"\",r),r}function xT(e,t,r,n){if(!Object.is(e,t)){if(Array.isArray(e)&&Array.isArray(t)){let o=e.length,s=t.length,a=Math.min(o,s);for(let i=0;i=s;i--)n.push({op:\"remove\",path:`${r}/${i}`});for(let i=o;ii)throw new Error(`Array index out of bounds at \"${t.path}\".`);let c=o.slice();return t.op===\"add\"?c.splice(a,0,t.value):t.op===\"remove\"?c.splice(a,1):c[a]=t.value,P$(s,c)}if(uS(o)){if(t.op!==\"add\"&&!Object.hasOwn(o,n))throw new Error(`Property \"${n}\" does not exist at \"${t.path}\".`);let a={...o};return t.op===\"remove\"?delete a[n]:B(a,n,t.value),P$(s,a)}throw new Error(`Cannot ${t.op} at \"${t.path}\" (parent not found or not a container).`)}function CQ(e,t){let r=wQ(t);if(r.length===0)return null;let n=r[r.length-1],o=[],s=e;for(let a=0;a=s.length)return null;o.push({container:s,token:c}),s=s[c];continue}if(uS(s)){if(!Object.hasOwn(s,i))return null;o.push({container:s,token:i}),s=s[i];continue}return null}return{stack:o,parent:s,lastToken:n}}function P$(e,t){let r=t;for(let n=e.length-1;n>=0;n--){let{container:o,token:s}=e[n];if(Array.isArray(o)){let a=o.slice();a[s]=r,r=a}else{let a={...o};B(a,s,r),r=a}}return r}function D$(e){let t=tS(e),r=Zy(t),n=Vy(t);return{empty:[],diff:(o,s)=>M$(r(o),r(s)),combine:(o,s)=>[...o,...s],patch:(o,s)=>{let a=r(o),i=F$(s,a);return Object.is(i,a)?o:n(i)}}}function L$(e,t){let r=el(e.ast)??YA(e.ast),n=NL(nS(e));return o=>n(o).pipe(W(s=>vQ(s,{rootName:r,...t})))}function vQ(e,t){let r=t.rootName??\"root\",n=t.arrayItemName??\"item\",o=t.pretty??!0,s=t.indent??\" \",a=t.sortKeys??!0,i=new Set,c=[];return f(r,e,0),c.join(o?`\n`:\"\");function u(p,d){c.push(o?s.repeat(p)+d:d)}function f(p,d,m,h){let{attrs:y,safe:S}=Sl.tagInfo(p,h);if(d===void 0)u(m,`<${S}${y}/>`);else if(typeof d==\"string\")u(m,`<${S}${y}>${Sl.escapeText(d)}`);else if(typeof d!=\"object\"||d===null)u(m,`<${S}${y}>${Sl.escapeText(K(d))}`);else{if(i.has(d))throw new globalThis.Error(\"Cycle detected while serializing to XML.\",{cause:d});i.add(d);try{if(globalThis.Array.isArray(d)){if(d.length===0){u(m,`<${S}${y}/>`);return}u(m,`<${S}${y}>`);for(let w of d)f(n,w,m+1);u(m,``);return}let b=d,x=Object.keys(b);if(a&&x.sort(),x.length===0){u(m,`<${S}${y}/>`);return}u(m,`<${S}${y}>`);for(let w of x)f(Sl.parseTagName(w).safe,b[w],m+1,w);u(m,``)}finally{i.delete(d)}}}}var Sl={escapeText(e){return e.replace(/&/g,\"&\").replace(//g,\">\")},escapeAttribute(e){return e.replace(/&/g,\"&\").replace(/\"/g,\""\").replace(//g,\">\")},parseTagName(e){let t=e,r=e;return/^[A-Za-z_]/.test(r)||(r=\"_\"+r),r=r.replace(/[^A-Za-z0-9._-]/g,\"_\"),/^xml/i.test(r)&&(r=\"_\"+r),{safe:r,changed:r!==t}},tagInfo(e,t){let{changed:r,safe:n}=Sl.parseTagName(e),s=r||t&&t!==e?` data-name=\"${Sl.escapeAttribute(t??e)}\"`:\"\";return{safe:n,attrs:s}}};var gT=on(e=>Li(e));function Li(e){let t=va(e)?.toEquivalence;if(t)return t(fl(e)?e.typeParameters.map(Li):[]);switch(e._tag){case\"Never\":return Wa();case\"Declaration\":return OQ(e);case\"Null\":case\"Undefined\":case\"Void\":case\"Unknown\":case\"Any\":case\"String\":case\"Number\":case\"Boolean\":case\"BigInt\":case\"Symbol\":case\"Literal\":case\"UniqueSymbol\":case\"ObjectKeyword\":case\"Enum\":case\"TemplateLiteral\":return Z;case\"Arrays\":{let r=e.elements.map(Li),n=e.rest.map(Li),[o,...s]=n,a=s.length;return Kt((i,c)=>{if(!Array.isArray(i)||!Array.isArray(c))return!1;let u=i.length;if(u!==c.length)return!1;let f=0;for(;f0){for(;fLi(o.type)),n=e.indexSignatures.map(o=>Li(o.type));return Kt((o,s)=>{if(!fr(o)||!fr(s))return!1;for(let a=0;a[Om(s),Li(e.types[a])]);return Kt((s,a)=>{let i=n(s,!1);for(let c=0;c(r??=gT(e.thunk()))(n,o))}}}function OQ(e){let t=e.annotations?.representation;if(t===void 0)return Z;switch(t.id){case\"effect/schema/Option\":{let[r]=yu(e);return(n,o)=>n._tag===o._tag&&(n._tag===\"None\"||r(n.value,o.value))}case\"effect/schema/Result\":{let[r,n]=yu(e);return(o,s)=>o._tag===s._tag&&(o._tag===\"Success\"?r(o.success,s.success):n(o.failure,s.failure))}case\"effect/schema/CauseReason\":{let[r,n]=yu(e);return K$(r,n)}case\"effect/schema/Cause\":{let[r,n]=yu(e);return $$(r,n)}case\"effect/schema/Exit\":{let[r,n,o]=yu(e),s=$$(n,o);return(a,i)=>a._tag===i._tag&&(a._tag===\"Success\"?r(a.value,i.value):s(a.cause,i.cause))}case\"effect/schema/ReadonlyMap\":{let[r,n]=yu(e);return _h(r,n)}case\"effect/schema/ReadonlySet\":return hp(yu(e)[0]);case\"effect/schema/RegExp\":return(r,n)=>r.source===n.source&&r.flags===n.flags;case\"effect/schema/URL\":return(r,n)=>r.toString()===n.toString();default:return Z}}function yu(e){return e.typeParameters.map(Li)}function K$(e,t){return(r,n)=>{if(r._tag!==n._tag)return!1;switch(r._tag){case\"Fail\":return e(r.error,n.error);case\"Die\":return t(r.defect,n.defect);case\"Interrupt\":return r.fiberId===n.fiberId}}}function $$(e,t){let r=Zu(K$(e,t));return(n,o)=>r(n.reasons,o.reasons)}function j$(e,t){return r=>{switch(r._tag){case\"Fail\":return`Fail(${e(r.error)})`;case\"Die\":return`Die(${t(r.defect)})`;case\"Interrupt\":return\"Interrupt\"}}}function B$(e,t){let r=j$(e,t);return n=>`Cause([${n.reasons.map(r).join(\", \")}])`}function H$(e,t){let r=new Map;return n(e);function n(a){let i=r.get(a);return i===void 0&&(i=o(a),r.set(a,i)),i}function o(a){let i=va(a)?.toFormatter;if(typeof i==\"function\")return i(fl(a)?a.typeParameters.map(n):[]);if(t?.onBefore){let c=t.onBefore(a,n);if(c!==void 0)return c}return s(a)}function s(a){switch(a._tag){default:return K;case\"Never\":return()=>\"never\";case\"Void\":return()=>\"void\";case\"Declaration\":{let i=a.annotations?.representation;if(i===void 0)return K;let c=a.typeParameters.map(n);switch(i.id){case\"effect/schema/Option\":{let[u]=c;return Zt({onNone:()=>\"none()\",onSome:f=>`some(${u(f)})`})}case\"effect/schema/Result\":{let[u,f]=c;return mr({onSuccess:p=>`success(${u(p)})`,onFailure:p=>`failure(${f(p)})`})}case\"effect/schema/CauseReason\":return j$(c[0],c[1]);case\"effect/schema/Cause\":return B$(c[0],c[1]);case\"effect/schema/Exit\":{let[u,f,p]=c,d=B$(f,p);return m=>{switch(m._tag){case\"Success\":return`Exit.Success(${u(m.value)})`;case\"Failure\":return`Exit.Failure(${d(m.cause)})`}}}case\"effect/schema/ReadonlyMap\":{let[u,f]=c;return p=>{let d=p.size;if(d===0)return\"ReadonlyMap(0) {}\";let m=globalThis.Array.from(p.entries()).map(([h,y])=>`${u(h)} => ${f(y)}`).sort();return`ReadonlyMap(${d}) { ${m.join(\", \")} }`}}case\"effect/schema/HashMap\":{let[u,f]=c;return p=>{let d=jU(p);if(d===0)return\"HashMap(0) {}\";let m=em(p).map(([h,y])=>`${u(h)} => ${f(y)}`).sort();return`HashMap(${d}) { ${m.join(\", \")} }`}}case\"effect/schema/ReadonlySet\":{let[u]=c;return f=>{let p=f.size;if(p===0)return\"ReadonlySet(0) {}\";let d=globalThis.Array.from(f.values()).map(m=>`${u(m)}`).sort();return`ReadonlySet(${p}) { ${d.join(\", \")} }`}}case\"effect/schema/HashSet\":{let[u]=c;return f=>{let p=JU(f);if(p===0)return\"HashSet(0) {}\";let d=globalThis.Array.from(f).map(m=>`${u(m)}`).sort();return`HashSet(${p}) { ${d.join(\", \")} }`}}case\"effect/schema/Chunk\":{let[u]=c;return f=>{let p=eN(f);if(p===0)return\"Chunk(0) {}\";let d=globalThis.Array.from(f).map(m=>`${u(m)}`);return`Chunk(${p}) { ${d.join(\", \")} }`}}default:return K}}case\"Arrays\":{let i=a.elements.map(d=>n(d)),c=a.rest.map(n),[u,...f]=c,p=f.length;return d=>{let m=[],h=0;for(;h0){for(;hn(u.type)),c=a.indexSignatures.map(u=>n(u.type));return a.propertySignatures.length===0&&a.indexSignatures.length===0?K:u=>{let f=[],p=new Set;for(let d=0;d0?\"{ \"+f.join(\", \")+\" }\":\"{}\"}}case\"Union\":{let i=Mt(a).types,c=Im(i),u=i.map((f,p)=>[Om(f),n(a.types[p])]);return f=>{let p=c(f,!1);for(let d=0;d(i??=n(a.thunk()))(c)}}}}var yT=l(2,(e,t)=>ET(e,(r,n)=>W$(t,r)?[r,n]:void 0)),ST=l(2,(e,t)=>ET(e,(r,n)=>W$(t,r)?void 0:[r,n])),z$=l(2,(e,t)=>({...e,...t}));var bT=l(2,(e,t)=>ET(e,(r,n)=>[Object.hasOwn(t,r)?t[r]:r,n]));var Kr=e=>e;function W$(e,t){return e.some(r=>r===t||typeof r==\"number\"&&String(r)===t)}function ET(e,t){let r={};for(let n of Reflect.ownKeys(e)){if(!Object.prototype.propertyIsEnumerable.call(e,n))continue;let o=t(n,e[n]);if(o){let[s,a]=o;B(r,s,a)}}return r}function G$(e,t){return Qo(bl(\"Iso\",e,t))}function q$(e,t){return Qo(bl(\"Lens\",e,t))}function bl(e,t,r){return[{_tag:\"PrimitiveNode\",kind:e,get:t,set:r}]}var PQ={kind:\"Iso\",get:D,set:D},fS=class{_tag=\"PathNode\";kind=\"Lens\";path;get;set;constructor(t){this.path=t,this.get=r=>{let n=r;for(let o=0;o{let o=lS(n),s=o,a=0;for(;aSL(t,r)}};function Su(e,t){if(e.length===0)return t;if(t.length===0)return e;let r=e.slice();for(let n=0;nr)}modify(t){return r=>_p(Yt(this.getResult(r),n=>this.replaceResult(t(n),r)),()=>r)}compose(t){return Qo(Su(this.node,t.node))}key(t){return Qo(Su(this.node,[new fS([t])]))}optionalKey(t){return Qo(Su(this.node,bl(\"Lens\",r=>r[t],(r,n)=>{let o=lS(n);return r===void 0?Array.isArray(o)&&(typeof t==\"number\"||typeof t==\"string\"&&of(t))?o.splice(Number(t),1):delete o[t]:B(o,t,r),o})))}check(...t){return Qo(Su(this.node,[new Mm(t)]))}refine(t,r){return Qo(Su(this.node,[new Mm([Ly(t,r)])]))}tag(t){let r=q(new fe({expected:`${JSON.stringify(t)} tag`}));return Qo(Su(this.node,bl(\"Prism\",n=>n._tag===t?j(n):r,D)))}at(t,...r){let n=q(new Ot([t],new Ni(void 0)));return Qo(Su(this.node,bl(\"Optional\",o=>Object.hasOwn(o,t)?j(o[t]):n,(o,s)=>{if(Object.hasOwn(s,t)){let a=lS(s);return B(a,t,o),j(a)}else return n})))}pick(t){return this.compose(q$(yT(t),(r,n)=>({...ST(n,t),...r})))}omit(t){return this.compose(q$(ST(t),(r,n)=>({...yT(n,t),...r})))}notUndefined(){return this.refine(cs,{expected:\"a value other than `undefined`\"})}forEach(t){let r=t(pS());return MQ(n=>sr(this.getResult(n),o=>{let s=[];for(let a=0;aYt(this.getResult(o),s=>{let a=[];for(let c=0;c_p(Yt(this.getResult(r),n=>this.replaceResult(n.map(t),r)),()=>r)}},wT=class extends El{get;set;constructor(t,r,n){super(t,o=>j(r(o)),o=>j(n(o))),this.get=r,this.set=n}replace(t,r){return this.set(t)}modify(t){return r=>this.set(t(this.get(r)))}},AT=class extends El{get;constructor(t,r,n){super(t,o=>j(r(o)),(o,s)=>j(n(o,s))),this.get=r,this.replace=n}modify(t){return r=>this.replace(t(this.get(r)),r)}},CT=class extends El{set;constructor(t,r,n){super(t,r,(o,s)=>j(n(o))),this.set=n}replace(t,r){return this.set(t)}modify(t){return r=>_p(sr(this.getResult(r),n=>this.set(t(n))),()=>r)}};function Qo(e){let t=e[0]??PQ;if(e.length>1){let r=e.reduce((n,o)=>UQ(n,o.kind),\"Iso\");t={kind:r,get:FQ(e,r),set:NQ(e,r)}}switch(t.kind){case\"Iso\":return new wT(e,t.get,t.set);case\"Lens\":return new AT(e,t.get,t.set);case\"Prism\":return new CT(e,t.get,t.set);case\"Optional\":return new El(e,t.get,t.set)}}function lS(e){if(Array.isArray(e))return e.slice();if(typeof e==\"object\"&&e!==null){let t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null)throw new Error(\"Cannot clone object with non-Object constructor or null prototype\");return{...e}}return e}function FQ(e,t){return r=>{for(let n=0;n{for(let n=e.length-1;n>=0;n--)r=e[n].set(r);return r}:(r,n)=>{let o=e.length,s=new Array(o);for(let a=0;a=0;a--){let i=e[a];if(J$(i.kind))r=i.set(r);else if(i.kind===\"Lens\")r=i.set(r,s[a]);else{let c=i.set(r,s[a]);if(ae(c))return c;r=c.success}}return t===\"Optional\"?j(r):r}}function TT(e){return e===\"Prism\"||e===\"Optional\"}function J$(e){return e===\"Iso\"||e===\"Prism\"}function UQ(e,t){return e===\"Iso\"?t:t===\"Iso\"||e===t?e:\"Optional\"}var DQ=Qo([]);function pS(){return DQ}function Z$(e){let t=rS(e);return G$(Zy(t),Vy(t))}function Y$(e){return pS()}function Q$(e){return pS()}var Il=\"~effect/Schema/SchemaError\";function X$(e){return A(e,Il)&&e[Il]===Il}var eK=Kt((e,t)=>{if(e.length!==t.length)return!1;for(let r=0;re.value,es=e=>e,Ra=e=>e.bytes,go=class extends Ut(\"NetAddressError\"){},wl=e=>A(e,qn),Ir=e=>wl(e)&&e._tag===\"Ipv4Address\",yo=e=>wl(e)&&e._tag===\"Ipv6Address\",vT=e=>Ir(e)||yo(e),Al=e=>Ir(e)?32:128;var Cl=e=>wl(e)&&e._tag===\"MacAddress\",Nm=e=>wl(e)&&e._tag===\"InetAddressV4\",Um=e=>wl(e)&&e._tag===\"InetAddressV6\",kT=e=>Nm(e)||Um(e),dS=e=>wl(e)&&e._tag===\"UnixPathAddress\",rK=e=>kT(e)||dS(e),$Q={...$t,_tag:\"Ipv4Address\",[qn]:qn,[ne](e){return Ir(e)&&Xo(this)===Xo(e)},[re](){return lr(Ee(jQ,Xo(this)|0))},toString(){return wr(this)},toJSON(){return this.toString()}},KQ={...$t,_tag:\"Ipv6Address\",[qn]:qn,[ne](e){if(!yo(e))return!1;let t=es(this),r=es(e);return t.w0===r.w0&&t.w1===r.w1&&t.w2===r.w2&&t.w3===r.w3},[re](){let e=es(this),t=Ee(HQ,e.w0|0);return t=Ee(t,e.w1|0),t=Ee(t,e.w2|0),lr(Ee(t,e.w3|0))},toString(){return wr(this)},toJSON(){return this.toString()}},BQ={...$t,_tag:\"MacAddress\",[qn]:qn,[ne](e){return Cl(e)&&eK(Ra(this),Ra(e))},[re](){return Ee(zQ,wo(Ra(this)))},toString(){return RT(this)},toJSON(){return this.toString()}},jQ=Pe(\"Ipv4Address\"),HQ=Pe(\"Ipv6Address\"),zQ=Pe(\"MacAddress\"),WQ=e=>{let t=Object.create($Q);return t.value=e>>>0,Object.freeze(t)},qQ=(e,t,r,n)=>{let o=Object.create(KQ);return o.w0=e>>>0,o.w1=t>>>0,o.w2=r>>>0,o.w3=n>>>0,Object.freeze(o)},JQ=(e,t,r,n)=>(e<<24|t<<16|r<<8|n)>>>0;var Fm=e=>[e>>>24,e>>>16&255,e>>>8&255,e&255],GQ=e=>{let t=Object.assign(Object.create(BQ),{bytes:new Uint8Array(e)});return Object.freeze(t)};var bt=(e,t)=>q(new go({input:e,message:t})),nK=(e,t)=>{for(let r=0;rt)return!1}return!0},VQ=e=>nK(e,255)?j(WQ(JQ(e[0],e[1],e[2],e[3]))):bt(e,\"octets must be integers from 0 through 255\"),ZQ=e=>nK(e,65535)?j(qQ(e[0]*65536+e[1],e[2]*65536+e[3],e[4]*65536+e[5],e[6]*65536+e[7])):bt(e,\"segments must be integers from 0 through 65535\");var oK=e=>/^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/.test(e)?j(GQ(new Uint8Array(e.split(\":\").map(t=>Number.parseInt(t,16))))):bt(e,\"expected six two-digit hexadecimal octets separated by colons\");var bu=e=>{let t=e.split(\".\");if(t.length!==4||t.some(n=>!/^\\d{1,3}$/.test(n)))return bt(e,\"expected exactly four decimal octets\");if(t.some(n=>n.length>1&&n[0]===\"0\"))return bt(e,\"leading zeroes are not allowed\");let r=t.map(Number);return r.some(n=>n>255)?bt(e,\"octets must be at most 255\"):VQ([r[0],r[1],r[2],r[3]])},YQ=e=>{if(e.includes(\"[\")||e.includes(\"]\")||e.includes(\"%\"))return bt(e,\"brackets and zone identifiers are not valid in a bare IPv6 address\");let t=e.split(\"::\");if(t.length>2)return bt(e,\"only one compression marker is allowed\");let r=t[0]===\"\"?[]:t[0].split(\":\"),n=t.length===2&&t[1]!==\"\"?t[1].split(\":\"):[];if(r.some(f=>f===\"\")||n.some(f=>f===\"\"))return bt(e,\"empty segments are only valid in the compression marker\");let o=n.length>0?n[n.length-1]:r.length>0?r[r.length-1]:\"\",s;if(o.includes(\".\")){if(t.length===2&&n.length===0)return bt(e,\"embedded IPv4 syntax must be trailing\");let f=sr(bu(o),p=>{let d=Xo(p);return[d>>>16,d&65535]});if(ae(f))return f;s=f.success,n.length>0?n.pop():r.pop()}let a=r.length+n.length+(s?2:0);if(t.length===1?a!==8:a>=8)return bt(e,t.length===1?\"expected eight segments\":\"compression must replace at least one segment\");let i=f=>/^[0-9a-fA-F]{1,4}$/.test(f)?Number.parseInt(f,16):void 0,c=r.map(i),u=n.map(i);return c.some(f=>f===void 0)||u.some(f=>f===void 0)?bt(e,\"segments must contain one through four hexadecimal digits\"):j([...c,...Array(8-a).fill(0),...u,...s??[]])},Eu=e=>Yt(YQ(e),t=>ZQ(t)),$i=e=>e.includes(\":\")?Eu(e):bu(e);var OT=e=>{if(typeof e!=\"string\"||!e.includes(\"%\"))return!1;let t=Dm(e);return rt(t)&&t.success===e},Dm=e=>{let t=e.indexOf(\"%\");if(t===-1)return bt(e,\"expected an IPv6 zone\");let r=e.slice(t+1);if(r.length===0||/[%[\\]/\\s\\p{Cc}]/u.test(r))return bt(e,\"invalid IPv6 scope identifier\");if(/^\\d+$/.test(r)){let n=Number(r);if(n>4294967295)return bt(e,\"scope identifier must be an unsigned 32-bit integer\");r=String(n)}return sr(Eu(e.slice(0,t)),n=>`${wr(n)}%${r}`)};var mS=e=>Fm(Xo(e)),QQ=e=>{let{w0:t,w1:r,w2:n,w3:o}=es(e);return[t>>>16,t&65535,r>>>16,r&65535,n>>>16,n&65535,o>>>16,o&65535]},_T=e=>{let{w0:t,w1:r,w2:n,w3:o}=es(e);return[...Fm(t),...Fm(r),...Fm(n),...Fm(o)]};var RT=e=>Array.from(Ra(e),t=>t.toString(16).padStart(2,\"0\")).join(\":\"),hS=e=>Ra(e).every(t=>t===255),XQ=e=>(Ra(e)[0]&1)!==0,xS=e=>(Ra(e)[0]&1)===0,PT=e=>(Ra(e)[0]&2)!==0,MT=e=>(Ra(e)[0]&2)===0;var wr=e=>{if(Ir(e))return mS(e).join(\".\");let t=QQ(e);if(eX(e))return`::ffff:${t[6]>>8}.${t[6]&255}.${t[7]>>8}.${t[7]&255}`;let r=-1,n=0,o=-1;for(let i=0;i<=8;i++)i<8&&t[i]===0?o===-1&&(o=i):o!==-1&&(i-o>n&&(r=o,n=i-o),o=-1);if(n<2)return t.map(i=>i.toString(16)).join(\":\");let s=t.slice(0,r).map(i=>i.toString(16)).join(\":\"),a=t.slice(r+n).map(i=>i.toString(16)).join(\":\");return`${s}::${a}`},gS=e=>{if(Ir(e))return Xo(e)===0;let{w0:t,w1:r,w2:n,w3:o}=es(e);return t===0&&r===0&&n===0&&o===0},FT=e=>{if(Ir(e))return Xo(e)>>>24===127;let{w0:t,w1:r,w2:n,w3:o}=es(e);return t===0&&r===0&&n===0&&o===1},Tl=e=>Cl(e)?XQ(e):Ir(e)?Xo(e)>>>28===14:es(e).w0>>>24===255,yS=e=>Cl(e)?hS(e):Xo(e)===4294967295,NT=e=>Cl(e)?xS(e):!Tl(e)&&!gS(e)&&(!Ir(e)||!yS(e)),UT=e=>Ir(e)?Xo(e)>>>16===43518:(es(e).w0>>>16&65472)===65152,DT=e=>{let t=Xo(e);return t>>>24===10||(t>>>16&65520)===44048||t>>>16===49320},LT=e=>(es(e).w0>>>24&254)===252,eX=e=>{let{w0:t,w1:r,w2:n}=es(e);return t===0&&r===0&&n===65535};var tX={...$t,_tag:\"InetAddressV4\",[qn]:qn,[ne](e){return Nm(e)&&this.port===e.port&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.port))},toString(){return SS(this)},toJSON(){return this.toString()}},rX={...$t,_tag:\"InetAddressV6\",[qn]:qn,[ne](e){return Um(e)&&this.port===e.port&&this.scopeId===e.scopeId&&Z(this.address,e.address)},[re](){return Ee(Ee(V(this.address),Lt(this.port)),Lt(this.scopeId))},toString(){return SS(this)},toJSON(){return this.toString()}},sK=e=>Number.isInteger(e)&&e>=0&&e<=65535,nX=(e,t)=>{if(!sK(t))return bt(e,\"port must be an integer from 0 through 65535\");let r=Object.create(tX);return r.address=e,r.port=t,j(Object.freeze(r))},oX=(e,t,r)=>{if(!sK(t))return bt(e,\"port must be an integer from 0 through 65535\");let n=r?.scopeId??0;if(!Number.isInteger(n)||n<0||n>4294967295)return bt(e,\"scopeId must be an unsigned 32-bit integer\");let o=Object.create(rX);return o.address=e,o.port=t,o.scopeId=n,j(Object.freeze(o))};var $T=e=>{let t,r,n=0,o=e.startsWith(\"[\");if(o){let s=e.indexOf(\"]\");if(s<0||e[s+1]!==\":\"||e.indexOf(\"]\",s+1)!==-1)return bt(e,\"expected [IPv6]:port\");t=e.slice(1,s),r=e.slice(s+2);let a=t.indexOf(\"%\");if(a!==-1){let i=t.slice(a+1);if(t.indexOf(\"%\",a+1)!==-1||!/^\\d+$/.test(i))return bt(e,\"scope identifier must be decimal\");if(n=Number(i),!Number.isInteger(n)||n>4294967295)return bt(e,\"scope identifier must be an unsigned 32-bit integer\");t=t.slice(0,a)}}else{let s=e.lastIndexOf(\":\");if(s<0)return bt(e,\"expected host:port or [IPv6]:port\");if(e.indexOf(\":\")!==s)return bt(e,\"IPv6 addresses must be bracketed\");t=e.slice(0,s),r=e.slice(s+1)}return/^(0|[1-9]\\d*)$/.test(r)?Yt($i(t),s=>o!==yo(s)?bt(e,\"only IPv6 addresses use brackets\"):yo(s)?oX(s,Number(r),{scopeId:n}):nX(s,Number(r))):bt(e,\"port must be an unpadded decimal integer\")};var sX=e=>wr(e.address)+(Um(e)&&e.scopeId!==0?`%${e.scopeId}`:\"\");var SS=e=>{let t=sX(e);return Nm(e)?`${t}:${e.port}`:`[${t}]:${e.port}`};var aX={...$t,_tag:\"UnixPathAddress\",[qn]:qn,[ne](e){return dS(e)&&this.path===e.path},[re](){return Ee(Pe(\"UnixPathAddress\"),Pe(this.path))},toString(){return this.path},toJSON(){return this.toString()}},aK=e=>{let t=Object.create(aX);return t.path=e,Object.freeze(t)};var KT=\"~effect/net/Host\",Ki=(e,t)=>q(new go({input:e,message:t})),iK=/^[a-z0-9_.-]*$/i,iX=/[\\u0080-\\uffff]/g,cX=/^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/,uX=/^(?:\\d+|0x[0-9a-f]*)$/,cK=e=>{if(e===\".\")return;let t=e.endsWith(\".\")?e.slice(0,-1):e;if(t.length===0)return\"domain name must not be empty\";if(t.length>253)return\"domain name must be at most 253 characters\";let r=t.split(\".\");for(let n of r){if(n.length===0)return\"domain name labels must not be empty\";if(n.length>63)return\"domain name labels must be at most 63 characters\";if(!cX.test(n))return\"domain name labels must contain only letters, digits, hyphens, or underscores and must not start or end with a hyphen\"}if(uX.test(r[r.length-1]))return\"the last domain name label must not be numeric\"},fX=e=>{if(iK.test(e))return e.toLowerCase();if(iK.test(e.normalize(\"NFC\").replace(iX,\"\")))try{return new URL(`http://${e}`).hostname}catch{return}},Pa=e=>typeof e==\"string\"&&/^[a-z0-9_.-]+$/.test(e)&&cK(e)===void 0;var jT=e=>A(e,KT),bS=e=>{let t=fX(e);if(t===void 0)return Ki(e,\"invalid domain name\");let r=cK(t);return r===void 0?j(t):Ki(e,r)};var lX=e=>{if(e.includes(\"%\"))return Dm(e);if(e.includes(\":\"))return $i(e);if(/^[\\d.]+$/.test(e)){let t=$i(e);if(rt(t))return t}return bS(e)};var pX=e=>typeof e==\"string\"?e:wr(e);var dX={...$t,_tag:\"HostPort\",[KT]:KT,[ne](e){return jT(e)&&this.port===e.port&&Z(this.host,e.host)},[re](){return Ee(V(this.host),Lt(this.port))},toString(){return HT(this)},toJSON(){return this.toString()}},mX=e=>Number.isInteger(e)&&e>=0&&e<=65535,hX=(e,t)=>{let r=Object.create(dX);return r.host=e,r.port=t,Object.freeze(r)};var uK=e=>{let t,r;if(e.startsWith(\"[\")){let o=e.indexOf(\"]\");if(o===-1||e[o+1]!==\":\")return Ki(e,\"expected [IPv6]:port\");if(t=e.slice(1,o),r=e.slice(o+2),!t.includes(\":\"))return Ki(e,\"only IPv6 addresses use brackets\")}else{let o=e.lastIndexOf(\":\");if(o===-1)return Ki(e,\"expected host:port\");if(e.indexOf(\":\")!==o)return Ki(e,\"IPv6 addresses must be bracketed\");t=e.slice(0,o),r=e.slice(o+1)}if(!/^(0|[1-9]\\d*)$/.test(r))return Ki(e,\"port must be an unpadded decimal integer\");let n=Number(r);return mX(n)?sr(lX(t),o=>hX(o,n)):Ki(e,\"port must be an integer from 0 through 65535\")};var HT=e=>{let t=pX(e.host);return t.includes(\":\")?`[${t}]:${e.port}`:`${t}:${e.port}`};var WT=\"~effect/net/Dns/DnsRecord\",zT=e=>Number.isInteger(e)&&e>=0&&e<=255,vl=e=>Number.isInteger(e)&&e>=0&&e<=65535,pK=e=>Number.isInteger(e)&&e>=0&&e<=4294967295,Bi=e=>typeof e==\"string\",ES=e=>Fp(e)&&sn(e)&&pK(hs(e)),dK={A:{address:Ir},AAAA:{address:yo},CAA:{critical:e=>typeof e==\"boolean\",tag:e=>Bi(e)&&/^[a-z0-9]+$/i.test(e),value:Bi},CNAME:{target:Pa},MX:{exchange:Pa,priority:vl},NAPTR:{order:vl,preference:vl,flags:Bi,service:Bi,regexp:Bi,replacement:Pa},NS:{host:Pa},PTR:{host:e=>Bi(e)&&e.length>0},SOA:{primary:Pa,admin:e=>Bi(e)&&e.length>0,serial:pK,refresh:ES,retry:ES,expire:ES,minimum:ES},SRV:{target:Pa,port:vl,priority:vl,weight:vl},TLSA:{certUsage:zT,selector:zT,matchingType:zT,data:e=>e instanceof Uint8Array&&e.length>0},TXT:{chunks:e=>Array.isArray(e)&&e.length>0&&e.every(Bi)}},qT=Object.keys(dK),xX=e=>qT.includes(e),JT=e=>A(e,WT),gX={...$t,[WT]:WT,[ne](e){return JT(e)&&e._tag===this._tag&&Object.keys(this).every(t=>Z(this[t],e[t]))},[re](){return dp(this,Object.keys(this))},toString(){return SX(this)},toJSON(){return{...this}}},mK=(e,t)=>{if(!xX(e))return q(new go({input:e,message:\"unknown DNS record type\"}));let r=typeof t==\"object\"&&t!==null?t:{},n=Object.create(gX);n._tag=e;for(let[o,s]of Object.entries(dK[e])){let a=r[o];if(!s(a))return q(new go({input:t,message:`invalid ${e} record ${o}`}));n[o]=Array.isArray(a)?Object.freeze([...a]):a instanceof Uint8Array?new Uint8Array(a):a}return j(Object.freeze(n))};var hK=new TextEncoder,xK=e=>`\\\\${e.toString().padStart(3,\"0\")}`,$m=e=>{let t='\"';for(let r of hK.encode(e))t+=r===34||r===92?`\\\\${String.fromCharCode(r)}`:r<32||r>126?xK(r):String.fromCharCode(r);return t+'\"'},yX=[34,36,40,41,59,64],lK=e=>{let t=hK.encode(e),r=\"\";for(let n=0;n126?r+=xK(o):r+=yX.includes(o)?`\\\\${String.fromCharCode(o)}`:String.fromCharCode(o)}return r},SX=e=>{switch(e._tag){case\"A\":case\"AAAA\":return`${e._tag} ${wr(e.address)}`;case\"CAA\":return`CAA ${e.critical?128:0} ${e.tag} ${$m(e.value)}`;case\"CNAME\":return`CNAME ${e.target}`;case\"MX\":return`MX ${e.priority} ${e.exchange}`;case\"NAPTR\":return`NAPTR ${e.order} ${e.preference} ${$m(e.flags)} ${$m(e.service)} ${$m(e.regexp)} ${e.replacement}`;case\"NS\":return`NS ${e.host}`;case\"PTR\":return`PTR ${lK(e.host)}`;case\"SOA\":return`SOA ${e.primary} ${lK(e.admin)} ${e.serial} ${hs(e.refresh)} ${hs(e.retry)} ${hs(e.expire)} ${hs(e.minimum)}`;case\"SRV\":return`SRV ${e.priority} ${e.weight} ${e.port} ${e.target}`;case\"TLSA\":return`TLSA ${e.certUsage} ${e.selector} ${e.matchingType} ${gx(e.data).toUpperCase()}`;case\"TXT\":return`TXT ${e.chunks.map($m).join(\" \")}`}};var GT=\"~effect/net/IpInterface\",gK=e=>Km(e)&&Ir(e.address),yK=e=>Km(e)&&yo(e.address),Km=e=>A(e,GT),wX={...$t,_tag:\"IpInterface\",[GT]:GT,[ne](e){return Km(e)&&this.prefixLength===e.prefixLength&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.prefixLength))},toString(){return jm(this)},toJSON(){return this.toString()}},VT=(e,t)=>q(new go({input:e,message:t})),Bm=(e,t)=>{let r=Al(e);if(!Number.isInteger(t)||t<0||t>r)return VT(e,`prefix length must be an integer from 0 through ${r}`);let n=Object.assign(Object.create(wX),{address:e,prefixLength:t});return j(Object.freeze(n))},ZT=(e,t)=>{let r=e.indexOf(\"/\");if(r===-1&&t?.prefix!==\"required\")return j({address:e,prefixLength:void 0});if(r<=0||r!==e.lastIndexOf(\"/\")||r===e.length-1)return VT(e,\"expected an address and prefix length separated by one slash\");let n=e.slice(r+1);return/^(0|[1-9][0-9]*)$/.test(n)?j({address:e.slice(0,r),prefixLength:Number(n)}):VT(e,\"prefix length must be an unpadded ASCII decimal integer\")},IS=(e,t)=>Yt(ZT(e,t),r=>Yt(bu(r.address),n=>Bm(n,r.prefixLength??Al(n)))),wS=(e,t)=>Yt(ZT(e,t),r=>Yt(Eu(r.address),n=>Bm(n,r.prefixLength??Al(n)))),AS=(e,t)=>Yt(ZT(e,t),r=>Yt($i(r.address),n=>Bm(n,r.prefixLength??Al(n))));var jm=e=>`${wr(e.address)}/${e.prefixLength}`;var YT=\"~effect/net/IpNetwork\",bK=e=>Hm(e)&&Ir(e.address),EK=e=>Hm(e)&&yo(e.address),Hm=e=>A(e,YT),AX={...$t,_tag:\"IpNetwork\",[YT]:YT,[ne](e){return Hm(e)&&this.prefixLength===e.prefixLength&&Z(this.address,e.address)},[re](){return Ee(V(this.address),Lt(this.prefixLength))},toString(){return zm(this)},toJSON(){return this.toString()}},CX=e=>{let t=Object.assign(Object.create(AX),{address:e.address,prefixLength:e.prefixLength});return Object.freeze(t)},TX=e=>Ir(e)?mS(e):_T(e);var vX=(e,t)=>{let r=Math.floor(t/8),n=t%8;return e.map((o,s)=>sYt(Bm(e,t),r=>{let n=TX(e),o=vX(n,t);return n.some((s,a)=>s!==o[a])?q(new go({input:e,message:\"address has non-zero host bits\"})):j(CX(r))});var IK=e=>Yt(IS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength)),wK=e=>Yt(wS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength)),AK=e=>Yt(AS(e,{prefix:\"required\"}),t=>QT(t.address,t.prefixLength));var zm=e=>`${wr(e.address)}/${e.prefixLength}`;var XT=\"~effect/SemVer\",ev=\"~effect/SemVer/SemVerError\",CS=class extends Ut(\"SemVerError\"){[ev]=ev},OX=e=>A(e,ev),So=e=>{throw new CS({message:e})},_X=e=>lE({try:e,catch:t=>{if(!OX(t))throw t;return t}}),tv=(e,t,r)=>nf(_X(()=>r(t)),n=>new CS({message:`Invalid ${e} ${JSON.stringify(t)}: ${n.message}`,input:t})),RX=/^(?:0|[1-9]\\d*)$/,PX=/^\\d+$/,TK=/^[0-9A-Za-z-]+$/,Wm=(e,t)=>!Number.isSafeInteger(e)||e<0?So(`${t} must be a non-negative safe integer, received ${e}`):e,kl=(e,t)=>RX.test(e)?Wm(Number(e),t):So(`${t} must be a non-negative integer without leading zeros, received ${JSON.stringify(e)}`),TS=e=>typeof e==\"number\"?Wm(e,\"numeric pre-release identifier\"):TK.test(e)?PX.test(e)?kl(e,\"numeric pre-release identifier\"):e:So(`pre-release identifier must be non-empty [0-9A-Za-z-], received ${JSON.stringify(e)}`),vK=e=>TK.test(e)?e:So(`build identifier must be non-empty [0-9A-Za-z-], received ${JSON.stringify(e)}`);var MX={[XT]:XT,[ne](e){return rv(e)&&NX(this,e)},[re](){return Pe(Iu(this))},toString(){return`SemVer(${Iu(this)})`},toJSON(){return{_id:\"SemVer\",value:Iu(this)}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},kK=(e,t,r,n,o)=>{let s=Object.create(MX);return s.major=e,s.minor=t,s.patch=r,s.prerelease=n,s.build=o,s};var rv=e=>A(e,XT),nv=e=>kK(Wm(e.major,\"major\"),Wm(e.minor,\"minor\"),Wm(e.patch,\"patch\"),e.prerelease?.map(TS)??[],e.build?.map(vK)??[]),FX=e=>{let t=e,r=[],n=t.indexOf(\"+\");n!==-1&&(r=t.slice(n+1).split(\".\").map(vK),t=t.slice(0,n));let o=[],s=t.indexOf(\"-\");s!==-1&&(o=t.slice(s+1).split(\".\").map(TS),t=t.slice(0,s));let a=t.split(\".\");return a.length!==3?So(\"expected MAJOR.MINOR.PATCH\"):kK(kl(a[0],\"major\"),kl(a[1],\"minor\"),kl(a[2],\"patch\"),o,r)},OK=e=>tv(\"SemVer\",e,FX);var Iu=e=>{let t=`${e.major}.${e.minor}.${e.patch}`;return e.prerelease.length>0&&(t+=`-${e.prerelease.join(\".\")}`),e.build.length>0&&(t+=`+${e.build.join(\".\")}`),t};var CK=Zu(Wa()),NX=Kt((e,t)=>e.major===t.major&&e.minor===t.minor&&e.patch===t.patch&&CK(e.prerelease,t.prerelease)&&CK(e.build,t.build));var av=\"~effect/SemVerRange\",UX={[av]:av,[ne](e){return iv(e)&&ji(this)===ji(e)},[re](){return Pe(ji(this))},toString(){return`SemVerRange(${ji(this)})`},toJSON(){return{_id:\"SemVerRange\",value:ji(this)}},[Je](){return this.toJSON()},pipe(){return te(this,arguments)}},iv=e=>A(e,av);var DX={components:[],prerelease:[]},LX=/^(<=|>=|<|>|=|~|\\^)?(.*)$/,$X=e=>e===\"x\"||e===\"X\"||e===\"*\",KX=[\"major\",\"minor\",\"patch\"],ov=e=>{if(e.length===0)return So(\"expected a version after the operator\");if(e.includes(\"+\"))return So(`build metadata is not allowed in ranges, received ${JSON.stringify(e)}`);let t=e.indexOf(\"-\"),r=(t===-1?e:e.slice(0,t)).split(\".\");if(r.length>3)return So(`expected at most MAJOR.MINOR.PATCH, received ${JSON.stringify(e)}`);let n=[];for(let o=0;o{let t=e.split(/\\s+/).filter(n=>n.length>0);if(t.length===0)return So(\"expected a comparator\");if(t.length===3&&t[1]===\"-\")return[{_tag:\"Hyphen\",from:ov(t[0]),to:ov(t[2])}];let r=[];for(let n=0;n{let t=Object.create(UX);return t.sets=e,t},jX=e=>e.trim().length===0?HX:RK(e.split(\"||\").map(BX)),cv=e=>tv(\"SemVer range\",e,jX),PK=e=>ms(cv(e));var HX=RK([[{_tag:\"Comparator\",operator:\"=\",version:DX}]]);var sv=e=>{if(e.components.length===0)return\"*\";let t=e.components.join(\".\");return e.prerelease.length===0?t:`${t}-${e.prerelease.join(\".\")}`},zX=e=>e._tag===\"Hyphen\"?`${sv(e.from)} - ${sv(e.to)}`:`${e.operator===\"=\"?\"\":e.operator}${sv(e.version)}`,ji=e=>e.sets.map(t=>t.map(zX).join(\" \")).join(\" || \");var qm=Qy;function yn(){return(e,t,r)=>Q(new ll(e.map(Em),n=>t(n.map(o=>Q(o))),r))}function je(e,t){return yn()([],()=>(r,n,o)=>e(r)?g(r):F(new _t(n,r,o)),t)}function WX(e){return e}function qX(e){return t=>t.annotate(e)}function JX(e){return t=>fv(fv(t).annotate(e))}function GX(e){return t=>t.rebuild(Tm(t.ast,e))}function VX(e){return e}var Ma=class extends Ut(\"SchemaError\"){[Il]=Il;constructor(t){let r=Co();pr(0);try{super({issue:t})}finally{pr(r)}}get message(){return U2(this.issue)}toJSON(){return{_tag:this._tag,message:this.message}}[Je](){return this.toJSON()}toString(){return`SchemaError(${this.message})`}};function JK(e){return X$(e)}function GK(e){return Ve(e)?hv(e):nt(e,t=>da(()=>fa(t,r=>new Ma(r))))}function hv(e){return ut(e)?e:Fn(fa(e.cause,t=>new Ma(t)))}function VK(e,t){let r;for(let n of e.reasons){if(!ai(n)||!JK(n.error))throw new globalThis.Error(t,{cause:e});r??=n.error}if(r===void 0)throw new globalThis.Error(t,{cause:e});return r}function ZK(e){return kg(e).then(t=>{if(ut(t))return t.value;throw VK(t.cause,\"Promise adapter can only reject schema errors\")})}function YK(e){let t=Ts(e);if(ut(t))return t.value;throw VK(t.cause,\"Sync adapter can only throw schema errors\")}function ZX(e,t){return O$(e,t)}function YX(e){return R$(e)}var QX=km,XX=RL;function OS(e,t){let r=St(e,t);return(n,o)=>GK(r(n,o))}var eee=OS;function QK(e,t){let r=PL(e,t);return(n,o)=>hv(r(n,o))}var tee=QK,ree=YC,nee=ML;function XK(e,t){let r=FL(e,t);return(n,o)=>nf(r(n,o),s=>new Ma(s))}var oee=XK;function eB(e,t){let r=OS(e,t);return(n,o)=>ZK(r(n,o))}var see=eB;function tB(e,t){let r=OS(e,t);return(n,o)=>YK(r(n,o))}var aee=tB;function _S(e,t){let r=hu(e,t);return(n,o)=>GK(r(n,o))}var iee=_S;function rB(e,t){let r=UL(e,t);return(n,o)=>hv(r(n,o))}var cee=rB,uee=QC,fee=DL;function nB(e,t){let r=LL(e,t);return(n,o)=>nf(r(n,o),s=>new Ma(s))}var lee=nB;function oB(e,t){let r=_S(e,t);return(n,o)=>ZK(r(n,o))}var pee=oB;function sB(e,t){let r=_S(e,t);return(n,o)=>YK(r(n,o))}var dee=sB,Q=Wn;function RS(e){return A(e,qm)&&e[qm]===qm}var rs=Kr(e=>Q(mu(e.ast),{schema:e})),mee=Kr(e=>e.schema),Ml=Kr(e=>{let t=NS(e);return Q(lL(e.ast),{schema:t})}),hee=Kr(e=>e.schema.members[0]),xee=Kr(e=>Q(UC(e.ast),{schema:e})),gee=Kr(e=>e.schema),Sn=Kr(e=>Q(Mt(e.ast),{schema:e})),Fl=Kr(e=>Q(gn(e.ast),{schema:e})),Jm=\"~effect/Schema/flip\";function yee(e){return A(e,Jm)&&e[Jm]===Jm}function fv(e){return yee(e)?e.schema.rebuild(Bn(e.ast)):Q(Bn(e.ast),{[Jm]:Jm,schema:e})}function zt(e){let t=Q(new Kn(e),{literal:e,transform(r){return t.pipe(J(zt(r),{decode:le(()=>r),encode:le(()=>e)}))}});return t}function aB(e){return e.map(t=>RS(t)?t.ast:new Kn(t))}function See(e){return Q(new IC(aB(e)),{parts:e})}function bee(e){return Q(qD(aB(e)),{parts:e})}function Eee(e){return Q(new WD(Object.keys(e).filter(t=>typeof e[e[t]]!=\"number\").map(t=>[t,e[t]])),{enums:e})}var iB=Q(pl),Iee=Q(HD),Nl=Q(Jo),PS=Q(ym),xv=Q(EC),H=Q(xn),wee=H,wu=Q(wC),Gm=Q(VD),cB=Q(ZD),Ul=Q(YD),Aee=Q(jD),Cee=Q(zD);function Tee(e){return Q(new GD(e))}function gv(e,t){return Q(e,{fields:t,mapFields(r,n){let o=r(this.fields);return gv(Ny(o,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function ve(e){return gv(Ny(e,void 0),e)}function vee(e){return Kr(t=>t.mapFields(z$(e)))}var kee=e=>typeof e==\"symbol\"?e:globalThis.String(e);function Oee(e){return function(t){let r={},n=Object.create(null),o=Object.create(null),s=new Set;for(let a of Reflect.ownKeys(t.fields)){let i=Fl(t.fields[a]),c=Object.hasOwn(e,a),u=c?e[a]:a,f=kee(u);if(s.has(f))throw new globalThis.Error(`Duplicate encoded keys: ${us(u)}`);s.add(f),B(r,u,i),c&&(n[a]=u,o[u]=a)}return ve(r).pipe(J(t,Ge({decode:bT(o),encode:bT(n)})))}}function _ee(e,t){return r=>{let n=gc(r.fields,Sn),o=ve({...n,...e});return r.pipe(J(o,Ge({decode:s=>{let a={...s};for(let i in e){let c=t[i],u=c(s);Ce(u)&&B(a,i,u.value)}return a},encode:s=>{let a={...s};for(let i in e)delete a[i];return a}})))}}function Na(e,t){return Q($y(e.ast,t.ast),{key:e,value:t})}function Ree(e,t){return Q(rL(e.ast,t.map(Em)),{schema:e,records:t})}function uB(e,t){return Q(e,{elements:t,mapElements(r,n){let o=r(this.elements);return uB(vC(o,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function Ds(e){return uB(vC(e),e)}function Pee(e,t){return Q(nL(e.ast,t.map(Em)),{schema:e,rest:t})}var Be=Kr(e=>Q(new jn(!1,[],[e.ast]),{value:e}));function MS(e,t,r){return t!==void 0&&r!==void 0?e.check(Av(t,r)):t!==void 0?e.check(wv(t)):r!==void 0?e.check(_B(r)):e}var FS=Kr(e=>Q(new jn(!1,[e.ast],[e.ast]),{value:e}));function Mee(e){let t=Be(e),r=Be(Sn(e)),n=J(Ds([Nl]),Ge({decode:o=>[o],encode:([o])=>o}))(e);return Q(st([n,t]).pipe(J(r)).ast,{from:st([e,t]),to:r})}function Fee(e){return Be(e).check(Tv())}var Nee=Kr(e=>Q(oL(e.ast),{schema:e}));function fB(e,t){return Q(e,{members:t,mapMembers(r,n){let o=r(this.members);return fB(Uy(o,this.ast.options,n?.unsafePreserveChecks?this.ast.checks:void 0),o)}})}function st(e,t){return fB(Uy(e,t,void 0),e)}function Jn(e){let t=e.map(zt);return Q(Uy(t,void 0,void 0),{literals:e,members:t,mapMembers(r){return st(r(this.members))},pick(r){return Jn(r)},transform(r){return st(t.map((n,o)=>n.transform(r[o])))}})}var yv=Kr(e=>st([e,PS])),NS=Kr(e=>st([e,xv])),lB=Kr(e=>st([e,PS,xv]));function pB(e){return Q(new OC(()=>e().ast))}function Uee(...e){return t=>t.check(...e)}function dB(e,t){return r=>Q(Us(r.ast,[Ly(e,t)]),{schema:r})}function US(e){return t=>Q(t.ast,{schema:t,identifier:e})}function Dee(e,t){return r=>(t.checks?r.check(...t.checks):r).pipe(US(e))}function mB(e){return t=>Q(uL(t.ast,new Ty(e,D)),{schema:t})}function hB(e){return t=>Q(fL(t.ast,new Ty(D,e)),{schema:t})}function Lee(e){return xB(e)}function xB(e){return t=>mB(Kf(e))(t)}function $ee(e){return gB(e)}function gB(e){return t=>hB(Kf(e))(t)}function J(e,t){return r=>Q(Oa(r.ast,e.ast,t?vy(t):ol()),{from:r,to:e})}function Hi(){return(e,t)=>ke()(e,{decode:t,encode:$2})}var yB=Jn([\"true\",\"yes\",\"on\",\"1\",\"y\"]),SB=Jn([\"false\",\"no\",\"off\",\"0\",\"n\"]),Sv=Jn([...yB.literals,...SB.literals]).pipe(J(Gm,Ge({decode:e=>e===\"true\"||e===\"yes\"||e===\"on\"||e===\"1\"||e===\"y\",encode:e=>e?\"true\":\"false\"})));function Kee(e){return t=>J(Sn(t),e)(t)}function bv(e,t){return r=>t?J(r,t)(e):J(r)(e)}function Bee(e){return t=>J(t,e)(Fl(t))}function bB(e){return t=>Q(pL(t.ast,e),{schema:t})}function EB(e){return Ve(e)&&e._tag===\"Success\"?e:nt(e,t=>da(()=>fa(t,r=>r.issue)))}function Ev(e,t){let r=t?.encodingStrategy===\"omit\"?nC():hn();return n=>rs(Fl(n)).pipe(J(n,{decode:oC(EB(e)),encode:r}))}function jee(e,t){return r=>Sn(r).pipe(Ev(e,t),bv(rs(r)))}function IB(e,t){let r=t?.encodingStrategy===\"omit\"?nC():hn();return n=>Ml(Fl(n)).pipe(J(n,{decode:oC(EB(e)),encode:r}))}function Hee(e,t){return r=>Sn(r).pipe(IB(e,t),bv(Ml(r)))}function Fa(e){return zt(e).pipe(bB(g(e)))}function zee(e){return Fa(e).pipe(Ev(g(e),{encodingStrategy:\"omit\"}))}function Vm(e,t){return ve({_tag:Fa(e),...t})}function wB(e){return t=>{let r={},n=[],o=new Set,s={},a=f=>p=>f.includes(p[e]);return i(t),Object.assign(t,{tag:e,cases:r,discriminants:n,isAnyOf:a,guards:s,match:c,matchOrElse:u});function i(f){let p=f.ast;if(Fy(p)&&\"members\"in f&&globalThis.Array.isArray(f.members)&&f.members.every(RS))return f.members.forEach(i);let d=cl(p);if(d.length>0){let m=d.find(h=>h.key===e)?.literal;if(vh(m)){let h=typeof m==\"number\"?globalThis.String(m):m;if(o.has(h))throw new globalThis.Error(`Duplicate discriminant: ${globalThis.String(m)}`);o.add(h),n.push(m),B(r,m,f),B(s,m,km(Sn(f)));return}}throw new globalThis.Error(\"No literal or unique symbol found\")}function c(){if(arguments.length===1){let h=arguments[0];return function(y){let S=y[e];return(Object.hasOwn(h,S)?h[S]:void 0)(y)}}let f=arguments[0],p=arguments[1],d=f[e];return(Object.hasOwn(p,d)?p[d]:void 0)(f)}function u(){if(arguments.length===2){let y=arguments[0],S=arguments[1];return function(b){let x=b[e];return(Object.hasOwn(y,x)?y[x]??S:S)(b)}}let f=arguments[0],p=arguments[1],d=arguments[2],m=f[e];return(Object.hasOwn(p,m)?p[m]??d:d)(f)}}}function Wee(e){let t={},r=[];for(let u of Object.keys(e)){let f=Vm(u,e[u]);B(t,u,f),r.push(f)}let n=st(r),{tag:o,guards:s,isAnyOf:a,match:i,matchOrElse:c}=wB(\"_tag\")(n);return Q(n.ast,{tag:o,cases:t,isAnyOf:a,guards:s,match:i,matchOrElse:c})}function qee(){return e=>e}function Au(e,t){return je(r=>r instanceof e,t)}function ke(){return(e,t)=>new Tt(e.ast,vy(t))}var Ne=Dy;function Jee(e,t=void 0){return new fu(e,t)}var FK=\"^\\\\S[\\\\s\\\\S]*\\\\S$|^\\\\S$|^$\";function AB(e){let t=new globalThis.RegExp(FK);return Ne(r=>r.trim()===r,{expected:\"a string with no leading or trailing whitespace\",representation:{id:\"effect/schema/isTrimmed\",payload:null},toJsonSchema:()=>({pattern:t.source}),toCode:()=>({runtime:\"Schema.isTrimmed()\"}),arbitraryConstraint:{patterns:[{source:FK,flags:\"\"}]},...e})}function zi(e,t){let r=e.source,n=e.flags,o=/^[dg]*uy?$/.test(n),s=n===\"\"?`new globalThis.RegExp(${K(r)})`:`new globalThis.RegExp(${K(r)}, ${K(n)})`;return wm(e,{toJsonSchema:()=>o?{pattern:n.endsWith(\"y\")?`^(?:${r})`:r}:[{},!0],toCode:()=>({runtime:`Schema.isPattern(${s})`}),...t})}function Gee(e){return $C({toCode:()=>({runtime:\"Schema.isStringFinite()\"}),...e})}function Vee(e){return KC({toCode:()=>({runtime:\"Schema.isStringBigInt()\"}),...e})}function Zee(e){return jC({toCode:()=>({runtime:\"Schema.isStringSymbol()\"}),...e})}var Yee=e=>e?new globalThis.RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$/;function Qee(e,t){let r=Yee(e);return zi(r,{expected:e?`a UUID v${e}`:\"a UUID\",representation:{id:\"effect/schema/isUUID\",payload:{version:e??null}},toJsonSchema:()=>({pattern:r.source,format:\"uuid\"}),toCode:()=>({runtime:e===void 0?\"Schema.isUUID()\":`Schema.isUUID(${e})`}),...t})}var Xee=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/u;function ete(e){return zi(Xee,{expected:\"a GUID\",representation:{id:\"effect/schema/isGUID\",payload:null},toCode:()=>({runtime:\"Schema.isGUID()\"}),...e})}var tte=/^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/u;function rte(e){return zi(tte,{representation:{id:\"effect/schema/isULID\",payload:null},toCode:()=>({runtime:\"Schema.isULID()\"}),...e})}var nte=/^[\\x00-\\x7F]*$/u;function ote(e){return zi(nte,{expected:\"an ASCII string\",representation:{id:\"effect/schema/isAscii\",payload:null},toCode:()=>({runtime:\"Schema.isAscii()\"}),...e})}function CB(e){let t=\"^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$\",r=/^[0-9a-zA-Z+/]*={0,2}$/;return Ne(n=>n.length%4===0&&r.test(n),{expected:\"a base64 encoded string\",representation:{id:\"effect/schema/isBase64\",payload:null},toJsonSchema:()=>({pattern:t}),arbitraryConstraint:{patterns:[{source:t,flags:\"\"}]},toCode:()=>({runtime:\"Schema.isBase64()\"}),...e})}function ste(e){let t=\"^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$\",r=/^[0-9a-zA-Z-_]*={0,2}$/;return Ne(n=>r.test(n)&&(n.endsWith(\"=\")?n.length%4===0:n.length%4!==1),{expected:\"a base64url encoded string\",representation:{id:\"effect/schema/isBase64Url\",payload:null},toJsonSchema:()=>({pattern:t}),arbitraryConstraint:{patterns:[{source:t,flags:\"\"}]},toCode:()=>({runtime:\"Schema.isBase64Url()\"}),...e})}function Iv(e,t,r){if(e.length===0)return t.length===0?{}:[{},!0];let n={pattern:new globalThis.RegExp(r).source};return e===t?n:[n,!0]}function ate(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(`^${_a(e)}`),o=e.replace(/[\\uD800-\\uDBFF]$/,\"\");return Ne(s=>s.startsWith(e),{expected:`a string starting with ${r}`,representation:{id:\"effect/schema/isStartingWith\",payload:{startsWith:e}},toJsonSchema:()=>Iv(o,e,`^${_a(o)}`),toCode:()=>({runtime:`Schema.isStartingWith(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}function ite(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(`${_a(e)}$`),o=e.replace(/^[\\uDC00-\\uDFFF]/,\"\");return Ne(s=>s.endsWith(e),{expected:`a string ending with ${r}`,representation:{id:\"effect/schema/isEndingWith\",payload:{endsWith:e}},toJsonSchema:()=>Iv(o,e,`${_a(o)}$`),toCode:()=>({runtime:`Schema.isEndingWith(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}function cte(e,t){let r=JSON.stringify(e),n=new globalThis.RegExp(_a(e)),o=e.replace(/^[\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF]$/g,\"\");return Ne(s=>s.includes(e),{expected:`a string including ${r}`,representation:{id:\"effect/schema/isIncluding\",payload:{includes:e}},toJsonSchema:()=>Iv(o,e,_a(o)),toCode:()=>({runtime:`Schema.isIncluding(${K(e)})`}),arbitraryConstraint:{patterns:[{source:n.source,flags:n.flags}]},...t})}var NK=\"^[^a-z]*$\";function ute(e){let t=new globalThis.RegExp(NK);return Ne(r=>r.toUpperCase()===r,{expected:\"a string with all characters in uppercase\",representation:{id:\"effect/schema/isUppercased\",payload:null},toJsonSchema:()=>[{pattern:t.source},!0],toCode:()=>({runtime:\"Schema.isUppercased()\"}),arbitraryConstraint:{patterns:[{source:NK,flags:\"\"}]},...e})}var UK=\"^[^A-Z]*$\";function fte(e){let t=new globalThis.RegExp(UK);return Ne(r=>r.toLowerCase()===r,{expected:\"a string with all characters in lowercase\",representation:{id:\"effect/schema/isLowercased\",payload:null},toJsonSchema:()=>[{pattern:t.source},!0],toCode:()=>({runtime:\"Schema.isLowercased()\"}),arbitraryConstraint:{patterns:[{source:UK,flags:\"\"}]},...e})}var DK=\"^(?:[^a-z][\\\\s\\\\S]*)?$\";function lte(e){return Ne(t=>{let[r=\"\"]=t;return r.toUpperCase()===r},{expected:\"a string with the first character in uppercase\",representation:{id:\"effect/schema/isCapitalized\",payload:null},toJsonSchema:()=>[{pattern:DK},!0],toCode:()=>({runtime:\"Schema.isCapitalized()\"}),arbitraryConstraint:{patterns:[{source:DK,flags:\"\"}]},...e})}var LK=\"^(?:[^A-Z][\\\\s\\\\S]*)?$\";function pte(e){return Ne(t=>{let[r=\"\"]=t;return r.toLowerCase()===r},{expected:\"a string with the first character in lowercase\",representation:{id:\"effect/schema/isUncapitalized\",payload:null},toJsonSchema:()=>[{pattern:LK},!0],toCode:()=>({runtime:\"Schema.isUncapitalized()\"}),arbitraryConstraint:{patterns:[{source:LK,flags:\"\"}]},...e})}var Dl=Q(RC),dte=_C;function Zm(e){let t=tf(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value greater than ${r(n)}`,arbitraryConstraint:{order:e.order,minimum:n,exclusiveMinimum:!0},...e.annotate?.(n),...o})}function Ym(e){let t=Vh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value greater than or equal to ${r(n)}`,arbitraryConstraint:{order:e.order,minimum:n},...e.annotate?.(n),...o})}function Qm(e){let t=Jh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value less than ${r(n)}`,arbitraryConstraint:{order:e.order,maximum:n,exclusiveMaximum:!0},...e.annotate?.(n),...o})}function Xm(e){let t=Gh(e.order),r=e.formatter??K;return(n,o)=>Ne(s=>t(s,n),{expected:`a value less than or equal to ${r(n)}`,arbitraryConstraint:{order:e.order,maximum:n},...e.annotate?.(n),...o})}function eh(e){let t=Vh(e.order),r=tf(e.order),n=Gh(e.order),o=Jh(e.order),s=e.formatter??K;return(a,i)=>{let c=a.exclusiveMinimum?r:t,u=a.exclusiveMaximum?o:n;return Ne(f=>c(f,a.minimum)&&u(f,a.maximum),{expected:`a value between ${s(a.minimum)}${a.exclusiveMinimum?\" (excluded)\":\"\"} and ${s(a.maximum)}${a.exclusiveMaximum?\" (excluded)\":\"\"}`,arbitraryConstraint:{order:e.order,minimum:a.minimum,maximum:a.maximum,...a.exclusiveMinimum&&{exclusiveMinimum:!0},...a.exclusiveMaximum&&{exclusiveMaximum:!0}},...e.annotate?.(a),...i})}}function mte(e){return(t,r)=>{let n=e.formatter??K;return Ne(o=>e.remainder(o,t)===e.zero,{expected:`a value that is a multiple of ${n(t)}`,...e.annotate?.(t),...r})}}function _l(e){if(!globalThis.Number.isFinite(e))throw new globalThis.RangeError(`Expected a finite number, got ${K(e)}`);return e}var hte=Zm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isGreaterThan\",payload:{exclusiveMinimum:_l(e)}},toJsonSchema:()=>({exclusiveMinimum:e}),toCode:()=>({runtime:`Schema.isGreaterThan(${K(e)})`})})}),TB=Ym({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualTo\",payload:{minimum:_l(e)}},toJsonSchema:()=>({minimum:e}),toCode:()=>({runtime:`Schema.isGreaterThanOrEqualTo(${K(e)})`})})}),xte=Qm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isLessThan\",payload:{exclusiveMaximum:_l(e)}},toJsonSchema:()=>({exclusiveMaximum:e}),toCode:()=>({runtime:`Schema.isLessThan(${K(e)})`})})}),gte=Xm({order:Qs,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualTo\",payload:{maximum:_l(e)}},toJsonSchema:()=>({maximum:e}),toCode:()=>({runtime:`Schema.isLessThanOrEqualTo(${K(e)})`})})}),Ls=eh({order:Qs,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetween\",payload:{minimum:_l(e.minimum),maximum:_l(e.maximum),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>({[t?\"exclusiveMinimum\":\"minimum\"]:e.minimum,[r?\"exclusiveMaximum\":\"maximum\"]:e.maximum}),toCode:()=>({runtime:`Schema.isBetween({ minimum: ${K(e.minimum)}, maximum: ${K(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}});function yte(e,t){if(!globalThis.Number.isFinite(e)||e===0)throw new globalThis.RangeError(`Expected a finite non-zero number, got ${globalThis.String(e)}`);return e=globalThis.Math.abs(e),Ne(r=>DF(r,e)===0,{expected:`a value that is a multiple of ${e}`,representation:{id:\"effect/schema/isMultipleOf\",payload:{divisor:e}},toJsonSchema:()=>({multipleOf:e}),toCode:()=>({runtime:`Schema.isMultipleOf(${K(e)})`}),...t})}function DS(e){return Ne(t=>globalThis.Number.isSafeInteger(t),{expected:\"an integer\",representation:{id:\"effect/schema/isInt\",payload:null},toJsonSchema:()=>({type:\"integer\",minimum:globalThis.Number.MIN_SAFE_INTEGER,maximum:globalThis.Number.MAX_SAFE_INTEGER}),toCode:()=>({runtime:\"Schema.isInt()\"}),arbitraryConstraint:{number:\"integer\"},...e})}var tn=wu.check(DS()),ts=tn.check(TB(0));function Ste(e){return new fu([DS(),Ls({minimum:-2147483648,maximum:2147483647})],{expected:\"a 32-bit integer\",...e})}function bte(e){return new fu([DS(),Ls({minimum:0,maximum:4294967295})],{expected:\"a 32-bit unsigned integer\",...e})}function Rl(e){if(globalThis.Number.isNaN(e.getTime()))throw new globalThis.RangeError(`Expected a valid Date, got ${K(e)}`);return e.toISOString()}function Pl(e){return`new globalThis.Date(${K(e.getTime())})`}var Ete=Zm({order:ef,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanDate\",payload:{exclusiveMinimum:Rl(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanDate(${Pl(e)})`})})}),Ite=Ym({order:ef,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualToDate\",payload:{minimum:Rl(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanOrEqualToDate(${Pl(e)})`})})}),wte=Qm({order:ef,annotate:e=>({representation:{id:\"effect/schema/isLessThanDate\",payload:{exclusiveMaximum:Rl(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanDate(${Pl(e)})`})})}),Ate=Xm({order:ef,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualToDate\",payload:{maximum:Rl(e)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanOrEqualToDate(${Pl(e)})`})})}),Cte=eh({order:ef,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetweenDate\",payload:{minimum:Rl(e.minimum),maximum:Rl(e.maximum),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenDate({ minimum: ${Pl(e.minimum)}, maximum: ${Pl(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}}),Tte=Zm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanBigInt\",payload:{exclusiveMinimum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanBigInt(${K(e)})`})})}),vB=Ym({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isGreaterThanOrEqualToBigInt\",payload:{minimum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isGreaterThanOrEqualToBigInt(${K(e)})`})})}),vte=Qm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isLessThanBigInt\",payload:{exclusiveMaximum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanBigInt(${K(e)})`})})}),kte=Xm({order:Xu,annotate:e=>({representation:{id:\"effect/schema/isLessThanOrEqualToBigInt\",payload:{maximum:e.toString(10)}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isLessThanOrEqualToBigInt(${K(e)})`})})}),Ote=eh({order:Xu,annotate:e=>{let t=e.exclusiveMinimum?!0:void 0,r=e.exclusiveMaximum?!0:void 0;return{representation:{id:\"effect/schema/isBetweenBigInt\",payload:{minimum:e.minimum.toString(10),maximum:e.maximum.toString(10),...t&&{exclusiveMinimum:t},...r&&{exclusiveMaximum:r}}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenBigInt({ minimum: ${K(e.minimum)}, maximum: ${K(e.maximum)}, exclusiveMinimum: ${K(t)}, exclusiveMaximum: ${K(r)} })`})}}});function wv(e,t){return e=Br(e),kB(e,Math.ceil(e/2),t)}function kB(e,t,r){return Ne(n=>n.length>=e,{expected:`a value with a length of at least ${e}`,representation:{id:\"effect/schema/isMinLength\",payload:{minLength:e}},toJsonSchema:({type:n})=>n===\"string\"?e<=1?{minLength:t}:[{minLength:t},!0]:n===\"array\"?{minItems:e}:n===void 0?[{minLength:t,minItems:e},!0]:[{},!0],toCode:()=>({runtime:`Schema.isMinLength(${e})`}),[pn]:!0,arbitraryConstraint:{minLength:e},...r})}function OB(e){return kB(1,1,e)}function _B(e,t){return e=Br(e),Ne(r=>r.length<=e,{expected:`a value with a length of at most ${e}`,representation:{id:\"effect/schema/isMaxLength\",payload:{maxLength:e}},toJsonSchema:({type:r})=>r===\"string\"?e===0?{maxLength:e}:[{maxLength:e},!0]:r===\"array\"?{maxItems:e}:r===void 0?[{maxLength:e,maxItems:e},!0]:[{},!0],toCode:()=>({runtime:`Schema.isMaxLength(${e})`}),[pn]:!0,arbitraryConstraint:{maxLength:e},...t})}function Av(e,t,r){return e=Br(e),t=Br(t),Ne(n=>n.length>=e&&n.length<=t,{expected:e===t?`a value with a length of ${e}`:`a value with a length between ${e} and ${t}`,representation:{id:\"effect/schema/isBetweenLength\",payload:{minimum:e,maximum:t}},toJsonSchema:({type:n})=>n===\"string\"?t===0||Math.ceil(e/2)>t?{minLength:Math.ceil(e/2),maxLength:t}:[{minLength:Math.ceil(e/2),maxLength:t},!0]:n===\"array\"?{minItems:e,maxItems:t}:n===void 0?[{minLength:Math.ceil(e/2),maxLength:t,minItems:e,maxItems:t},!0]:[{},!0],toCode:()=>({runtime:`Schema.isBetweenLength(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minLength:e,maxLength:t},...r})}function _te(e,t){return e=Br(e),Ne(r=>Cv(r,e)>=e,{expected:`a string with at least ${e} code points`,representation:{id:\"effect/schema/isMinCodePoints\",payload:{minCodePoints:e}},toJsonSchema:()=>({minLength:e}),toCode:()=>({runtime:`Schema.isMinCodePoints(${e})`}),arbitraryConstraint:{minCodePoints:e},...t})}function Rte(e,t){return e=Br(e),Ne(r=>Cv(r,e+1)<=e,{expected:`a string with at most ${e} code points`,representation:{id:\"effect/schema/isMaxCodePoints\",payload:{maxCodePoints:e}},toJsonSchema:()=>({maxLength:e}),toCode:()=>({runtime:`Schema.isMaxCodePoints(${e})`}),arbitraryConstraint:{maxCodePoints:e},...t})}function Pte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>{let o=Cv(n,t+1);return o>=e&&o<=t},{expected:e===t?`a string with ${e} code points`:`a string with between ${e} and ${t} code points`,representation:{id:\"effect/schema/isBetweenCodePoints\",payload:{minimum:e,maximum:t}},toJsonSchema:()=>({allOf:[{minLength:e},{maxLength:t}]}),toCode:()=>({runtime:`Schema.isBetweenCodePoints(${e}, ${t})`}),arbitraryConstraint:{minCodePoints:e,maxCodePoints:t},...r})}function Cv(e,t){if(t===0)return 0;let r=0;for(let n of e)if(++r>=t)break;return r}function Br(e){if(!globalThis.Number.isFinite(e))throw new globalThis.RangeError(`Expected a finite number, got ${e}`);return Math.max(0,Math.floor(e))}function Mte(e,t){return e=Br(e),Ne(r=>r.size>=e,{expected:`a value with a size of at least ${e}`,representation:{id:\"effect/schema/isMinSize\",payload:{minSize:e}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isMinSize(${e})`}),[pn]:!0,arbitraryConstraint:{minSize:e},...t})}function Fte(e,t){return e=Br(e),Ne(r=>r.size<=e,{expected:`a value with a size of at most ${e}`,representation:{id:\"effect/schema/isMaxSize\",payload:{maxSize:e}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isMaxSize(${e})`}),[pn]:!0,arbitraryConstraint:{maxSize:e},...t})}function Nte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>n.size>=e&&n.size<=t,{expected:e===t?`a value with a size of ${e}`:`a value with a size between ${e} and ${t}`,representation:{id:\"effect/schema/isBetweenSize\",payload:{minimum:e,maximum:t}},toJsonSchema:()=>[{},!0],toCode:()=>({runtime:`Schema.isBetweenSize(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minSize:e,maxSize:t},...r})}function Ute(e,t){return e=Br(e),Ne(r=>Reflect.ownKeys(r).length>=e,{expected:`a value with at least ${e===1?\"1 entry\":`${e} entries`}`,representation:{id:\"effect/schema/isMinProperties\",payload:{minProperties:e}},toJsonSchema:({type:r})=>r===\"object\"?{minProperties:e}:[{minProperties:e},!0],toCode:()=>({runtime:`Schema.isMinProperties(${e})`}),[pn]:!0,arbitraryConstraint:{minProperties:e},...t})}function Dte(e,t){return e=Br(e),Ne(r=>Reflect.ownKeys(r).length<=e,{expected:`a value with at most ${e===1?\"1 entry\":`${e} entries`}`,representation:{id:\"effect/schema/isMaxProperties\",payload:{maxProperties:e}},toJsonSchema:({type:r})=>r===\"object\"?{maxProperties:e}:[{maxProperties:e},!0],toCode:()=>({runtime:`Schema.isMaxProperties(${e})`}),[pn]:!0,arbitraryConstraint:{maxProperties:e},...t})}function Lte(e,t,r){return e=Br(e),t=Br(t),Ne(n=>Reflect.ownKeys(n).length>=e&&Reflect.ownKeys(n).length<=t,{expected:e===t?`a value with exactly ${e===1?\"1 entry\":`${e} entries`}`:`a value with between ${e} and ${t} entries`,representation:{id:\"effect/schema/isBetweenProperties\",payload:{minimum:e,maximum:t}},toJsonSchema:({type:n})=>n===\"object\"?{minProperties:e,maxProperties:t}:[{minProperties:e,maxProperties:t},!0],toCode:()=>({runtime:`Schema.isBetweenProperties(${e}, ${t})`}),[pn]:!0,arbitraryConstraint:{minProperties:e,maxProperties:t},...r})}function $te(e,t){let r=Fl(e),n=_L(r.ast);return Ne((o,s,a)=>{let i=Reflect.ownKeys(o),c=[];for(let u of i){let f=n(u,a);if(f!==void 0&&(c.push(new Ot([u],f)),a.errors===\"first\"))break}return Mr(c)?new Ht(s,c,o,a):!0},{expected:\"an object with property names matching the schema\",representation:{id:\"effect/schema/isPropertyNames\",payload:null,schemas:[r.ast]},toJsonSchema:({schemas:o,type:s})=>s===\"object\"?{propertyNames:o[0]}:[{propertyNames:o[0]},!0],toCode:({schemas:o})=>({runtime:`Schema.isPropertyNames(${o[0].runtime})`}),[pn]:!0,...t})}function Tv(e){return Ne(t=>cx(t).length===t.length,{expected:\"an array with unique items\",representation:{id:\"effect/schema/isUnique\",payload:null},toJsonSchema:()=>({uniqueItems:!0}),toCode:()=>({runtime:\"Schema.isUnique()\"}),arbitraryConstraint:{uniqueBy:D},...e})}function RB(e){return Ne(t=>cx(t.map(([r])=>r)).length===t.length,{expected:\"an array with unique keys\",representation:{id:\"effect/schema/isUniqueKey\",payload:null},toCode:()=>({runtime:\"Schema.isUniqueKey()\"}),arbitraryConstraint:{uniqueBy:t=>t[0]},...e})}var th=H.check(OB()),Kte=H.check(Av(1,1)),PB=e=>(e?.includeStack===!0?1:0)|(e?.excludeCause===!0?2:0),MB=e=>{switch(e){case 0:return;case 1:return{includeStack:!0};case 2:return{excludeCause:!0};case 3:return{includeStack:!0,excludeCause:!0}}},$K=[];function Bte(e){let t=PB(e),r=$K[t];if(r!==void 0)return r;let n=MB(t),o=Au(globalThis.Error,{representation:{id:\"effect/schema/Error\",payload:n??null},toCode:()=>({runtime:n!==void 0?`Schema.ErrorInstance(${K(n)})`:\"Schema.ErrorInstance()\",Type:\"globalThis.Error\"}),expected:\"Error\",toCodecJson:()=>ke()(Joe,SD(n))});return $K[t]=o,o}var KK=[];function jte(e){let t=PB(e),r=KK[t];if(r!==void 0)return r;let n=BS.pipe(J(Nl,bD(MB(t))));return KK[t]=n,n}function Hte(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(Ds([n,o]));return(a,i,c)=>a instanceof globalThis.Map?Sr(St(s)([...a],c),{onSuccess:u=>new globalThis.Map(u),onFailure:u=>mn(i,\"entries\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/ReadonlyMap\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.ReadonlyMap(${n[0].runtime}, ${n[1].runtime})`,Type:`globalThis.ReadonlyMap<${n[0].Type}, ${n[1].Type}>`}),expected:\"ReadonlyMap\",toCodec:([n,o])=>ke()(Be(Ds([n,o])),Ge({decode:s=>new globalThis.Map(s),encode:s=>[...s.entries()]}))});return Q(r.ast,{key:e,value:t})}function zte(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>o instanceof globalThis.Set?Sr(St(n)([...o],a),{onSuccess:i=>new globalThis.Set(i),onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/ReadonlySet\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.ReadonlySet(${r[0].runtime})`,Type:`globalThis.ReadonlySet<${r[0].Type}>`}),expected:\"ReadonlySet\",toCodec:([r])=>ke()(Be(r),Ge({decode:n=>new globalThis.Set(n),encode:n=>[...n.values()]}))});return Q(t.ast,{value:e})}var Wte=Au(globalThis.RegExp,{representation:{id:\"effect/schema/RegExp\",payload:null},toCode:()=>({runtime:\"Schema.RegExp\",Type:\"globalThis.RegExp\"}),expected:\"RegExp\",toCodecJson:()=>ke()(ve({source:H,flags:H}),mt({decode:(e,t)=>Nf({try:()=>new globalThis.RegExp(e.source,e.flags),catch:()=>new fe({expected:\"valid RegExp source and flags\"},e,t)}),encode:e=>g({source:e.source,flags:e.flags})}))}),FB=H.annotate({expected:\"a string that will be decoded as a URL\"}),LS=Au(globalThis.URL,{representation:{id:\"effect/schema/URL\",payload:null},toCode:()=>({runtime:\"Schema.URL\",Type:\"globalThis.URL\"}),expected:\"URL\",toCodecJson:()=>ke()(FB,uC)}),qte=FB.pipe(J(LS,uC)),NB=H.annotate({expected:\"a string that will be decoded as a Date\"}),Ll=je(e=>e instanceof globalThis.Date&&!globalThis.Number.isNaN(e.getTime()),{representation:{id:\"effect/schema/Date\",payload:null},toCode:()=>({runtime:\"Schema.Date\",Type:\"globalThis.Date\"}),expected:\"a valid Date\",toCodecJson:()=>ke()(NB,iC)}),Jte=NB.pipe(J(Ll,iC)),Gte=tn.pipe(J(Ll,dD)),Vte=H.annotate({expected:\"a string that will be decoded as JSON\"});function vv(e,t){return Vte.pipe(J(e,_D(t)))}var Zte=vv(Nl),UB=Au(globalThis.File,{representation:{id:\"effect/schema/File\",payload:null},toCode:()=>({runtime:\"Schema.File\",Type:\"globalThis.File\"}),expected:\"File\",toCodecJson:()=>ke()(ve({data:H.check(CB()),type:H,name:H,lastModified:tn}),mt({decode:(e,t)=>mr(Xc(e.data),{onFailure:()=>F(new fe({expected:\"a valid Base64 string\"},e.data,t)),onSuccess:r=>{let n=new globalThis.Uint8Array(r);return g(new globalThis.File([n],e.name,{type:e.type,lastModified:e.lastModified}))}}),encode:(e,t)=>fi({try:async()=>{let r=new globalThis.Uint8Array(await e.arrayBuffer());return{data:Ca(r),type:e.type,name:e.name,lastModified:e.lastModified}},catch:()=>new fe({expected:\"a readable File\"},e,t)})}))}),DB=je(e=>e instanceof globalThis.FormData,{representation:{id:\"effect/schema/FormData\",payload:null},toCode:()=>({runtime:\"Schema.FormData\",Type:\"globalThis.FormData\"}),expected:\"FormData\",toCodecJson:()=>ke()(Be(Ds([H,st([ve({_tag:Fa(\"String\"),value:H}),ve({_tag:Fa(\"File\"),value:UB})])])),mt({decode:e=>{let t=new globalThis.FormData;for(let[r,n]of e)t.append(r,n.value);return g(t)},encode:e=>g(globalThis.Array.from(e.entries()).map(([t,r])=>typeof r==\"string\"?[t,{_tag:\"String\",value:r}]:[t,{_tag:\"File\",value:r}]))}))});function Yte(e){return DB.pipe(J(e,RD))}var LB=Au(globalThis.URLSearchParams,{representation:{id:\"effect/schema/URLSearchParams\",payload:null},toCode:()=>({runtime:\"Schema.URLSearchParams\",Type:\"globalThis.URLSearchParams\"}),expected:\"URLSearchParams\",toCodecJson:()=>ke()(H.annotate({expected:\"a query string that will be decoded as URLSearchParams\"}),Ge({decode:e=>new globalThis.URLSearchParams(e),encode:e=>e.toString()}))});function Qte(e){return LB.pipe(J(e,PD))}var Xte=H.annotate({expected:\"a string that will be decoded as a number\"}).pipe(J(wu,sl)),ere=H.annotate({expected:\"a string that will be decoded as a finite number\"}).pipe(J(Dl,sl)),tre=Q(BC).pipe(J(Ul,Oy)),$B=H.check(AB()),rre=H.annotate({expected:\"a string that will be decoded as a trimmed string\"}).pipe(J($B,lD())),nre=H.annotate({expected:\"a base64 encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,TD)),ore=H.annotate({expected:\"a base64 (URL) encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,vD)),sre=H.annotate({expected:\"a hex encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,kD)),are=H.annotate({expected:\"a URI component encoded string that will be decoded as a UTF-8 string\"}).pipe(J(H,OD)),lv=st([Dl,cB,H]),ire=ve({issues:Be(ve({message:H,path:Ml(Be(st([lv,ve({key:lv})])))}))}),cre=Jn([0,1]).pipe(J(Gm,Ge({decode:e=>e===1,encode:e=>e?1:0}))),KB=H.annotate({expected:\"a base64 encoded string that will be decoded as Uint8Array\",format:\"byte\",contentEncoding:\"base64\"}),$l=Au(globalThis.Uint8Array,{representation:{id:\"effect/schema/Uint8Array\",payload:null},toCode:()=>({runtime:\"Schema.Uint8Array\",Type:\"globalThis.Uint8Array\"}),expected:\"Uint8Array\",toCodecJson:()=>ke()(KB,fC)}),ure=KB.pipe(J($l,fC)),fre=H.annotate({expected:\"a base64 (URL) encoded string that will be decoded as a Uint8Array\"}).pipe(J($l,{decode:V2(),encode:Ay()})),BB=H.annotate({expected:\"a hex encoded string that will be decoded as a Uint8Array\"}).pipe(J($l,{decode:Y2(),encode:Cy()})),jB=mt({decode:(e,t)=>{let r=$1(e);return ge(r)?F(new fe({expected:\"a valid BigDecimal string\"},e,t)):g(r.value)},encode:e=>g(ya(e))}),lre=Zm({order:jf,formatter:e=>ya(e)}),pre=Ym({order:jf,formatter:e=>ya(e)}),dre=Qm({order:jf,formatter:e=>ya(e)}),mre=Xm({order:jf,formatter:e=>ya(e)}),hre=eh({order:jf,formatter:e=>ya(e)}),HB=H.annotate({expected:\"a string that will be decoded as a BigDecimal\"}),zB=je(gw,{representation:{id:\"effect/schema/BigDecimal\",payload:null},toCode:()=>({runtime:\"Schema.BigDecimal\",Type:\"BigDecimal.BigDecimal\",importDeclarations:['import * as BigDecimal from \"effect/BigDecimal\"']}),expected:\"BigDecimal\",toCodecJson:()=>ke()(HB,jB),toFormatter:()=>e=>ya(e)}),xre=HB.pipe(J(zB,jB)),Kl=je(V1,{representation:{id:\"effect/schema/ByteSize\",payload:null},toCode:()=>({runtime:\"Schema.ByteSize\",Type:\"ByteSize.ByteSize\",importDeclarations:['import * as ByteSize from \"effect/ByteSize\"']}),expected:\"ByteSize\",toCodecJson:()=>ke()(Ul.check(vB(globalThis.BigInt(0))),Ge({decode:G1,encode:Lg})),toCodecStringTree:()=>ke()(WB,cC)}),WB=H.annotate({expected:\"a string that will be decoded as a ByteSize\"}),gre=WB.pipe(J(Kl,cC)),yre=Ul.pipe(J(Kl,mD)),Sre=wu.pipe(J(Kl,hD));function pv(e,t){let r=yn()([e,t],([n,o])=>(s,a,i)=>{if(!YI(s))return F(new _t(a,s,i));switch(s._tag){case\"Fail\":return Sr(St(n)(s.error,i),{onSuccess:Cf,onFailure:c=>mn(a,\"error\",c,s,i)});case\"Die\":return Sr(St(o)(s.defect,i),{onSuccess:Tf,onFailure:c=>mn(a,\"defect\",c,s,i)});case\"Interrupt\":return g(s)}},{representation:{id:\"effect/schema/CauseReason\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.CauseReason(${n[0].runtime}, ${n[1].runtime})`,Type:`Cause.Failure<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Cause from \"effect/Cause\"']}),expected:\"Cause.Failure\",toCodec:([n,o])=>ke()(st([ve({_tag:zt(\"Fail\"),error:n}),ve({_tag:zt(\"Die\"),defect:o}),ve({_tag:zt(\"Interrupt\"),fiberId:NS(Dl)})]),Ge({decode:s=>{switch(s._tag){case\"Fail\":return Cf(s.error);case\"Die\":return Tf(s.defect);case\"Interrupt\":return XI(s.fiberId)}},encode:s=>{switch(s._tag){case\"Fail\":return{_tag:\"Fail\",error:s.error};case\"Die\":return{_tag:\"Die\",defect:s.defect};case\"Interrupt\":return{_tag:\"Interrupt\",fiberId:s.fiberId}}}}))});return Q(r.ast,{error:e,defect:t})}function dv(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(pv(n,o));return(a,i,c)=>id(a)?Sr(St(s)(a.reasons,c),{onSuccess:gs,onFailure:u=>mn(i,\"reasons\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/Cause\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.Cause(${n[0].runtime}, ${n[1].runtime})`,Type:`Cause.Cause<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Cause from \"effect/Cause\"']}),expected:\"Cause\",toCodec:([n,o])=>ke()(Be(pv(n,o)),Ge({decode:gs,encode:({reasons:s})=>s}))});return Q(r.ast,{error:e,defect:t})}function BK(e){return ke()(e,Ge({decode:Cw,encode:wt}))}function bre(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>Kg(o)?Sr(St(n)(wt(o),a),{onSuccess:Cw,onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/Chunk\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.Chunk(${r[0].runtime})`,Type:`Chunk.Chunk<${r[0].Type}>`}),expected:\"Chunk\",toCodec:([r])=>BK(Be(r)),toCodecArbitrary:({constraint:r,typeParameters:[n]})=>BK(MS(Be(n),r?.minLength,r?.maxLength)),toEquivalence:([r])=>ww(r)});return Q(t.ast,{value:e})}function qB(){return Rt((e,t)=>Zt(dA(e),{onNone:()=>F(new fe({message:\"Invalid DateTime input\"},e,t)),onSome:r=>g(mA(r))}))}var Ere=Ge({decode:e=>xA(e),encode:e=>e.offset}),JB=mt({decode:(e,t)=>Zt(OU(e),{onNone:()=>F(new fe({expected:\"a valid IANA time zone\"},e,t)),onSome:g}),encode:e=>g(e.id)}),GB=mt({decode:(e,t)=>Zt(_U(e),{onNone:()=>F(new fe({expected:\"a valid time zone\"},e,t)),onSome:g}),encode:e=>g(Zd(e))}),VB=mt({decode:(e,t)=>Zt(dA(e),{onNone:()=>F(new fe({expected:\"a valid UTC DateTime string\"},e,t)),onSome:r=>g(mA(r))}),encode:e=>g(RU(e))}),ZB=mt({decode:(e,t)=>Zt(kU(e),{onNone:()=>F(new fe({expected:\"a valid Zoned DateTime string\"},e,t)),onSome:g}),encode:e=>g(yA(e))}),YB=-864e13,QB=864e13,Ire=YB+840*60*1e3,wre=QB-840*60*1e3,Are=-720*60*1e3,Cre=840*60*1e3,XB=[\"UTC\",\"Europe/London\",\"America/New_York\",\"Asia/Tokyo\",\"Australia/Sydney\"];function ej(e,t,r){let n=Math.max(t,e?.minimum===void 0?t:e.minimum.epochMilliseconds+(e.exclusiveMinimum===!0?1:0)),o=Math.min(r,e?.maximum===void 0?r:e.maximum.epochMilliseconds-(e.exclusiveMaximum===!0?1:0));return n<=o?[n,o]:[t,r]}function kv(e,t){return tn.check(Ls({minimum:e,maximum:t}))}function tj(){return st([kv(Are,Cre),Jn(XB)])}var Bl=je(e=>lA(e)&&CU(e),{representation:{id:\"effect/schema/DateTimeUtc\",payload:null},toCode:()=>({runtime:\"Schema.DateTimeUtc\",Type:\"DateTime.Utc\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.Utc\",toCodecArbitrary:({constraint:e})=>{let[t,r]=ej(e,YB,QB);return Hi()(kv(t,r),le(Vd))},toCodecJson:()=>ke()(H,VB),toFormatter:()=>e=>e.toString()}),Tre=Ll.pipe(J(Bl,{decode:qB(),encode:le(cy)})),vre=H.annotate({expected:\"a string that will be decoded as a DateTime.Utc\"}).pipe(J(Bl,VB)),kre=mt({decode:(e,t)=>mr(p2(e),{onFailure:()=>F(new fe({expected:\"an HTTP date (RFC 9110 \\xA75.6.7)\"},e,t)),onSuccess:g}),encode:e=>g(zA(e))}),Ore=H.annotate({expected:\"an HTTP date string\"}).pipe(J(Bl,kre)),_re=tn.pipe(J(Bl,{decode:qB(),encode:le(gA)})),Rre=je(wU,{representation:{id:\"effect/schema/TimeZoneOffset\",payload:null},toCode:()=>({runtime:\"Schema.TimeZoneOffset\",Type:\"DateTime.TimeZone.Offset\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone.Offset\",toCodecJson:()=>ke()(tn,Ere),toFormatter:()=>e=>Zd(e)}),rj=H.annotate({expected:\"an IANA time zone identifier\"}),nj=je(AU,{representation:{id:\"effect/schema/TimeZoneNamed\",payload:null},toCode:()=>({runtime:\"Schema.TimeZoneNamed\",Type:\"DateTime.TimeZone.Named\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone.Named\",toCodecArbitrary:()=>Hi()(Jn(XB),le(hA)),toCodecJson:()=>ke()(rj,JB),toFormatter:()=>e=>Zd(e)}),Pre=rj.pipe(J(nj,JB)),oj=H.annotate({expected:\"a time zone string (IANA identifier or offset like +03:00)\"}),sj=je(IU,{representation:{id:\"effect/schema/TimeZone\",payload:null},toCode:()=>({runtime:\"Schema.TimeZone\",Type:\"DateTime.TimeZone\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.TimeZone\",toCodecArbitrary:()=>Hi()(tj(),le(e=>typeof e==\"number\"?xA(e):hA(e))),toCodecJson:()=>ke()(oj,GB),toFormatter:()=>e=>Zd(e)}),Mre=oj.pipe(J(sj,GB)),aj=H.annotate({expected:\"a zoned DateTime string (e.g. 2024-01-01T00:00:00.000+00:00[Europe/London])\"}),ij=je(e=>lA(e)&&TU(e),{representation:{id:\"effect/schema/DateTimeZoned\",payload:null},toCode:()=>({runtime:\"Schema.DateTimeZoned\",Type:\"DateTime.Zoned\",importDeclarations:['import * as DateTime from \"effect/DateTime\"']}),expected:\"DateTime.Zoned\",toCodecArbitrary:({constraint:e})=>{let[t,r]=ej(e,Ire,wre);return Hi()(ve({epochMilliseconds:kv(t,r),timeZone:tj()}),le(({epochMilliseconds:n,timeZone:o})=>vU(n,{timeZone:o})))},toCodecJson:()=>ke()(aj,ZB),toFormatter:()=>e=>yA(e),toEquivalence:()=>pA}),Fre=aj.pipe(J(ij,ZB)),bn=(e,t,r,n)=>H.pipe(J(e,mt({decode:(o,s)=>{let a=t(o);return rt(a)?g(a.success):F(new fe({message:a.failure.message},o,s))},encode:o=>g(r(o))}))).annotate({identifier:n}),Cu=je(Cl,{identifier:\"MacAddress\"}),jl=bn(Cu,oK,RT,\"MacAddressFromString\"),rh=je(Ir,{identifier:\"Ipv4Address\"}),Ov=bn(rh,bu,wr,\"Ipv4AddressFromString\"),$S=je(yo,{identifier:\"Ipv6Address\"}),cj=bn($S,Eu,wr,\"Ipv6AddressFromString\"),Wi=je(vT,{identifier:\"IpAddress\"}),Tu=bn(Wi,$i,wr,\"IpAddressFromString\"),ht=(e,t,r,n)=>dB(t,{expected:r})(e).annotate({identifier:n}),Nre=ht(Wi,Tl,\"a multicast address\",\"IpMulticastAddress\"),Ure=ht(Tu,Tl,\"a multicast address\",\"IpMulticastAddressFromString\"),Dre=ht(Cu,Tl,\"a multicast address\",\"MacMulticastAddress\"),Lre=ht(jl,Tl,\"a multicast address\",\"MacMulticastAddressFromString\"),$re=ht(Wi,NT,\"a unicast address\",\"IpUnicastAddress\"),Kre=ht(Tu,NT,\"a unicast address\",\"IpUnicastAddressFromString\"),Bre=ht(Cu,xS,\"a unicast address\",\"MacUnicastAddress\"),jre=ht(jl,xS,\"a unicast address\",\"MacUnicastAddressFromString\"),Hre=ht(rh,yS,\"a broadcast address\",\"Ipv4BroadcastAddress\"),zre=ht(Ov,yS,\"a broadcast address\",\"Ipv4BroadcastAddressFromString\"),Wre=ht(Cu,hS,\"a broadcast address\",\"MacBroadcastAddress\"),qre=ht(jl,hS,\"a broadcast address\",\"MacBroadcastAddressFromString\"),Jre=ht(Wi,FT,\"a loopback address\",\"IpLoopbackAddress\"),Gre=ht(Tu,FT,\"a loopback address\",\"IpLoopbackAddressFromString\"),Vre=ht(Wi,UT,\"a link-local address\",\"IpLinkLocalAddress\"),Zre=ht(Tu,UT,\"a link-local address\",\"IpLinkLocalAddressFromString\"),Yre=ht(Wi,gS,\"an unspecified address\",\"IpUnspecifiedAddress\"),Qre=ht(Tu,gS,\"an unspecified address\",\"IpUnspecifiedAddressFromString\"),Xre=ht(rh,DT,\"a private address\",\"Ipv4PrivateAddress\"),ene=ht(Ov,DT,\"a private address\",\"Ipv4PrivateAddressFromString\"),tne=ht($S,LT,\"a unique-local address\",\"Ipv6UniqueLocalAddress\"),rne=ht(cj,LT,\"a unique-local address\",\"Ipv6UniqueLocalAddressFromString\"),nne=ht(Cu,PT,\"a locally administered address\",\"MacLocallyAdministeredAddress\"),one=ht(jl,PT,\"a locally administered address\",\"MacLocallyAdministeredAddressFromString\"),sne=ht(Cu,MT,\"a universally administered address\",\"MacUniversallyAdministeredAddress\"),ane=ht(jl,MT,\"a universally administered address\",\"MacUniversallyAdministeredAddressFromString\"),uj=je(gK,{identifier:\"Ipv4Interface\"}),ine=bn(uj,IS,jm,\"Ipv4InterfaceFromString\"),fj=je(yK,{identifier:\"Ipv6Interface\"}),cne=bn(fj,wS,jm,\"Ipv6InterfaceFromString\"),lj=je(Km,{identifier:\"IpInterface\"}),une=bn(lj,AS,jm,\"IpInterfaceFromString\"),pj=je(bK,{identifier:\"Ipv4Network\"}),fne=bn(pj,IK,zm,\"Ipv4NetworkFromString\"),dj=je(EK,{identifier:\"Ipv6Network\"}),lne=bn(dj,wK,zm,\"Ipv6NetworkFromString\"),mj=je(Hm,{identifier:\"IpNetwork\"}),pne=bn(mj,AK,zm,\"IpNetworkFromString\"),dne=je(Nm,{identifier:\"InetAddressV4\"}),mne=je(Um,{identifier:\"InetAddressV6\"}),hj=je(kT,{identifier:\"InetAddress\"}),hne=bn(hj,$T,SS,\"InetAddressFromString\"),xj=je(dS,{identifier:\"UnixPathAddress\"}),xne=H.pipe(J(xj,Ge({decode:aK,encode:e=>e.path}))).annotate({identifier:\"UnixPathAddressFromString\"}),gne=je(rK,{identifier:\"SocketAddress\"}),Ua=H.check(Ne(Pa,{expected:\"a normalized domain name\"})).pipe(US(\"~effect/net/Host/DomainName\")).annotate({identifier:\"DomainName\"}),gj=bn(Ua,bS,e=>e,\"DomainNameFromString\"),_v=H.check(Ne(OT,{expected:\"a canonical scoped IPv6 literal\"})).pipe(US(\"~effect/net/NetAddress/ScopedIpv6Literal\")).annotate({identifier:\"ScopedIpv6Literal\"}),yj=bn(_v,Dm,e=>e,\"ScopedIpv6LiteralFromString\"),yne=st([Wi,_v,Ua]).annotate({identifier:\"Host\"}),Sne=st([Tu,yj,gj]).annotate({identifier:\"HostFromString\"}),Sj=je(jT,{identifier:\"HostPort\"}),bne=bn(Sj,uK,HT,\"HostPortFromString\"),Ene=tn.check(Ls({minimum:0,maximum:65535},{expected:\"a port number\"})),Ine=mt({decode:(e,t)=>Zt(K_(e),{onNone:()=>F(new fe({expected:\"a valid Duration string\"},e,t)),onSome:g}),encode:e=>g(globalThis.String(e))}),wne=mt({decode:e=>g(On(e)),encode:(e,t)=>Zt(B_(e),{onNone:()=>F(new fe({expected:\"a Duration representable as a bigint\"},e,t)),onSome:r=>g(r)})}),Ane=Ge({decode:e=>na(e),encode:e=>Nr(e)}),Cne=mt({decode:(e,t)=>Zt(J_(e),{onNone:()=>F(new fe({expected:\"an ISO 8601 duration without years or months\"},e,t)),onSome:g}),encode:(e,t)=>Zt(q_(e),{onNone:()=>F(new fe({expected:\"a finite Duration\"},e,t)),onSome:g})}),vu=je(Fp,{representation:{id:\"effect/schema/Duration\",payload:null},toCode:()=>({runtime:\"Schema.Duration\",Type:\"Duration.Duration\",importDeclarations:['import * as Duration from \"effect/Duration\"']}),expected:\"Duration\",toCodecJson:()=>ke()(st([ve({_tag:zt(\"Infinity\")}),ve({_tag:zt(\"NegativeInfinity\")}),ve({_tag:zt(\"Nanos\"),value:Ul}),ve({_tag:zt(\"Millis\"),value:tn})]),Ge({decode:e=>{switch(e._tag){case\"Infinity\":return ra;case\"NegativeInfinity\":return cf;case\"Nanos\":return On(e.value);case\"Millis\":return na(e.value)}},encode:e=>{switch(e.value._tag){case\"Infinity\":return{_tag:\"Infinity\"};case\"NegativeInfinity\":return{_tag:\"NegativeInfinity\"};case\"Nanos\":return{_tag:\"Nanos\",value:e.value.nanos};case\"Millis\":return{_tag:\"Millis\",value:e.value.millis}}}}))}),Tne=H.annotate({expected:\"a string that will be decoded as a Duration\"}),Rv=Tne.pipe(J(vu,Ine)),vne=Ul.pipe(J(vu,wne)),kne=wu.pipe(J(vu,Ane)),One=H.annotate({expected:\"an ISO 8601 duration string that will be decoded as a Duration\"}).pipe(J(vu,Cne)),_ne=Jn(qT),bj=(e,t)=>H.pipe(J(e,mt({decode:(r,n)=>{let o=t(r);return ae(o)?F(new fe({message:o.failure.message},r,n)):wr(o.success)===r?g(o.success):F(new fe({message:\"expected a canonical address\"},r,n))},encode:r=>g(wr(r))}))),uv=tn.check(Ls({minimum:0,maximum:255})),Ol=tn.check(Ls({minimum:0,maximum:65535})),Ej=tn.check(Ls({minimum:0,maximum:4294967295})),vS=Ej.pipe(J(vu,Ge({decode:uf,encode:hs}))),bo=(e,t)=>je(r=>JT(r)&&r._tag===e,{identifier:`Dns${e.charAt(0)}${e.slice(1).toLowerCase()}Record`,toCodecJson:()=>{let r=Vm(e,t);return ke()(r,mt({decode:(n,o)=>{let{_tag:s,...a}=n,i=mK(e,a);return rt(i)?g(i.success):F(new fe({message:i.failure.message},n,o))},encode:n=>g({...n})}))}}),Ij=bo(\"A\",{address:bj(rh,bu)}),wj=bo(\"AAAA\",{address:bj($S,Eu)}),Aj=bo(\"CAA\",{critical:Gm,tag:H.check(zi(/^[a-z0-9]+$/i)),value:H}),Cj=bo(\"CNAME\",{target:Ua}),Tj=bo(\"MX\",{exchange:Ua,priority:Ol}),vj=bo(\"NAPTR\",{order:Ol,preference:Ol,flags:H,service:H,regexp:H,replacement:Ua}),kj=bo(\"NS\",{host:Ua}),Oj=bo(\"PTR\",{host:th}),_j=bo(\"SOA\",{primary:Ua,admin:th,serial:Ej,refresh:vS,retry:vS,expire:vS,minimum:vS}),Rj=bo(\"SRV\",{target:Ua,port:Ol,priority:Ol,weight:Ol}),Pj=bo(\"TLSA\",{certUsage:uv,selector:uv,matchingType:uv,data:BB}),Mj=bo(\"TXT\",{chunks:FS(H)}),Rne=st([Ij,wj,Aj,Cj,Tj,vj,kj,Oj,_j,Rj,Pj,Mj]).annotate({identifier:\"DnsRecord\"}),Pne=(e,t)=>e===t||e.name===t.name&&e.hash?.name===t.hash?.name&&e.saltLength===t.saltLength,jK=e=>`Digest.${e.name.toLowerCase().replace(\"-\",\"\")}`,Mne=(e,t)=>{if(t.modulusLength===void 0||t.hash===void 0||t._tag===void 0){let o=`${e}.${t.name}`;return t.hash===void 0?o:`{ ...${o}, hash: ${jK(t.hash)} }`}let r=t._tag.charAt(0).toLowerCase()+t._tag.slice(1),n=t.saltLength===void 0?\"\":`, saltLength: ${t.saltLength}`;return`${e}.${r}({ hash: ${jK(t.hash)}, modulusLength: ${t.modulusLength}${n} })`},Fne=e=>{let t={name:e.name};return e.hash!==void 0&&(t.hash=e.hash.name),e.modulusLength!==void 0&&(t.modulusLength=e.modulusLength),e.saltLength!==void 0&&(t.saltLength=e.saltLength),t},$s=(e,t,r,n,o)=>{let s=Mne(t,o),a=cu(()=>`Cannot serialize ${t}.${r} values as JSON, use Schema.${e}FromFormat to read and write keys`);return je(i=>n(i)&&Pne(i.algorithm,o),{expected:`${t}.${r} for ${o.name}`,representation:{id:`effect/crypto/${e}`,payload:Fne(o)},toCode:()=>({runtime:`Schema.${e}(${s})`,Type:`${t}.${r}`,importDeclarations:[`import * as ${t} from \"effect/crypto/${t}\"`,...s.includes(\"Digest.\")?['import * as Digest from \"effect/crypto/Digest\"']:[]]}),toCodecJson:()=>ke()(Nl,{decode:a,encode:a}),toCodecArbitrary:()=>ke()(iB,{decode:a,encode:a}),toFormatter:()=>i=>globalThis.String(i),toEquivalence:()=>(i,c)=>i===c})},kS=(e,t,r)=>new fe({message:e.message,cause:e},t,r),Fj=(e,t,r)=>F(new iu({message:`Schema.${e} only decodes, pass { allowEncode: true } to encode the key`},t,r)),qi=(e,t,r,n)=>$l.pipe(J(t,mt({decode:(o,s)=>Do(r(o),a=>kS(a,o,s)),encode:(o,s)=>n===void 0?Fj(e,o,s):Do(n(o),a=>kS(a,o,s))}))),Ar=rs(H),Nne=ve({kty:Ar,crv:Ar,alg:Ar,use:Ar,key_ops:rs(Be(H)),ext:rs(Gm),k:Ar,x:Ar,y:Ar,d:Ar,n:Ar,e:Ar,p:Ar,q:Ar,dp:Ar,dq:Ar,qi:Ar,oth:rs(Be(ve({r:Ar,d:Ar,t:Ar})))}),Une=e=>e._tag===\"jwk\"?Nne:e.pem?H:$l,Ks=(e,t,r,n,o)=>{let s=o&&r._tag!==\"pkcs1\"&&r._tag!==\"sec1\";return Une(r).pipe(J(t,mt({decode:(a,i)=>C(Mf(()=>Promise.resolve()),()=>Do(n(a),c=>kS(c,a,i))),encode:(a,i)=>s?Do(EU(r,a),c=>kS(c,a,i)):Fj(e,a,i)})))},Pv=e=>$s(\"MacKey\",\"Mac\",\"Key\",Yw,e),Dne=(e,t)=>qi(\"MacKeyFromBytes\",Pv(e),r=>Qw(e,r),t?.allowEncode===!0?Xw:void 0),Lne=(e,t,r)=>Ks(\"MacKeyFromFormat\",Pv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Mv=e=>$s(\"AeadKey\",\"Aead\",\"Key\",Nw,e),$ne=(e,t)=>qi(\"AeadKeyFromBytes\",Mv(e),r=>Uw(e,r),t?.allowEncode===!0?Dw:void 0),Kne=(e,t,r)=>Ks(\"AeadKeyFromFormat\",Mv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Fv=e=>$s(\"CipherKey\",\"Cipher\",\"Key\",$w,e),Bne=(e,t)=>qi(\"CipherKeyFromBytes\",Fv(e),r=>Kw(e,r),t?.allowEncode===!0?Bw:void 0),jne=(e,t,r)=>Ks(\"CipherKeyFromFormat\",Fv(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Nv=e=>$s(\"SignaturePublicKey\",\"Signature\",\"PublicKey\",iU,e),Hne=e=>qi(\"SignaturePublicKeyFromBytes\",Nv(e),t=>uU(e,t),cA),zne=(e,t)=>Ks(\"SignaturePublicKeyFromFormat\",Nv(t),e,r=>ay(e,t,r),!0),Uv=e=>$s(\"SignaturePrivateKey\",\"Signature\",\"PrivateKey\",aA,e),Wne=(e,t)=>qi(\"SignaturePrivateKeyFromBytes\",Uv(e),r=>cU(e,r),t?.allowEncode===!0?cA:void 0),qne=(e,t,r)=>Ks(\"SignaturePrivateKeyFromFormat\",Uv(t),e,n=>iy(e,t,n),r?.allowEncode===!0),Dv=e=>$s(\"KeyAgreementPublicKey\",\"KeyAgreement\",\"PublicKey\",FN,e),Jne=e=>qi(\"KeyAgreementPublicKeyFromBytes\",Dv(e),t=>UN(e,t),Jw),Gne=(e,t)=>Ks(\"KeyAgreementPublicKeyFromFormat\",Dv(t),e,r=>ay(e,t,r),!0),Lv=e=>$s(\"KeyAgreementPrivateKey\",\"KeyAgreement\",\"PrivateKey\",Ww,e),Vne=(e,t)=>qi(\"KeyAgreementPrivateKeyFromBytes\",Lv(e),r=>NN(e,r),t?.allowEncode===!0?Jw:void 0),Zne=(e,t,r)=>Ks(\"KeyAgreementPrivateKeyFromFormat\",Lv(t),e,n=>iy(e,t,n),r?.allowEncode===!0),$v=e=>$s(\"KeyWrapKey\",\"KeyWrap\",\"Key\",eA,e),Yne=(e,t)=>qi(\"KeyWrapKeyFromBytes\",$v(e),r=>oA(e,r),t?.allowEncode===!0?sA:void 0),Qne=(e,t,r)=>Ks(\"KeyWrapKeyFromFormat\",$v(t),e,n=>Gd(e,t,n),r?.allowEncode===!0),Nj=e=>$s(\"KeyWrapPublicKey\",\"KeyWrap\",\"PublicKey\",tU,e),Xne=(e,t)=>Ks(\"KeyWrapPublicKeyFromFormat\",Nj(t),e,r=>ay(e,t,r),!0),Uj=e=>$s(\"KeyWrapPrivateKey\",\"KeyWrap\",\"PrivateKey\",tA,e),eoe=(e,t,r)=>Ks(\"KeyWrapPrivateKeyFromFormat\",Uj(t),e,n=>iy(e,t,n),r?.allowEncode===!0);function toe(e,t,r){let n=yn()([e,t,r],([o,s,a])=>{let i=dv(s,a);return(c,u,f)=>{if(!fd(c))return F(new _t(u,c,f));switch(c._tag){case\"Success\":return Sr(St(o)(c.value,f),{onSuccess:Vr,onFailure:p=>mn(u,\"value\",p,c,f)});case\"Failure\":return Sr(St(i)(c.cause,f),{onSuccess:Fn,onFailure:p=>mn(u,\"cause\",p,c,f)})}}},{representation:{id:\"effect/schema/Exit\",payload:null},toCode:({typeParameters:o})=>({runtime:`Schema.Exit(${o[0].runtime}, ${o[1].runtime}, ${o[2].runtime})`,Type:`Exit.Exit<${o[0].Type}, ${o[1].Type}, ${o[2].Type}>`,importDeclarations:['import * as Exit from \"effect/Exit\"']}),expected:\"Exit\",toCodec:([o,s,a])=>ke()(st([ve({_tag:zt(\"Success\"),value:o}),ve({_tag:zt(\"Failure\"),cause:dv(s,a)})]),Ge({decode:i=>i._tag===\"Success\"?Vr(i.value):Fn(i.cause),encode:i=>ut(i)?{_tag:\"Success\",value:i.value}:{_tag:\"Failure\",cause:i.cause}}))});return Q(n.ast,{value:e,error:t,defect:r})}function HK(e,t,r){return ve({type:zt(e),nodes:Be(ve({index:ts,data:t})),edges:Be(ve({index:ts,source:ts,target:ts,data:r}))})}function zK(e,t){let r=-1,n=new Set;for(let o=0;o{let o=om(r),s=om(n);if(o.type!==s.type||o.nodes.length!==s.nodes.length||o.edges.length!==s.edges.length)return!1;for(let a=0;a{if(n===null)return gy({type:e,nodes:[],edges:[]});let o=n.nodes.map((s,a)=>({index:a,data:s}));return gy({type:e,nodes:o,edges:n.edges.map(([s,a,i],c)=>({index:c,source:s%o.length,target:a%o.length,data:i}))})}))}function soe(e,t,r){let n=yn()([t,r],([o,s])=>{let a=HK(e,o,s);return(i,c,u)=>!VA(i)||i.mutable||i.type!==e?F(new _t(c,i,u)):C(St(a)(om(i),u),f=>zK(f,u))},{representation:{id:\"effect/schema/Graph\",payload:e},toCode:({typeParameters:o})=>({runtime:`Schema.Graph(${K(e)}, ${o[0].runtime}, ${o[1].runtime})`,Type:`Graph.Graph<${o[0].Type}, ${o[1].Type}, ${K(e)}>`,importDeclarations:['import * as Graph from \"effect/Graph\"']}),expected:`an immutable ${e} Graph`,toCodec:([o,s])=>ke()(HK(e,o,s),mt({decode:zK,encode:(a,i)=>roe(a,e,i)})),toCodecArbitrary:({typeParameters:[o,s]})=>ooe(e,o,s),toEquivalence:([o,s])=>noe(o,s)});return Q(n.ast,{type:e,node:t,edge:r})}function WK(e){return ke()(e,Ge({decode:kA,encode:em}))}function aoe(e,t){let r=yn()([e,t],([n,o])=>{let s=Be(Ds([n,o]));return(a,i,c)=>BU(a)?Sr(St(s)(em(a),c),{onSuccess:kA,onFailure:u=>mn(i,\"entries\",u,a,c)}):F(new _t(i,a,c))},{representation:{id:\"effect/schema/HashMap\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.HashMap(${n[0].runtime}, ${n[1].runtime})`,Type:`HashMap.HashMap<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as HashMap from \"effect/HashMap\"']}),expected:\"HashMap\",toCodec:([n,o])=>WK(Be(Ds([n,o]))),toCodecArbitrary:({constraint:n,typeParameters:[o,s]})=>WK(MS(Be(Ds([o,s])).check(RB()),n?.minSize,n?.maxSize)),toEquivalence:([n,o])=>_h(n,o)});return Q(r.ast,{key:e,value:t})}function qK(e){return ke()(e,Ge({decode:RA,encode:wt}))}function ioe(e){let t=yn()([e],([r])=>{let n=Be(r);return(o,s,a)=>qU(o)?Sr(St(n)(wt(o),a),{onSuccess:RA,onFailure:i=>mn(s,\"values\",i,o,a)}):F(new _t(s,o,a))},{representation:{id:\"effect/schema/HashSet\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.HashSet(${r[0].runtime})`,Type:`HashSet.HashSet<${r[0].Type}>`}),expected:\"HashSet\",toCodec:([r])=>qK(Be(r)),toCodecArbitrary:({constraint:r,typeParameters:[n]})=>qK(MS(Be(n).check(Tv()),r?.minSize,r?.maxSize)),toEquivalence:([r])=>hp(r)});return Q(t.ast,{value:e})}function ku(e){let t=yn()([e],([r])=>(n,o,s)=>rf(n)?ge(n)?li:Sr(St(r)(n.value,s),{onSuccess:_,onFailure:a=>mn(o,\"value\",a,n,s)}):F(new _t(o,n,s)),{representation:{id:\"effect/schema/Option\",payload:null},toCode:({typeParameters:r})=>({runtime:`Schema.Option(${r[0].runtime})`,Type:`Option.Option<${r[0].Type}>`,importDeclarations:['import * as Option from \"effect/Option\"']}),expected:\"Option\",toCodec:([r])=>ke()(st([ve({_tag:zt(\"Some\"),value:r}),ve({_tag:zt(\"None\")})]),Ge({decode:n=>n._tag===\"None\"?v():_(n.value),encode:n=>Ce(n)?{_tag:\"Some\",value:n.value}:{_tag:\"None\"}}))});return Q(t.ast,{value:e})}function coe(e){return yv(e).pipe(J(ku(Sn(e)),ED()))}function uoe(e){return NS(e).pipe(J(ku(Sn(e)),ID()))}function foe(e,t){return lB(e).pipe(J(ku(Sn(e)),wD(t)))}var Dj=je(YU,{representation:{id:\"effect/http/Cookie\",payload:null},toCode:()=>({runtime:\"Schema.Cookie\",Type:\"Cookies.Cookie\",importDeclarations:['import * as Cookies from \"effect/http/Cookies\"']}),expected:\"Cookie\"}),Lj=je(ZU,{representation:{id:\"effect/http/Cookies\",payload:null},toCode:()=>({runtime:\"Schema.Cookies\",Type:\"Cookies.Cookies\",importDeclarations:['import * as Cookies from \"effect/http/Cookies\"']}),expected:\"Cookies\",toCodecJson:()=>ke()(Be(H),Ge({decode:QU,encode:n2})),toCodecIso:()=>ke()(Na(H,Dj),Ge({decode:DA,encode:e=>e.cookies}))}),loe=Lj.pipe(J(Na(H,H),Ge({decode:r2,encode:e=>LA(globalThis.Object.entries(e).map(([t,r])=>t2(t,r)))}))),poe=je(c2,{representation:{id:\"effect/http/Headers\",payload:null},toCode:()=>({runtime:\"Schema.Headers\",Type:\"Headers.Headers\",importDeclarations:['import * as Headers from \"effect/http/Headers\"']}),expected:\"Headers\",toEquivalence:()=>HA,toCodec:()=>ke()(Na(H,H),Ge({decode:u2,encode:e=>({...e})}))}),$j=st([ve({_tag:Fa(\"Duration\"),duration:vu.check(Ne(e=>sn(e)&&!hx(e),{expected:\"a finite, non-negative duration\"}))}),ve({_tag:Fa(\"DateTime\"),dateTime:Bl})]),doe=mt({decode:(e,t)=>mr(d2(e),{onFailure:()=>F(new fe({expected:\"whole non-negative seconds or an HTTP date (RFC 9110 \\xA710.2.3)\"},e,t)),onSuccess:g}),encode:e=>g(m2(e))}),moe=H.annotate({expected:\"a Retry-After header value\"}).pipe(J($j,doe)),Kv=je(qA,{representation:{id:\"effect/http/UrlParams\",payload:null},toCode:()=>({runtime:\"Schema.UrlParams\",Type:\"UrlParams.UrlParams\",importDeclarations:['import * as UrlParams from \"effect/http/UrlParams\"']}),expected:\"UrlParams\",toEquivalence:()=>JA,toCodec:()=>ke()(Be(Ds([H,H])),Ge({decode:xy,encode:e=>e.params.map(([t,r])=>[t,nm(r)])}))}),hoe=(e,t)=>Kv.pipe(J(vv(Nl,t),mt({decode:r=>Zt(b2(r,e),{onNone:()=>F(new Ot([e],new Ni(void 0))),onSome:g}),encode:r=>g(xy([[e,r]]))}))),xoe=Kv.pipe(J(Na(H,st([H,FS(H)])),Ge({decode:E2,encode:y2})));function goe(e){return rs(e).pipe(J(ku(Sn(e)),AD()))}function yoe(e){return Ml(e).pipe(J(ku(Sn(e)),CD()))}function Soe(e,t){let r=t===void 0?\"omit\":t.onNoneEncoding,n=r===null?null:void 0;return Ml(yv(e)).pipe(J(ku(Sn(e)),ky({decode:o=>o.pipe(hc(kh),_),encode:r===\"omit\"?mc:o=>_(Tp(mc(o),()=>n))})))}function KS(e,t){let r=typeof t?.label==\"string\"?t.label:void 0,n=t?.disallowJsonEncode===!0,o=r!==void 0?n?{label:r,disallowJsonEncode:!0}:{label:r}:n?{disallowJsonEncode:!0}:void 0,s=r!==void 0?St(zt(r)):void 0,a=yn()([e],([i])=>(c,u,f)=>{if(Xf(c)){let p=s!==void 0?$f(s(c.label,f),d=>new Ot([\"label\"],d)):ie;return Ct(p,()=>Sr(St(i)(Mi(c),f),{onSuccess:d=>Ta(d,{label:c.label}),onFailure:()=>new Ht(u,[new Ot([\"value\"],new fe(void 0,c,f))],c,f)}))}return F(new _t(u,c,f))},{representation:{id:\"effect/schema/Redacted\",payload:o??null},toCode:({typeParameters:i})=>({runtime:o!==void 0?`Schema.Redacted(${i[0].runtime}, ${K(o)})`:`Schema.Redacted(${i[0].runtime})`,Type:`Redacted.Redacted<${i[0].Type}>`,importDeclarations:['import * as Redacted from \"effect/Redacted\"']}),expected:\"Redacted\",toCodecJson:([i])=>ke()(i,{decode:le(c=>Ta(c,{label:r})),encode:n?cu(c=>\"Cannot serialize Redacted\"+(Ce(c)&&typeof c.value.label==\"string\"?` with label: \"${c.value.label}\"`:\"\")):le(Mi)}),toEquivalence:([i])=>a2(i)});return Q(a.ast,{value:e})}function boe(e,t){return J(KS(Sn(e),{label:t?.label,disallowJsonEncode:t?.disallowEncode}),{decode:le(r=>Ta(r,{label:t?.label})),encode:t?.disallowEncode?cu(r=>\"Cannot encode Redacted\"+(Ce(r)&&typeof r.value.label==\"string\"?` with label: \"${r.value.label}\"`:\"\")):le(Mi)})(e)}function Eoe(e,t){let r=yn()([e,t],([n,o])=>(s,a,i)=>{if(!y_(s))return F(new _t(a,s,i));switch(s._tag){case\"Success\":return Sr(ZC(n)(s.success,i),{onSuccess:j,onFailure:c=>mn(a,\"success\",c,s,i)});case\"Failure\":return Sr(ZC(o)(s.failure,i),{onSuccess:q,onFailure:c=>mn(a,\"failure\",c,s,i)})}},{representation:{id:\"effect/schema/Result\",payload:null},toCode:({typeParameters:n})=>({runtime:`Schema.Result(${n[0].runtime}, ${n[1].runtime})`,Type:`Result.Result<${n[0].Type}, ${n[1].Type}>`,importDeclarations:['import * as Result from \"effect/Result\"']}),expected:\"Result\",toCodec:([n,o])=>ke()(st([ve({_tag:zt(\"Success\"),success:n}),ve({_tag:zt(\"Failure\"),failure:o})]),Ge({decode:s=>s._tag===\"Success\"?j(s.success):q(s.failure),encode:s=>rt(s)?{_tag:\"Success\",success:s.success}:{_tag:\"Failure\",failure:s.failure}}))});return Q(r.ast,{success:e,failure:t})}var Kj=(e,t)=>mt({decode:(r,n)=>$f(jc(e(r)),o=>new fe({message:o.message},r,n)),encode:r=>g(t(r))}),Bj=ve({major:ts,minor:ts,patch:ts,prerelease:Be(st([ts,H.check(zi(/^[0-9]*[A-Za-z-][0-9A-Za-z-]*$/))]))}),jj=Kj(OK,Iu),Hj=H.annotate({expected:\"a string that will be decoded as a SemVer\"}),zj=je(rv,{representation:{id:\"effect/schema/SemVer\",payload:null},toCode:()=>({runtime:\"Schema.SemVer\",Type:\"SemVer.SemVer\",importDeclarations:['import * as SemVer from \"effect/SemVer\"']}),expected:\"SemVer\",toCodecArbitrary:()=>Hi()(ve({...Bj.fields,build:Be(H.check(zi(/^[0-9A-Za-z-]+$/)))}),le(nv)),toCodecJson:()=>ke()(Hj,jj),toFormatter:()=>Iu}),Ioe=Hj.pipe(J(zj,jj)),Wj=Kj(cv,ji),qj=H.annotate({expected:\"a string that will be decoded as a SemVer range\"}),Jj=je(iv,{representation:{id:\"effect/schema/SemVerRange\",payload:null},toCode:()=>({runtime:\"Schema.SemVerRange\",Type:\"SemVerRange.SemVerRange\",importDeclarations:['import * as SemVerRange from \"effect/SemVerRange\"']}),expected:\"SemVerRange\",toCodecArbitrary:()=>Hi()(Be(Be(ve({operator:Jn([\"\",\"=\",\"<\",\"<=\",\">\",\">=\",\"~\",\"^\"]),version:Bj})).check(wv(1))),le(e=>PK(e.map(t=>t.map(({operator:r,version:n})=>`${r}${Iu(nv(n))}`).join(\" \")).join(\" || \")))),toCodecJson:()=>ke()(qj,Wj),toFormatter:()=>ji}),woe=qj.pipe(J(Jj,Wj)),Aoe=globalThis.Symbol.for(\"immer-draftable\"),mv={};function Bv(e,t,r,n,o){let s=Toe(r,t,n),a=Gj(t),i=class extends e{constructor(...[c,u]){let p=u?.[\"~payload\"],d=p?.token===mv?p.value:r.make(c??{},u);super(d,{...u,disableChecks:!0,\"~payload\":{token:mv,value:d}})}static[qm]=qm;get[a](){return a}static[Aoe]=!0;static identifier=t;static fields=r.fields;static get ast(){return s(this).ast}static pipe(){return te(this,arguments)}static rebuild(c){return s(this).rebuild(c)}static make(c,u){return zL(Mt(s(this).ast),c??{},u,f=>jv(this,f))}static makeOption(c,u){return Gy(s(this))(c??{},u)}static makeEffect(c,u){return s(this).makeEffect(c??{},u)}static annotate(c){return this.rebuild(Go(this.ast,c))}static annotateKey(c){return this.rebuild(Tm(this.ast,c))}static check(...c){return this.rebuild(Us(this.ast,c))}static extend(c){return(u,f)=>{let p=nh(u)?u:ve(u),d={...r.fields,...p.fields},m=Ny(d,r.ast.checks,{identifier:c});return Bv(this,c,gv(Us(m,p.ast.checks),d),f,o)}}static mapFields(c,u){return r.mapFields(c,u)}};return o!==void 0&&Object.assign(i.prototype,o(t)),i}function jv(e,t){return new e(t,{\"~payload\":{token:mv,value:t}})}function Coe(e){return new Ke(le(t=>jv(e,t)),hn())}function Gj(e){return`~effect/Schema/Class/${e}`}function Toe(e,t,r){let n;return o=>{if(n!==void 0)return n;let s=Gj(t),a=u=>u instanceof o||A(u,s),i=Coe(o),c=Q(new ll([e.ast],()=>(u,f,p)=>a(u)?g(u):F(new _t(f,u,p)),{identifier:t,[Sy]:([u])=>({isConstructed:a,link:new Tt(u,i)}),toCodec:([u])=>new Tt(u.ast,i),toEquivalence:([u])=>u,toFormatter:([u])=>f=>`${o.identifier}(${u(f)})`,[sm]:cl(e.ast),...r}));return n=J(c,i)(e)}}function nh(e){return RS(e)}var Vj=e=>(t,r)=>{let n=nh(t)?t:ve(t);return Bv(xx,e,n,r,o=>({toString(){return`${o}(${K({...this})})`}}))},voe=e=>(t,r,n)=>{let o=nh(r)?r.mapFields(s=>({_tag:Fa(t),...s}),{unsafePreserveChecks:!0}):Vm(t,r);return Vj(e??t)(o,n)},Zj=e=>(t,r)=>{let n=nh(t)?t:ve(t);return Bv(Ip,e,n,r,s=>({name:s}))},koe=e=>(t,r,n)=>{let o=nh(r)?r.mapFields(s=>({_tag:Fa(t),...s}),{unsafePreserveChecks:!0}):Vm(t,r);return Zj(e??t)(o,n)};function Ooe(e){return t=>t.annotate({toFormatter:e})}function _oe(e,t){return H$(e.ast,t)}function Roe(e){return t=>t.annotate({toEquivalence:e})}function Poe(e){return gT(e.ast)}function Moe(e,t){return Pm(e.ast,t)}function Foe(e,t){let r=Pm(yl(e.ast),t);return cS(r,t)}var Noe=tS,Uoe=rS,oh=nS,Doe=p$,Loe=x$;function $oe(e,t){return L$(e,t)}function Koe(e){return Z$(e)}function Boe(e){return Y$(e)}function joe(e){return Q$(e)}function Hoe(e,t){return r=>Q(Go(r.ast,{toCodecIso:()=>new Tt(e.ast,vy(t))}),{schema:r})}function zoe(e){return D$(e)}function Woe(e){let t=pB(()=>r),r=st([e,Be(t),Na(H,t)]);return r}var BS=Q(Go(ul,{toCode:()=>({runtime:\"Schema.Json\",Type:\"Schema.Json\"})})),qoe=Na(H,BS),Joe=ve({message:H,name:rs(H),stack:rs(H),cause:rs(BS)}),Goe=Q(Go(EL,{toCode:()=>({runtime:\"Schema.MutableJson\",Type:\"Schema.MutableJson\"})}));function Voe(e){return va(e.ast)}function Zoe(e){return e.ast.context?.annotations}var rn=HI,Yj=MM;var Qj=\"~effect/MutableRef\",Yoe={[Qj]:Qj,...kr,toJSON(){return{_id:\"MutableRef\",current:qt(this.current)}}},Hl=e=>{let t=Object.create(Yoe);return t.current=e,t};var Xj=e=>e.current;var HS=l(2,(e,t)=>(e.current=t,e));var Qoe=\"~effect/PubSub\";var Xoe=\"~effect/PubSub/Subscription\",JS=e=>Y(()=>sse(e.atomicPubSub(),new Map,so(),rn(!1),Hl(!1),e.strategy(),Hl(v()))),GS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new zS}),VS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new WS}),ZS=e=>JS({atomicPubSub:()=>tk(e),strategy:()=>new ek}),YS=e=>JS({atomicPubSub:()=>eH(e),strategy:()=>new WS}),tk=e=>{let t=typeof e==\"number\"?{capacity:e}:e;if(ase(t.capacity),t.capacity===1/0)return eH(t);let r=t.replay&&t.replay>0?new qS(Math.ceil(t.replay)):void 0;return t.capacity===1?new Gv(r):LF(t.capacity)===t.capacity?new qv(t.capacity,r):new zv(t.capacity,r)},eH=e=>{let t=e?.replay;return new Zv(t&&t>0?new qS(Math.ceil(t)):void 0)};var sh=e=>ma(Un(t=>(HS(e.shutdownFlag,!0),Xe(e.scope,ld(t.id)).pipe(Yr(e.strategy.shutdown),Cg(e.shutdownHook.open),pi)))),QS=l(2,(e,t)=>Y(()=>ese(e,t))),ese=l(2,(e,t)=>{if(e.shutdownFlag.current||Ce(e.ended.current))return!1;if(HS(e.ended,_(t)),e.strategy instanceof zS)for(let[n,o,s]of yi(e.strategy.publishers))s&&ys(o,Vr(!1));let r=Vr(t);for(let n of e.subscribers.values())for(let o of n){let s;for(;(s=Gc(o))!==br;)ys(s,r)}return e.subscribers.clear(),!0});var XS=l(2,(e,t)=>L(()=>e.shutdownFlag.current||Ce(e.ended.current)?g(!1):e.pubsub.publish(t)?(e.strategy.completeSubscribersUnsafe(e.pubsub,e.subscribers),g(!0)):e.strategy.handleSurplus(e.pubsub,e.subscribers,[t],e.shutdownFlag,e.ended)));var tH=l(2,(e,t)=>L(()=>{if(e.shutdownFlag.current||Ce(e.ended.current))return g(!1);let r=e.pubsub.publishAll(t);return e.strategy.completeSubscribersUnsafe(e.pubsub,e.subscribers),r.length===0?g(!0):e.strategy.handleSurplus(e.pubsub,e.subscribers,r,e.shutdownFlag,e.ended)})),ah=e=>ma(Od(t=>{let r=Me(t,Zr),n=tr(e.scope),o=ose(e.pubsub,e.subscribers,e.strategy,e.ended);return xr(n,tse(o)).pipe(Yr(bs(r,s=>Xe(n,s))),jt(o))})),tse=e=>ma(Un(t=>(HS(e.shutdownFlag,!0),ui(yi(e.pollers),r=>u0(r,t.id),{discard:!0,concurrency:\"unbounded\"}).pipe(Qr(()=>Y(()=>{e.subscribers.delete(e.subscription),e.subscription.unsubscribe(),e.replayWindow.close(),e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers)})),Cg(e.shutdownHook.open),pi)))),eb=e=>L(()=>{if(e.shutdownFlag.current)return co;if(e.replayWindow.remaining>0){let r=e.replayWindow.take();return g(r)}let t=e.pollers.length===0?e.subscription.poll():br;return t===br?nH(e):(e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),g(t))}),rH=e=>L(function t(r){if(e.shutdownFlag.current)return co;let n=e.pollers.length===0?e.subscription.pollUpTo(Number.POSITIVE_INFINITY):[];return r&&(n=r.concat(n)),e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),e.replayWindow.remaining>0?g(e.replayWindow.takeAll().concat(n)):Mr(n)?g(n):C(nH(e),o=>t([o]))}),nH=e=>Ff(t=>{if(e.shutdownFlag.current)return t(co);if(Ce(e.ended.current)){let o=e.pollers.length===0?e.subscription.poll():br;return o!==br?(e.strategy.onPubSubEmptySpaceUnsafe(e.pubsub,e.subscribers),t(g(o))):t(g(e.ended.current.value))}let r=Mc(),n=e.subscribers.get(e.subscription);return n||(n=new Set,e.subscribers.set(e.subscription,n)),n.add(e.pollers),Bo(e.pollers,r),e.strategy.completePollersUnsafe(e.pubsub,e.subscribers,e.subscription,e.pollers),r.effect?t(r.effect):(r.resumes=[t],Y(()=>b1(e.pollers,r)))});var Ft=Symbol.for(\"effect/PubSub/AbsentValue\"),rse=(e,t,r)=>{e.has(t)||e.set(t,new Set),e.get(t).add(r)},nse=(e,t,r)=>{if(!e.has(t))return;let n=e.get(t);n.delete(r),n.size===0&&e.delete(t)},ose=(e,t,r,n)=>new Qv(e,t,e.subscribe(),xa(),rn(!1),Hl(!1),r,e.replayWindow(),n),zv=class{array;replayIndices;publisherIndex=0;subscribers;subscriberCount=0;subscribersIndex=0;capacity;replayBuffer;constructor(t,r){this.capacity=t,this.replayBuffer=r,this.array=Array.from({length:t}),this.replayIndices=r?Array.from({length:t}):[],this.subscribers=Array.from({length:t})}replayWindow(){return this.replayBuffer?new zl(this.replayBuffer):tb}isEmpty(){return this.publisherIndex===this.subscribersIndex}isFull(){return this.publisherIndex===this.subscribersIndex+this.capacity}size(){return this.publisherIndex-this.subscribersIndex}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);if(this.subscriberCount!==0){let n=this.publisherIndex%this.capacity;this.array[n]=t,r!==void 0&&(this.replayIndices[n]=r),this.subscribers[n]=this.subscriberCount,this.publisherIndex+=1}return!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t),n=r.length,o=this.publisherIndex-this.subscribersIndex,s=this.capacity-o,a=Math.min(n,s);if(a===0)return r;let i=0,c=this.publisherIndex+a;for(;this.publisherIndex!==c;){let u=r[i++],f=this.publisherIndex%this.capacity;this.array[f]=u;let p=this.replayBuffer?.offer(u);p!==void 0&&(this.replayIndices[f]=p),this.subscribers[f]=this.subscriberCount,this.publisherIndex+=1}return r.slice(i)}slide(){if(this.subscribersIndex!==this.publisherIndex){let t=this.subscribersIndex%this.capacity,r=this.array[t];this.array[t]=Ft,this.subscribers[t]=0,this.subscribersIndex+=1,this.replayBuffer?.slide(r,this.replayIndices[t])}}subscribe(){return this.subscriberCount+=1,new Wv(this,this.publisherIndex,!1)}},Wv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.publisherIndex===this.subscriberIndex||this.self.publisherIndex===this.self.subscribersIndex}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;if(this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex),this.subscriberIndex!==this.self.publisherIndex){let t=this.subscriberIndex%this.self.capacity,r=this.self.array[t];return this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1,r}return br}pollUpTo(t){if(t=It(t),this.unsubscribed)return[];this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);let r=this.self.publisherIndex-this.subscriberIndex,n=Math.min(t,r);if(n<=0)return[];let o=[],s=this.subscriberIndex+n;for(;this.subscriberIndex!==s;){let a=this.subscriberIndex%this.self.capacity,i=this.self.array[a];this.self.subscribers[a]-=1,this.self.subscribers[a]===0&&(this.self.array[a]=Ft,this.self.subscribersIndex+=1),o.push(i),this.subscriberIndex+=1}return o}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.subscriberCount-=1,this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);this.subscriberIndex!==this.self.publisherIndex;){let t=this.subscriberIndex%this.self.capacity;this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1}}},qv=class{array;replayIndices;mask;publisherIndex=0;subscribers;subscriberCount=0;subscribersIndex=0;capacity;replayBuffer;constructor(t,r){this.capacity=t,this.replayBuffer=r,this.array=Array.from({length:t}),this.replayIndices=r?Array.from({length:t}):[],this.mask=t-1,this.subscribers=Array.from({length:t})}replayWindow(){return this.replayBuffer?new zl(this.replayBuffer):tb}isEmpty(){return this.publisherIndex===this.subscribersIndex}isFull(){return this.publisherIndex===this.subscribersIndex+this.capacity}size(){return this.publisherIndex-this.subscribersIndex}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);if(this.subscriberCount!==0){let n=this.publisherIndex&this.mask;this.array[n]=t,r!==void 0&&(this.replayIndices[n]=r),this.subscribers[n]=this.subscriberCount,this.publisherIndex+=1}return!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t),n=r.length,o=this.publisherIndex-this.subscribersIndex,s=this.capacity-o,a=Math.min(n,s);if(a===0)return r;let i=0,c=this.publisherIndex+a;for(;this.publisherIndex!==c;){let u=r[i++],f=this.publisherIndex&this.mask;this.array[f]=u;let p=this.replayBuffer?.offer(u);p!==void 0&&(this.replayIndices[f]=p),this.subscribers[f]=this.subscriberCount,this.publisherIndex+=1}return r.slice(i)}slide(){if(this.subscribersIndex!==this.publisherIndex){let t=this.subscribersIndex&this.mask,r=this.array[t];this.array[t]=Ft,this.subscribers[t]=0,this.subscribersIndex+=1,this.replayBuffer?.slide(r,this.replayIndices[t])}}subscribe(){return this.subscriberCount+=1,new Jv(this,this.publisherIndex,!1)}},Jv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.publisherIndex===this.subscriberIndex||this.self.publisherIndex===this.self.subscribersIndex}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;if(this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex),this.subscriberIndex!==this.self.publisherIndex){let t=this.subscriberIndex&this.self.mask,r=this.self.array[t];return this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1,r}return br}pollUpTo(t){if(t=It(t),this.unsubscribed)return[];this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);let r=this.self.publisherIndex-this.subscriberIndex,n=Math.min(t,r);if(n<=0)return[];let o=[],s=this.subscriberIndex+n;for(;this.subscriberIndex!==s;){let a=this.subscriberIndex&this.self.mask,i=this.self.array[a];this.self.subscribers[a]-=1,this.self.subscribers[a]===0&&(this.self.array[a]=Ft,this.self.subscribersIndex+=1),o.push(i),this.subscriberIndex+=1}return o}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.subscriberCount-=1,this.subscriberIndex=Math.max(this.subscriberIndex,this.self.subscribersIndex);this.subscriberIndex!==this.self.publisherIndex;){let t=this.subscriberIndex&this.self.mask;this.self.subscribers[t]-=1,this.self.subscribers[t]===0&&(this.self.array[t]=Ft,this.self.subscribersIndex+=1),this.subscriberIndex+=1}}},Gv=class{publisherIndex=0;subscriberCount=0;subscribers=0;value=Ft;replayIndex=0;capacity=1;replayBuffer;constructor(t){this.replayBuffer=t}replayWindow(){return this.replayBuffer?new zl(this.replayBuffer):tb}pipe(){return te(this,arguments)}isEmpty(){return this.subscribers===0}isFull(){return!this.isEmpty()}size(){return this.isEmpty()?0:1}publish(t){if(this.isFull())return!1;let r=this.replayBuffer?.offer(t);return this.subscriberCount!==0&&(this.value=t,r!==void 0&&(this.replayIndex=r),this.subscribers=this.subscriberCount,this.publisherIndex+=1),!0}publishAll(t){if(this.subscriberCount===0)return this.replayBuffer&&this.replayBuffer.offerAll(t),[];let r=wt(t);return r.length===0?r:this.publish(r[0])?r.slice(1):r}slide(){if(this.isFull()){let t=this.value;this.subscribers=0,this.value=Ft,this.replayBuffer?.slide(t,this.replayIndex)}}subscribe(){return this.subscriberCount+=1,new Vv(this,this.publisherIndex,!1)}},Vv=class{self;subscriberIndex;unsubscribed;constructor(t,r,n){this.self=t,this.subscriberIndex=r,this.unsubscribed=n}isEmpty(){return this.unsubscribed||this.self.subscribers===0||this.subscriberIndex===this.self.publisherIndex}size(){return this.isEmpty()?0:1}poll(){if(this.isEmpty())return br;let t=this.self.value;return this.self.subscribers-=1,this.self.subscribers===0&&(this.self.value=Ft),this.subscriberIndex=this.self.publisherIndex,t}pollUpTo(t){return It(t)<1||this.isEmpty()?[]:[this.poll()]}unsubscribe(){this.unsubscribed||(this.unsubscribed=!0,this.self.subscriberCount-=1,this.self.subscribers!==0&&this.subscriberIndex!==this.self.publisherIndex&&(this.self.subscribers-=1,this.self.subscribers===0&&(this.self.value=Ft)))}},Zv=class{publisherHead={value:Ft,replayIndex:void 0,subscribers:0,next:null};publisherTail=this.publisherHead;publisherIndex=0;subscribersIndex=0;capacity=Number.MAX_SAFE_INTEGER;replayBuffer;constructor(t){this.replayBuffer=t}replayWindow(){return this.replayBuffer?new zl(this.replayBuffer):tb}isEmpty(){return this.publisherHead===this.publisherTail}isFull(){return!1}size(){return this.publisherIndex-this.subscribersIndex}publish(t){let r=this.replayBuffer?.offer(t),n=this.publisherTail.subscribers;if(n!==0){let o={value:t,replayIndex:r,subscribers:n,next:null};this.publisherTail.next=o,this.publisherTail=this.publisherTail.next,this.publisherIndex+=1}return!0}publishAll(t){if(this.publisherTail.subscribers!==0)for(let r of t)this.publish(r);else this.replayBuffer&&this.replayBuffer.offerAll(t);return[]}slide(){if(this.publisherHead!==this.publisherTail){let t=this.publisherHead.next,r=t.value;this.publisherHead=this.publisherHead.next,this.publisherHead.value=Ft,this.subscribersIndex+=1,this.replayBuffer?.slide(r,t.replayIndex)}}subscribe(){return this.publisherTail.subscribers+=1,new Yv(this,this.publisherTail,this.publisherIndex,!1)}},Yv=class{self;subscriberHead;subscriberIndex;unsubscribed;constructor(t,r,n,o){this.self=t,this.subscriberHead=r,this.subscriberIndex=n,this.unsubscribed=o}isEmpty(){if(this.unsubscribed)return!0;let t=!0,r=!0;for(;r;)this.subscriberHead===this.self.publisherTail?r=!1:this.subscriberHead.next.value!==Ft?(t=!1,r=!1):(this.subscriberHead=this.subscriberHead.next,this.subscriberIndex+=1);return t}size(){return this.unsubscribed?0:this.self.publisherIndex-Math.max(this.subscriberIndex,this.self.subscribersIndex)}poll(){if(this.unsubscribed)return br;let t=!0,r=br;for(;t;)if(this.subscriberHead===this.self.publisherTail)t=!1;else{let n=this.subscriberHead.next.value;n!==Ft&&(r=n,this.subscriberHead.subscribers-=1,this.subscriberHead.subscribers===0&&(this.self.publisherHead=this.self.publisherHead.next,this.self.publisherHead.value=Ft,this.self.subscribersIndex+=1),t=!1),this.subscriberHead=this.subscriberHead.next,this.subscriberIndex+=1}return r}pollUpTo(t){t=It(t);let r=[],n=0;for(;n!==t;){let o=this.poll();o===br?n=t:(r.push(o),n+=1)}return r}unsubscribe(){if(!this.unsubscribed)for(this.unsubscribed=!0,this.self.publisherTail.subscribers-=1;this.subscriberHead!==this.self.publisherTail;)this.subscriberHead.next.value!==Ft&&(this.subscriberHead.subscribers-=1,this.subscriberHead.subscribers===0&&(this.self.publisherHead=this.self.publisherHead.next,this.self.publisherHead.value=Ft,this.self.subscribersIndex+=1)),this.subscriberHead=this.subscriberHead.next}},Qv=class{[Xoe]={_A:D};pubsub;subscribers;subscription;pollers;shutdownHook;shutdownFlag;strategy;replayWindow;ended;constructor(t,r,n,o,s,a,i,c,u){this.pubsub=t,this.subscribers=r,this.subscription=n,this.pollers=o,this.shutdownHook=s,this.shutdownFlag=a,this.strategy=i,this.replayWindow=c,this.ended=u}pipe(){return te(this,arguments)}},Xv=class{[Qoe]={_A:D};pubsub;subscribers;scope;shutdownHook;shutdownFlag;strategy;ended;constructor(t,r,n,o,s,a,i){this.pubsub=t,this.subscribers=r,this.scope=n,this.shutdownHook=o,this.shutdownFlag=s,this.strategy=a,this.ended=i}pipe(){return te(this,arguments)}},sse=(e,t,r,n,o,s,a)=>new Xv(e,t,r,n,o,s,a),ase=e=>{if(e<=0||e!==1/0&&!Number.isInteger(e))throw new Error(`Cannot construct PubSub with capacity of ${e}`)},zS=class{publishers=xa();get shutdown(){return Un(t=>ui(yi(this.publishers),([r,n,o])=>o?u0(n,t.id):ie,{concurrency:\"unbounded\",discard:!0}))}handleSurplus(t,r,n,o,s){return Ff(a=>{if(Ce(s.current))return a(g(!1));let i=Mc();return this.offerUnsafe(n,i),this.onPubSubEmptySpaceUnsafe(t,r),this.completeSubscribersUnsafe(t,r),Xj(o)?(this.removeUnsafe(i),a(co)):i.effect?a(i.effect):(i.resumes=[a],Y(()=>this.removeUnsafe(i)))})}onPubSubEmptySpaceUnsafe(t,r){let n=!0;for(;n&&!t.isFull();){let o=Gc(this.publishers);if(o===br)n=!1;else{let[s,a,i]=o,c=t.publish(s);c||rw(this.publishers,o),this.completeSubscribersUnsafe(t,r),c&&i&&ys(a,Vr(!0))}}}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}offerUnsafe(t,r){let n=t[Symbol.iterator](),o=n.next();if(!o.done)for(;;){let s=o.value;if(o=n.next(),o.done){Bo(this.publishers,[s,r,!0]);break}Bo(this.publishers,[s,r,!1])}}removeUnsafe(t){nw(this.publishers,([r,n])=>n!==t)}},WS=class{get shutdown(){return ie}handleSurplus(t,r,n,o){return g(!1)}onPubSubEmptySpaceUnsafe(t,r){}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}},ek=class{get shutdown(){return ie}handleSurplus(t,r,n,o,s){return Y(()=>Ce(s.current)?!1:(this.slidingPublishUnsafe(t,n),this.completeSubscribersUnsafe(t,r),!0))}onPubSubEmptySpaceUnsafe(t,r){}completePollersUnsafe(t,r,n,o){return rk(this,t,r,n,o)}completeSubscribersUnsafe(t,r){return nk(this,t,r)}slidingPublishUnsafe(t,r){let n=r[Symbol.iterator](),o=n.next();if(!o.done&&t.capacity>0){let s=o.value,a=!0;for(;a;){t.slide();let i=t.publish(s);i&&(o=n.next())&&!o.done?s=o.value:i&&(a=!1)}}}},rk=(e,t,r,n,o)=>{let s=!0;for(;s&&!n.isEmpty();){let a=Gc(o);if(a===br)nse(r,n,o),o.length===0?s=!1:rse(r,n,o);else{let i=n.poll();i===br?rw(o,a):(ys(a,Vr(i)),e.onPubSubEmptySpaceUnsafe(t,r))}}},nk=(e,t,r)=>{for(let[n,o]of r)for(let s of o)e.completePollersUnsafe(t,r,n,s)},qS=class{capacity;head={value:Ft,index:0,next:null};tail=this.head;slideValues=[];size=0;index=0;publisherIndex=0;constructor(t){this.capacity=t}slide(t,r){this.slideValues[this.index%this.capacity]={value:t,index:r},this.index++}offer(t){let r=this.publisherIndex++;if(this.tail.value=t,this.tail.index=r,this.tail.next={value:Ft,index:0,next:null},this.tail=this.tail.next,this.size===this.capacity){let n=this.head;this.head=n.next,n.next=null,n.value=Ft}else this.size+=1;return r}offerAll(t){for(let r of t)this.offer(r)}},zl=class{buffer;values;index=0;remaining;slideIndex;newestIndex=-1;constructor(t){this.buffer=t,this.remaining=t.size,this.slideIndex=t.index,this.values=new Array(this.remaining);let r=t.head;for(let n=0;nthis.newestIndex&&(this.index=(this.index+1)%this.values.length,this.values[(this.index+this.remaining-1)%this.values.length]=s.value,this.newestIndex=s.index)}this.slideIndex=this.buffer.index}take(){if(this.remaining===0)return;this.sync();let t=this.values[this.index];return this.values[this.index]=Ft,this.index=(this.index+1)%this.values.length,this.remaining--,this.remaining===0&&this.close(),t}takeN(t){t=It(t);let r=Math.min(t,this.remaining),n=new Array(r);for(let o=0;o{},takeN:()=>[],takeAll:()=>[],close:()=>{}};var sk=e=>fd(e)?ut(e)?ue(e.value):e:g(e);var iH=\"~effect/Channel\",Rr=e=>A(e,iH),ise={[iH]:{_Env:D,_InErr:D,_InElem:D,_OutErr:D,_OutElem:D},pipe(){return te(this,arguments)}},Ue=e=>{let t=Object.create(ise);return t.transform=(r,n)=>nt(e(r,n),o=>g($e(o))),t},nn=(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>t(o,n))),Cr=e=>Ue((t,r)=>e),ns=e=>Ue(_e(function*(t,r){let n=tr(r),o=a=>Xe(n,bd(a)),s=yield*Lo(e(t,r,n),o);return Lo(s,o)})),we=e=>e.transform,ih=4096,cse=(e,t,r)=>fo({capacity:r?.bufferSize,strategy:r?.strategy}).pipe(Qr(n=>xr(e,lo(n))),Qr(n=>Ss(t(n),e).pipe(nt(o=>cr(n,o)),rr(e,{startImmediately:!0}))));var cH=(e,t)=>Ue((r,n)=>W(cse(n,e,t),Zc)),rb=e=>Ue((t,r)=>L(()=>we(e())(t,r))),use=(e,t,r)=>ns(_e(function*(n,o,s){let a=v();yield*bs(s,c=>Ce(a)?r(a.value,c):ie);let i=yield*ma(W(e,c=>(a=_(c),c)));return yield*we(t(i))(n,o)}));var uH=e=>Cr(Y(()=>{let t=e();return L(()=>{let r=t.next();return r.done?ue(r.value):g(r.value)})})),ak=e=>Cr(Y(()=>{let t=0;return L(()=>t>=e.length?ue():g(e[t++]))}));var ik=(e,t=ih)=>{let r=eo(t);return Cr(Y(()=>{let n=e(),o=v();return L(()=>{if(o._tag===\"Some\")return ue(o.value);let s=[];for(;s.lengthik(()=>e[Symbol.iterator](),t),nb=e=>ob(g(e));var lH=e=>ob(Y(e)),Ou=Cr(g(ue())),pH=Cr(g(Bc)),Ji=e=>Cr(g(F(e))),dH=e=>Cr(Ig(e)),ch=e=>Cr($e(e)),mH=e=>Cr(da(e)),ck=e=>ch(Rc(e)),ob=e=>Cr(Y(()=>{let t=!1;return L(()=>t?ue():(t=!0,e))}));var hH=e=>Cr(C(e,()=>ue())),uk=e=>Cr(g(C(e,sk)));var xH=e=>Cr(g(Zc(e)));var fk=e=>Cr(g(V0(rH(e),()=>ue())));var gH=e=>_u(W(ah(e),fk)),yH=e=>_u(W(ah(e),t=>uk(eb(t))));var SH=e=>Ue((t,r)=>fse({scope:r,readable:e.evaluate(),onError:e.onError,releaseLockOnEnd:e.releaseLockOnEnd}));var fse=e=>{let t=e.readable.getReader(),r=e.exit??Hl(void 0),n=L(()=>r.current?r.current:As(fi({try:()=>t.read(),catch:e.onError}),{onFailure:o=>r.current??$e(o),onSuccess:({done:o,value:s})=>r.current?r.current:o?ue():g(Oe(s))}));return jt(xr(e.scope,e.releaseLockOnEnd?Y(()=>t.releaseLock()):Mf(()=>t.cancel().catch(o=>t.closed.then(()=>Promise.reject(o),Wr))).pipe(hi(Y(()=>t.releaseLock())))),n)},lse=(e,t)=>Ue(_e(function*(r,n){let o=e[Symbol.asyncIterator](),s=!1;return o.return&&(yield*xr(n,L(()=>s?Y(()=>{o.return().catch(Wr)}):Mf(()=>o.return())))),C(fi({try:()=>{let a=o.next();return s=!0,a.finally(()=>{s=!1})},catch:t}),a=>a.done?ue(a.value):g(a.value))})),bH=(e,t)=>os(lse(e,t),Oe),os=l(2,(e,t)=>nn(e,r=>Y(()=>{let n=0;return W(r,o=>t(o,n++))})));var EH=l(2,(e,t)=>nn(e,r=>g(At(r,n=>C(t(n),ue))))),IH=e=>e===void 0||e!==\"unbounded\"&&e<=1,sb=l(e=>Rr(e[0]),(e,t,r)=>IH(r?.concurrency)?wH(e,t):pse(e,t,r)),wH=(e,t)=>Ue((r,n)=>{let o=0;return W(we(e)(r,n),C(s=>t(s,o++)))}),pse=(e,t,r)=>ns(_e(function*(n,o,s){let a=0,i=yield*we(e)(n,o),c=r.concurrency===\"unbounded\"?Number.MAX_SAFE_INTEGER:Math.min(r.concurrency,Number.MAX_SAFE_INTEGER),u=yield*Fd(0);yield*xr(s,lo(u));let f=uo(yield*Hc()),p=gi(s);if(r.unordered){let d=Ug(c),m=gt(d.release(1)),h=As({onFailure:y=>C(cr(u,y),m),onSuccess:y=>C(Ln(u,y),m)});yield*d.take(1).pipe(C(()=>i),C(y=>{let S=a++;return p(f(h(L(()=>t(y,S))))),ie}),ir({disableYield:!0}),nt(y=>d.withPermits(c-1)(cr(u,y))),rr(s))}else{let d=yield*Fd(c-2);yield*xr(s,lo(d)),yield*ga(d).pipe(K0,C(y=>Ln(u,y)),ir({disableYield:!0}),nt(y=>cr(u,y)),rr(s));let m,h=y=>{y._tag!==\"Success\"&&(m=y.cause,Si(u,y.cause))};yield*i.pipe(C(y=>{if(m)return $e(m);let S=a++,b=f(L(()=>t(y,S)));return p(b),b.addObserver(h),Ln(d,xi(b))}),ir({disableYield:!0}),nt(y=>Ln(d,Fn(y)).pipe(Yr(cr(d,y)))),rr(s))}return ga(u)}));var lk=l(e=>Rr(e[0]),(e,t,r)=>IH(r?.concurrency)?dse(e,t):mse(e,t,r)),dse=(e,t)=>Ue((r,n)=>W(we(e)(r,n),o=>{let s,a,i=C(o,u=>(a??=tr(n),Ct(we(t(u))(r,a),f=>(s=c(f),s)))),c=At(u=>{if(s=void 0,a.state._tag===\"Empty\")return i;let f=Xe(a,Bt);return a=void 0,C(f,()=>i)});return L(()=>s??i)})),mse=(e,t,r)=>e.pipe(os(t),cb(r)),AH=l(2,(e,t)=>Ue((r,n)=>Y(()=>{let o,s=tr(n),a=C(we(e)(r,s),i=>(o=At(i,c=>Xe(s,Bt).pipe(C(()=>we(t(c))(r,n)),C(u=>(o=u,u)))),o));return L(()=>o??a)})));var pk=l(4,(e,t,r,n)=>Ue(_e(function*(o,s){let a=yield*we(e)(o,s),i=yield*we(t)(o,s),c=r();return L(()=>{let u=n(c,a,i);return W(u,([f,p])=>(c=p,f))})}))),CH=l(2,(e,t)=>Ue((r,n)=>Y(()=>{let o,s=tr(n),a=C(we(e)(r,s),i=>{let c=i.pipe(Qr(()=>(o=i,ie)),At(u=>Xe(s,Vr(u)).pipe(Yr(we(t(u))(r,n)),C(f=>(o=f,f)))));return o=c,c});return L(()=>o??a)}))),TH=e=>lk(e,D),jr=e=>nn(e,t=>{let r,n=0,o=L(function s(){if(r===void 0)return C(t,i=>{switch(i.length){case 0:return s();case 1:return g(i[0]);default:return r=i,g(i[n++])}});let a=r[n++];return n>=r.length&&(r=void 0,n=0),g(a)});return g(o)}),vH=e=>wH(e,sk),kH=e=>nn(e,t=>g(ir(t,{disableYield:!0}))),OH=l(2,(e,t)=>Fo(typeof t==\"function\"?t(D):t).pipe(W(r=>{let n=gr.defaultValue();return dk(db(e,gr,Y(()=>n)),o=>oo(o)?$e(o.cause):r(o.value).pipe(W(s=>{n=s}),At(()=>ue(o.value))))}),_u)),dk=(e,t)=>Ue((r,n)=>Y(()=>{let o,s=()=>{let a=tr(n);return C(we(e)(r,a),i=>(o=nt(i,c=>{let u=bd(c);return Xe(a,u).pipe(C(()=>t(u,n)),C(s))}),o))};return L(()=>o??s())})),_H=e=>dk(e,t=>oo(t)?$e(t.cause):ie),RH=l(2,(e,t)=>nn(e,(r,n)=>W(Id(t),o=>Qr(r,o)))),PH=l(2,(e,t)=>Ue((r,n)=>W(we(e)(r,n),o=>C(o,function s(a){return t(a)?g(a):C(o,s)}))));var MH=l(2,(e,t)=>nn(e,r=>g(C(r,function n(o){let s=[];for(let a=0;ann(e,r=>g(C(r,function n(o){let s=[];for(let a=0;ann(e,r=>{let n=C(r,o=>z0(o,t));return g(C(n,function o(s){return yt(s)?g(s):C(n,o)}))})),UH=l(2,(e,t)=>nn(e,r=>g(C(r,function n(o){return C(W0(o,t),s=>yt(s)?g(s):C(r,n))})))),Wl=l(e=>Rr(e[0]),(e,t,r,n)=>Ue((o,s)=>W(we(e)(o,s),a=>{let i=t(),c,u=0,f,p=As(a,{onFailure(m){f=m;let h=n?.onHalt&&n.onHalt(i);return h&&h.length>0?g([i,h]):$e(m)},onSuccess(m){let h=r(i,m);return v_(h)?g(h):h}});return L(function m(){if(c===void 0)return f?$e(f):C(p,([y,S])=>(i=y,S.length===0?m():S.length===1?g(S[0]):(c=S,m())));let h=c[u++];return u>=c.length&&(c=void 0,u=0),g(h)})})));var DH=l(3,(e,t,r)=>Ue((n,o)=>W(we(e)(n,o),s=>{let a=t,i=!0;return L(()=>i?(i=!1,g(a)):W(C(s,c=>r(a,c)),c=>(a=c,a)))}))),ql=l(2,(e,t)=>Ue((r,n)=>{let o=tr(n);return W(we(e)(r,o),s=>{let a=s.pipe(nt(i=>{if(Is(i))return $e(i);let c=o;return o=tr(n),Xe(c,Fn(i)).pipe(Yr(we(t(i))(r,o)),C(u=>(a=u,u)))}));return L(()=>a)})})),LH=l(2,(e,t)=>ib(e,cd,t)),ab=l(2,(e,t)=>ql(e,r=>hH(C(t(r),n=>$e(r))))),$H=l(3,(e,t,r)=>ql(e,n=>t(n)?r(n):ch(n))),ib=l(3,(e,t,r)=>ql(e,n=>{let o=t(n);return ae(o)?ch(o.failure):r(o.success,n)})),Da=l(2,(e,t)=>ib(e,cn,r=>t(r)));var KH=l(2,(e,t)=>nn(e,r=>g(Ag(r,n=>Pc(n)?ie:pi(t(n)))))),BH=l(e=>Rr(e[0]),(e,t,r,n)=>Da(e,o=>t(o)?r(o):n?n(o):Ji(o))),jH=l(e=>Rr(e[0]),(e,t,r,n)=>Da(e,o=>{let s=t(o);return ae(s)?n?n(s.failure):Ji(s.failure):r(s.success)}));var HH=l(e=>Rr(e[0]),(e,t,r,n,o)=>Da(e,s=>{if(Wt(s,t)&&A(s,\"reason\")){let a=s.reason;return Wt(a,r)?n(a,s):o?o(a,s):Ji(s)}return Ji(s)})),zH=l(e=>Rr(e[0]),(e,t,r,n)=>{let o;return Da(e,s=>{if(Wt(s,t)&&A(s,\"reason\")&&A(s.reason,\"_tag\")&&hg(s.reason._tag)){let a=s.reason;return o??=new Set(Object.keys(r)),o.has(a._tag)?r[a._tag](a,s):n?n(a,s):Ji(s)}return Ji(s)})});var WH=l(2,(e,t)=>nn(e,r=>g(Do(r,n=>Pc(n)?n:t(n))))),qH=e=>Da(e,ck),JH=l(e=>Rr(e[0]),(e,t)=>{if(!t?.log)return Da(e,()=>Ou);let r=Xp(t.log);return Da(ab(e,n=>t0(n)?r(n):ie),()=>Ou)}),sH=e=>ql(e,()=>Ou),GH=l(e=>Rr(e[0]),(e,t)=>{if(!t?.log)return sH(e);let r=Xp(t.log);return sH(ab(e,n=>r(n)))}),VH=l(2,(e,t)=>rb(()=>{let r,n=gr.defaultValue(),o=db(e,gr,Y(()=>n)),s=yk(o,()=>(r=void 0,ie)),a=typeof t==\"function\"?t(D):t;return dk(s,(i,c)=>{if(ut(i))return ue(i.value);let u=cn(i.cause);return ae(u)?$e(u.failure):kt(function*(){r||(r=yield*Fo(a)),n=yield*r(u.success)}).pipe(At(()=>F(u.success)),Ss(c))})})),ZH=l(e=>Rr(e[0]),(e,t,r)=>e.pipe(os(t),cb({...r,concurrency:r?.concurrency??1,switch:!0}))),cb=l(2,(e,{bufferSize:t=16,concurrency:r,switch:n=!1})=>ns(_e(function*(o,s,a){let i=r===\"unbounded\"?Number.MAX_SAFE_INTEGER:Math.max(1,r),c=n?void 0:Ug(i),u=yield*Yj(!0),f=new Map,p=yield*Fd(t);yield*xr(a,lo(p));let d=yield*we(e)(o,s);return yield*kt(function*(){for(;;){let m;c&&(f.size=i;){let[x,w]=I_(f);f.delete(x),f.size===0&&(yield*u.open),yield*Ko(x),yield*di(Xe(w,ld()))}let b=yield*S.pipe(Qr(()=>kd),C(x=>Ln(p,x)),ir({disableYield:!0}),Lo(_e(function*(x){let w=bd(x),I=yield*ao(Xe(y,w));if(!f.has(b))return;let T=pd([w,I]);oo(T)&&(yield*cr(p,T.cause)),f.delete(b),c&&(yield*c.release(1)),f.size===0&&(yield*u.open)})),Df);u.closeUnsafe(),f.set(b,y)}}).pipe(nt(m=>{let h=Sd(m);return rt(h)?u.whenOpen(cr(p,m)):cr(p,m)}),rr(a)),ga(p)}))),ub=l(e=>Rr(e[0])&&Rr(e[1]),(e,t,r)=>ns(_e(function*(n,o,s){let a=r?.haltStrategy??\"both\",i=yield*Fd(0);yield*xr(s,lo(i));let c=0;function u(p,d){if(c++,!Is(d))return cr(i,d);switch(a){case\"both\":return c===2?cr(i,d):ie;case\"left\":case\"right\":return p===a?cr(i,d):ie;case\"either\":return cr(i,d)}}let f=(p,d,m)=>we(d)(n,m).pipe(C(h=>h.pipe(C(y=>Ln(i,y)),ir)),Lo(h=>_d(bd(h),y=>Xe(m,y)).pipe(As({onFailure:y=>u(p,y),onSuccess:()=>u(p,h)}))),rr(s));return yield*f(\"left\",e,tr(s)),yield*f(\"right\",t,tr(s)),ga(i)}))),YH=l(2,(e,t)=>ub(e,hH(t),{haltStrategy:\"left\"})),QH=()=>Ue((e,t)=>Y(()=>{let r=\"\",n=!1,o=v();function s(c){let u=[];function f(p){r.length===0?u.push(p):(u.push(r+p),r=\"\")}for(let p=0;po._tag===\"Some\"?ue(o.value):Uc(e,{onSuccess:i,onFailure:$e,onDone:c=>{if(o=_(c),r.length>0){let u=r;return r=\"\",n=!1,g([u])}return ue(c)}}));function i(c){let u=s(c);return u!==null?g(u):a}return a})),XH=(e,t)=>Ue((r,n)=>Y(()=>{let o=new TextDecoder(e,t),s={stream:!0},a=r.pipe(W(kn(i=>o.decode(i,s))),At(i=>{a=ue(i);let c=o.decode();return c.length>0?g(Oe(c)):a}));return L(()=>a)}));var fb=l(2,(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>we(t)(o,n)))),mk=l(2,(e,t)=>Ue((r,n)=>C(we(e)(r,n),o=>W(we(t)(hk(o),n),xk)))),ez=e=>e._tag===\"Die\"&&Pc(e.defect)&&id(e.defect.value),tz=e=>e.reasons.some(ez),hk=e=>nt(e,t=>Is(t)?$e(t):yr(o0(t))),hse=e=>tz(e)?gs(e.reasons.flatMap(t=>ez(t)?t.defect.value.reasons:[t])):e,xk=e=>$o(t=>nt(t(e),r=>$e(hse(r)))),_u=e=>Ue((t,r)=>{let n;return g(L(()=>n||e.pipe(Ss(r),C(o=>we(o)(t,r)),C(o=>n=o))))}),rz=e=>ns((t,r,n)=>W(Ss(we(e)(t,r),n),Ss(n)));var nz=l(2,(e,t)=>Ue(_e(function*(r,n){let o=yield*we(e)(r,n),s=yield*fo({capacity:t.capacity===\"unbounded\"?void 0:t.capacity,strategy:t.capacity===\"unbounded\"?void 0:t.strategy});return yield*xr(n,lo(s)),yield*o.pipe(C(a=>Ln(s,a)),ir({disableYield:!0}),Lo(a=>cr(s,a)),rr(n)),ga(s)}))),oz=l(2,(e,t)=>Ue(_e(function*(r,n){let o=yield*we(e)(r,n),s=yield*fo({capacity:t.capacity===\"unbounded\"?void 0:t.capacity,strategy:t.capacity===\"unbounded\"?void 0:t.strategy});return yield*xr(n,lo(s)),yield*o.pipe(C(a=>Vc(s,a)),ir({disableYield:!0}),Lo(a=>cr(s,a)),rr(n)),Zc(s)}))),gk=l(2,(e,t)=>ub(e,Cr(g(C(t,ue))),{haltStrategy:\"either\"})),sz=l(2,(e,t)=>ns(_e(function*(r,n,o){let s=yield*we(e)(r,n),a=yield*rr(t,o,{startImmediately:!0});return L(()=>{let i=a.pollUnsafe();return i===void 0?s:c0(i,{onFailure:$e,onSuccess:ue})})}))),az=l(2,(e,t)=>uh(e,r=>oo(r)?t(r.cause):ie)),uh=l(2,(e,t)=>ns((r,n,o)=>bs(o,t).pipe(Yr(we(e)(r,n))))),iz=l(2,(e,t)=>_u(jt(t,e))),yk=l(2,(e,t)=>nn(e,r=>Y(()=>{let n=!0,o=Qr(r,s=>(n=!1,t(s)));return L(()=>n?o:r)}))),cz=l(2,(e,t)=>nn(e,r=>g(At(r,n=>C(t,()=>ue(n)))))),uz=l(2,(e,t)=>uh(e,r=>t)),Ru=(e,t,r)=>L(()=>{let n=so(),o=we(e)(ue(),n);return At(C(o,t),r||g).pipe(Dn(s=>Xe(n,s)))});var lb=l(2,(e,t)=>Ue((r,n)=>W(io(we(e)(r,n),t),io(t)))),pb=l(3,(e,t,r)=>Ue((n,o)=>W(Cs(we(e)(n,o),t,r),Cs(t,r)))),db=l(3,(e,t,r)=>Ue((n,o)=>C(r,s=>we(pb(e,t,s))(n,o)))),fz=l(e=>Rr(e[0]),(e,t,r)=>kp(t)?lb(e,t):Ue((n,o)=>C(r?.local?hd(t,md(),o):cg(t,o),s=>W(io(we(e)(n,o),s),io(s))))),lz=l(2,(e,t)=>Ue((r,n)=>Od(o=>{let s=t(o);return we(lb(e,s))(r,n)})));var Sk=function(){let e=Rr(arguments[0]),t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return aH(n,t,r)}return n=>aH(n,t,r)},aH=(e,t,r)=>use(Z0(t,r),n=>pb(e,Ic,n),(n,o)=>Un(s=>{let a=s.getRef(Dr),i=s.getRef(uF);return tg(n,o,a,i)}));var pz=e=>Ru(e,t=>ir(t,{disableYield:!0})),Gi=l(2,(e,t)=>Ru(e,r=>ir(C(r,t),{disableYield:!0}))),dz=l(2,(e,t)=>Ru(e,r=>r.pipe(C(t),C(n=>n?ie:ue()),ir({disableYield:!0})))),bk=e=>W(Pu(e,()=>({bytes:0,arrays:[]}),(t,r)=>{for(let n=0;n{let n=new Uint8Array(r),o=0;for(let s=0;sL(()=>{let t=v();return Ru(e,r=>r.pipe(wg,C(n=>(t=n,ue()))),()=>g(t))}),hz=e=>L(()=>{let t=Symbol(),r=t;return Ru(e,n=>ir(C(n,o=>(r=o,ie)),{disableYield:!0}),()=>r===t?li:$0(r))}),Pu=l(3,(e,t,r)=>L(()=>{let n=t();return Ru(e,o=>No({while:Cn,body:()=>o,step:s=>{n=r(n,s)}}),()=>g(n))})),xz=l(3,(e,t,r)=>L(()=>{let n=t();return Ru(e,o=>No({while:Cn,body:gt(o.pipe(C(s=>r(n,s)),W(s=>{n=s}))),step:Wr}),()=>g(n))})),Ek=_e(function*(e){let t=Ug(1),r=yield*Hc(),n=Me(r,Zr);return(yield*we(e)(ue(),n)).pipe(io(r),t.withPermits(1))},nt(e=>g($e(e)))),Bs=(e,t)=>we(e)(ue(),t);var Ik=l(e=>Rr(e[0]),(e,t)=>$o(r=>Gi(e,n=>Vc(t,n)).pipe(r,ao,C(n=>(ut(n)?Nd(t):Si(t,n.cause),ie)))));var gz=l(e=>Rr(e[0]),_e(function*(e,t){let r=yield*zc,n=yield*fo({capacity:typeof t.capacity==\"number\"?t.capacity:void 0,strategy:typeof t.capacity==\"number\"?t.strategy:void 0});return yield*xr(r,lo(n)),yield*rr(Ik(e,n),r),n}));var yz=e=>Wc(e.capacity===\"unbounded\"?YS(e):e.strategy===\"dropping\"?VS(e):e.strategy===\"sliding\"?ZS(e):GS(e),sh),Sz=l(2,_e(function*(e,t){let r=yield*yz(t);return yield*Lf(wk(e,r,{shutdownOnEnd:t.shutdownOnEnd!==!1})),r})),wk=l(e=>Rr(e[0]),(e,t,r)=>Gi(e,n=>tH(t,n)).pipe(r?.shutdownOnEnd===!0?hi(sh(t)):D)),bz=l(2,_e(function*(e,t){let r=yield*yz(t);return yield*Gi(e,n=>XS(r,n)).pipe(Dn(n=>QS(r,n)),Lf),r}));var Hr={};An(Hr,{Array:()=>Sue,Boolean:()=>Eue,ByteSize:()=>wue,ConfigError:()=>Zl,Date:()=>kue,Duration:()=>Iue,Finite:()=>hue,Int:()=>xue,Literal:()=>gue,Literals:()=>yue,LogLevel:()=>Cue,NonEmptyString:()=>due,Number:()=>mue,Port:()=>Aue,Record:()=>bue,Redacted:()=>Tue,String:()=>pue,URL:()=>vue,all:()=>BW,fail:()=>fue,flatMap:()=>tue,isConfig:()=>$W,map:()=>KW,mapEffect:()=>rue,nested:()=>Oue,option:()=>oue,orElse:()=>nue,schema:()=>Tr,succeed:()=>lue,unwrap:()=>HW,withDefault:()=>jW});var Vl={};An(Vl,{ConfigProvider:()=>Du,SourceError:()=>gb,constantCase:()=>$ce,fromDir:()=>Xce,fromDotEnv:()=>Qce,fromDotEnvContents:()=>NW,fromEnv:()=>FW,fromEnvRecord:()=>qk,fromUnknown:()=>Hce,layer:()=>Bce,layerAdd:()=>jce,make:()=>Sb,makeArray:()=>zk,makeRecord:()=>yb,makeValue:()=>gh,mapInput:()=>Wk,nested:()=>Kce,orElse:()=>jk});var xse=\"~effect/Stream\",gse={_R:D,_E:D,_A:D},Ez=function(e){this.channel=e};Ez.prototype={[xse]:gse,pipe(){return te(this,arguments)}};var Iz=e=>new Ez(e);var Sse=\"~effect/Sink\";var bse={_A:D,_In:D,_L:D,_E:D,_R:D},Ese={[Sse]:bse,pipe(){return te(this,arguments)}};var Ise=e=>{let t=Object.create(Ese);return t.transform=e,t},wz=e=>Ue((t,r)=>g(C(e.transform(t,r),ue)));var Az=e=>{let t=It(e);return Ise(r=>{let n=[];if(t===0)return g([n]);let o;return r.pipe(C(s=>{if(n.length+s.length<=t){for(let a=0;ag([n,o])))})};var Hs={};An(Hs,{DefaultChunkSize:()=>Lz,Do:()=>fce,TypeId:()=>Dz,accumulate:()=>Jie,aggregate:()=>$ie,aggregateWithin:()=>Nk,as:()=>rae,bind:()=>pce,bindEffect:()=>dce,bindTo:()=>mce,broadcast:()=>hW,broadcastN:()=>Kie,buffer:()=>qae,bufferArray:()=>Jae,callback:()=>Bz,catch:()=>xh,catchCause:()=>tW,catchCauseFilter:()=>nie,catchCauseIf:()=>rie,catchDefect:()=>Gae,catchFilter:()=>Mk,catchIf:()=>nW,catchReason:()=>Xae,catchReasons:()=>eie,catchTag:()=>Yae,catchTags:()=>Qae,changes:()=>Gie,changesWith:()=>xW,changesWithEffect:()=>Vie,chunks:()=>fW,collect:()=>qie,combine:()=>Iie,combineArray:()=>wie,concat:()=>Fu,cross:()=>Tae,crossWith:()=>Qz,debounce:()=>Oie,decodeText:()=>Zie,die:()=>zz,drain:()=>lae,drainFork:()=>pae,drop:()=>Fk,dropRight:()=>Sie,dropUntil:()=>xie,dropUntilEffect:()=>gie,dropWhile:()=>cW,dropWhileEffect:()=>uW,dropWhileFilter:()=>yie,empty:()=>$a,encodeText:()=>Yie,ensuring:()=>sce,fail:()=>Jl,failCause:()=>Hz,failCauseSync:()=>Lse,failSync:()=>Dse,filter:()=>Lae,filterEffect:()=>Kae,filterMap:()=>$ae,filterMapEffect:()=>Bae,flatMap:()=>Gl,flatten:()=>Vz,flattenArray:()=>fae,flattenEffect:()=>oae,flattenIterable:()=>yae,flattenTake:()=>Sae,forever:()=>gae,fromArray:()=>dh,fromArrayEffect:()=>jse,fromArrays:()=>Hse,fromAsyncIterable:()=>Jse,fromChannel:()=>k,fromEffect:()=>mb,fromEffectDrain:()=>$z,fromEffectRepeat:()=>Kz,fromEffectSchedule:()=>Mse,fromEventListener:()=>Zse,fromIterable:()=>Nu,fromIterableEffect:()=>Kse,fromIterableEffectRepeat:()=>Bse,fromIteratorSucceed:()=>$se,fromPubSub:()=>Wse,fromPubSubTake:()=>Wz,fromPull:()=>js,fromQueue:()=>zse,fromReadableStream:()=>qse,fromSchedule:()=>Gse,fromSubscription:()=>Vse,groupAdjacentBy:()=>Die,groupBy:()=>Nie,groupByKey:()=>Uie,grouped:()=>Mie,groupedWithin:()=>Fie,haltWhen:()=>rce,ignore:()=>iie,ignoreCause:()=>cie,interleave:()=>ece,interleaveWith:()=>yW,interruptWhen:()=>tce,intersperse:()=>gW,intersperseAffixes:()=>Xie,isStream:()=>Re,iterate:()=>Qse,let:()=>lce,limitBytes:()=>pie,make:()=>Nse,map:()=>Gn,mapAccum:()=>Aie,mapAccumArray:()=>Uu,mapAccumArrayEffect:()=>Tie,mapAccumEffect:()=>Cie,mapArray:()=>Jz,mapArrayEffect:()=>sae,mapBoth:()=>nae,mapEffect:()=>mh,mapError:()=>oW,merge:()=>Ok,mergeAll:()=>Cae,mergeEffect:()=>hb,mergeLeft:()=>wae,mergeResult:()=>Iae,mergeRight:()=>Aae,mkArrayBuffer:()=>vce,mkString:()=>Tce,mkUint8Array:()=>kce,never:()=>eae,onEnd:()=>oce,onError:()=>nce,onExit:()=>SW,onFirst:()=>EW,onStart:()=>bW,orDie:()=>aie,orElseIfEmpty:()=>oie,orElseSucceed:()=>sie,paginate:()=>Yse,partition:()=>Hae,partitionEffect:()=>jae,partitionQueue:()=>Rk,peel:()=>Wae,pipeThrough:()=>Wie,pipeThroughChannel:()=>Hie,pipeThroughChannelOrFail:()=>zie,prepend:()=>Eae,provide:()=>IW,provideContext:()=>ace,provideService:()=>ice,provideServiceEffect:()=>Uk,race:()=>Dae,raceAll:()=>eW,range:()=>Xse,rechunk:()=>lW,repeat:()=>dae,repeatElements:()=>xae,result:()=>aae,retry:()=>uie,run:()=>hce,runCollect:()=>AW,runCount:()=>xce,runDrain:()=>xb,runFold:()=>yce,runFoldEffect:()=>Sce,runForEach:()=>Ice,runForEachArray:()=>Ace,runForEachWhile:()=>wce,runHead:()=>bce,runIntoPubSub:()=>Mce,runIntoQueue:()=>Uce,runLast:()=>Ece,runSum:()=>gce,scan:()=>vie,scanEffect:()=>kie,schedule:()=>mae,scoped:()=>tae,service:()=>Rse,serviceOption:()=>Pse,share:()=>jie,sliding:()=>bie,slidingSize:()=>pW,split:()=>Eie,splitLines:()=>Qie,succeed:()=>Mu,suspend:()=>En,switchMap:()=>uae,sync:()=>Use,take:()=>lie,takeRight:()=>die,takeUntil:()=>sW,takeUntilEffect:()=>aW,takeWhile:()=>iW,takeWhileEffect:()=>hie,takeWhileFilter:()=>mie,tap:()=>Gz,tapBoth:()=>iae,tapCause:()=>rW,tapDefect:()=>Zae,tapError:()=>Pk,tapErrorTag:()=>Vae,tapSink:()=>cae,throttle:()=>Pie,throttleEffect:()=>dW,tick:()=>Fse,timeout:()=>hae,timeoutOrElse:()=>Zz,toAsyncIterable:()=>Pce,toAsyncIterableEffect:()=>Rce,toAsyncIterableWith:()=>$k,toChannel:()=>Eo,toPubSub:()=>Fce,toPubSubTake:()=>CW,toPull:()=>Cce,toQueue:()=>Nce,toReadableStream:()=>Oce,toReadableStreamEffect:()=>_ce,toReadableStreamWith:()=>Lk,transduce:()=>Lie,transformPull:()=>or,transformPullBracket:()=>kk,unfold:()=>qz,unwrap:()=>Vi,unwrapReason:()=>tie,updateContext:()=>wW,updateService:()=>cce,when:()=>zae,withExecutionPlan:()=>fie,withSpan:()=>uce,zip:()=>vae,zipFlatten:()=>_ae,zipLatest:()=>Nae,zipLatestAll:()=>_k,zipLatestWith:()=>Uae,zipLeft:()=>kae,zipRight:()=>Oae,zipWith:()=>hh,zipWithArray:()=>Xz,zipWithIndex:()=>Rae,zipWithNext:()=>Pae,zipWithPrevious:()=>Mae,zipWithPreviousAndNext:()=>Fae});var Tz=\"~effect/RcMap\",wse=e=>({[Tz]:Tz,lookup:e.lookup,context:e.context,scope:e.scope,idleTimeToLive:e.idleTimeToLive,capacity:e.capacity,state:{_tag:\"Open\",map:$c()},pipe(){return te(this,arguments)}}),vz=e=>Un(t=>{let r=t.context,n=Me(r,Zr),o=wse({lookup:e.lookup,context:r,scope:n,idleTimeToLive:typeof e.idleTimeToLive==\"function\"?gO(e.idleTimeToLive,ct):gt(ct(e.idleTimeToLive??ta)),capacity:Math.max(e.capacity??Number.POSITIVE_INFINITY,0)});return jt(bs(n,()=>{if(o.state._tag===\"Closed\")return ie;let s=o.state.map;return o.state={_tag:\"Closed\"},ui(s,([,a])=>ao(fh(a))).pipe(Qr(()=>Y(()=>{Sg(s)})),C(pd))}),o)}),Ck=l(2,(e,t)=>$o(r=>{if(e.state._tag===\"Closed\")return co;let n=e.state,o=Bf(),s=Nn(n.map,t),a;if(s._tag===\"Some\")a=s.value,a.refCount++;else{if(Number.isFinite(e.capacity)&&QF(e.state.map)>=e.capacity)return F(new s0(`RcMap attempted to exceed capacity of ${e.capacity}`));{a={deferred:Mc(),scope:so(),idleTimeToLive:e.idleTimeToLive(t),finalizer:void 0,fiber:void 0,expiresAt:0,refCount:1},a.finalizer=Cse(e,t,a),Kc(n.map,t,a);let c=new Map(e.context.mapUnsafe);o.context.mapUnsafe.forEach((f,p)=>{c.set(p,f)}),c.set(Zr.key,a.scope);let u=Xs(c);L(()=>e.lookup(t)).pipe(uo(u),gi(a.scope)).addObserver(f=>{i0(f)&&Ase(e,t,a,u),ys(a.deferred,f)})}}let i=ds(o.context,Zr);return xr(i,a.finalizer).pipe(Yr(r(og(a.deferred))))}));var Ase=(e,t,r,n)=>{if(e.state._tag===\"Closed\")return;let o=Nn(e.state.map,t);o._tag===\"None\"||o.value!==r||(ci(e.state.map,t),!(r.refCount>0)&&fh(r).pipe(di({log:\"Unhandled\",message:\"Unhandled error in RcMap finalizer\"}),uo(n),gi(e.scope)))},fh=e=>e.fiber?Ko(e.fiber).pipe(Yr(Xe(e.scope,Bt))):Xe(e.scope,Bt),Cse=(e,t,r)=>Un(n=>{if(r.refCount--,r.refCount>0)return ie;if(e.state._tag===\"Closed\")return fh(r);let o=Nn(e.state.map,t);if(o._tag===\"None\"||o.value!==r)return fh(r);if(Sc(r.idleTimeToLive))return ci(e.state.map,t),fh(r);if(!sn(r.idleTimeToLive))return ie;let s=n.getRef(vf);return r.expiresAt=s.currentTimeMillisUnsafe()+Nr(r.idleTimeToLive),r.fiber?ie:(r.fiber=$o(function a(i){let c=s.currentTimeMillisUnsafe(),u=r.expiresAt-c;if(u<=0){if(e.state._tag===\"Closed\"||r.refCount>0)return ie;let f=Nn(e.state.map,t);return f._tag===\"None\"||f.value!==r?ie:(ci(e.state.map,t),di(Xe(r.scope,Bt),{log:\"Unhandled\",message:\"Unhandled error in RcMap finalizer\"}))}return C(i(s.sleep(na(u))),()=>a(i))}).pipe(hi(Y(()=>{r.fiber=void 0})),uo(n.context),gi(e.scope)),ie)});var Tk=l(2,(e,t)=>qc(r=>{if(e.state._tag===\"Closed\")return ie;let n=Nn(e.state.map,t);if(n._tag===\"None\"||Sc(n.value.idleTimeToLive))return ie;let o=n.value;return o.expiresAt=r.currentTimeMillisUnsafe()+Nr(o.idleTimeToLive),ie}));var Tse=\"~effect/RcRef\",lh={_tag:\"Empty\"},vse={_tag:\"Closed\"},kse={_A:D,_E:D},vk=class{[Tse]=kse;pipe(){return te(this,arguments)}state=lh;acquire;context;scope;idleTimeToLive;constructor(t,r,n,o){this.acquire=t,this.context=r,this.scope=n,this.idleTimeToLive=o}},_z=e=>Un(t=>{let r=t.context,n=Me(r,Zr),o=new vk(e.acquire,r,n,e.idleTimeToLive!==void 0?ct(e.idleTimeToLive):void 0);return jt(bs(n,()=>{let s=o.state;return o.state=vse,s._tag===\"Acquired\"?Xe(s.scope,Bt):s._tag===\"Acquiring\"?Ko(s.fiber):ie}),o)}),Ose=(e,t)=>{switch(e.state._tag){case\"Closed\":return co;case\"Acquired\":{let r=e.state;return r.refCount++,r.fiber?jt(Ko(r.fiber),r):g(r)}case\"Acquiring\":{let r=e.state;return r.awaiters++,Oz(e,r,t)}case\"Empty\":{let r={_tag:\"Acquiring\",fiber:void 0,awaiters:1,acquired:void 0};e.state=r;let n=so(),o=io(e.acquire,dr(e.context,Zr,n)).pipe(C(s=>{if(e.state!==r)return co;let a={_tag:\"Acquired\",value:s,scope:n,fiber:void 0,refCount:r.awaiters,invalidated:!1};return e.state=a,r.acquired=a,g(a)}),Dn(s=>ut(s)?ie:(e.state===r&&(e.state=lh),Xe(n,s))));return r.fiber=uo(Bf().context)(o),Oz(e,r,t)}}},Oz=(e,t,r)=>Dn(r(xi(t.fiber)),n=>{let o=t.acquired;return o!==void 0?oo(n)?Pz(e,o):ie:--t.awaiters>0||e.state!==t?ie:(e.state=lh,Ko(t.fiber))}),Rz=e=>{let t=e;return $o(r=>C(zc,n=>C(Ose(t,r),o=>jt(bs(n,()=>Pz(t,o)),o.value))))},Pz=(e,t)=>{if(t.refCount--,t.refCount>0)return ie;let r=e.idleTimeToLive;return r===void 0||t.invalidated?(e.state===t&&(e.state=lh),Xe(t.scope,Bt)):sn(r)?(t.fiber=$o(n=>C(n(mi(r)),()=>e.state===t&&t.refCount===0?(e.state=lh,di(Xe(t.scope,Bt),{log:\"Unhandled\",message:\"Unhandled error in RcRef finalizer\"})):ie)).pipe(hi(Y(()=>{t.fiber=void 0})),uo(e.context),gi(e.scope)),ie):ie};var Mz=_z,Fz=Rz;var Dz=\"~effect/Stream\",Re=e=>A(e,Dz),Lz=ih,k=Iz,mb=e=>k(ob(W(e,Oe))),Rse=e=>mb(J0(e)),Pse=e=>mb(G0(e)),$z=e=>js(g(C(e,()=>ue()))),Kz=e=>js(g(W(e,Oe))),Mse=(e,t)=>js(kt(function*(){let r=yield*Fo(t),n=yield*Cs(e,gr,gr.defaultValue()),o=!0,s=L(()=>r(n)).pipe(C(a=>Cs(e,gr,a)),W(a=>(n=a,Oe(a))));return L(()=>o?(o=!1,g(Oe(n))):s)})),Fse=e=>js(Y(()=>{let t=!0,r=g(Oe(void 0)),n=j0(r,e);return L(()=>t?(t=!1,r):n)})),js=e=>k(Cr(e)),or=(e,t)=>k(Ue((r,n)=>C(Bs(e.channel,n),o=>t(o,n)))),kk=(e,t)=>k(ns((r,n,o)=>C(Bs(e.channel,n),s=>t(s,n,o)))),Eo=e=>e.channel,Bz=(e,t)=>k(cH(e,t)),$a=k(Ou),Mu=e=>k(nb(Oe(e))),Nse=(...e)=>dh(e),Use=e=>k(lH(()=>Oe(e()))),En=e=>{let t=k(rb(()=>e().channel));return jz.set(t,e),t},jz=new WeakMap,Jl=e=>k(Ji(e)),Dse=e=>k(dH(e)),Hz=e=>k(ch(e)),zz=e=>k(ck(e)),Lse=e=>k(mH(e)),$se=(e,t)=>k(ik(()=>e,t)),Nu=(e,t)=>Array.isArray(e)&&t?.chunkSize===void 0?dh(e):k(fH(e,t?.chunkSize)),Kse=e=>Vi(W(e,Nu)),Bse=e=>Gl(Kz(e),Nu),dh=e=>yt(e)?k(nb(e)):$a,jse=e=>Vi(W(e,dh)),Hse=(...e)=>k(ak(ix(e,yt))),zse=e=>k(xH(e)),Wse=e=>k(gH(e)),Wz=e=>k(yH(e)),qse=e=>k(SH(e)),Jse=(e,t)=>k(bH(e,t)),Gse=e=>js(W(Id(e),t=>At(W(t(void 0),Oe),()=>ue()))),Vse=e=>k(fk(e)),Zse=(e,t,r)=>Bz(n=>{let o=typeof r==\"object\"&&r.once;function s(a){Pg(n,a),o&&Nd(n)}return Wc(Y(()=>e.addEventListener(t,s,r)),()=>Y(()=>e.removeEventListener(t,s,r)))},{bufferSize:typeof r==\"object\"?r.bufferSize:void 0}),qz=(e,t)=>js(Y(()=>{let r=e;return C(L(()=>t(r)),n=>n===void 0?ue():(r=n[1],g(Oe(n[0]))))})),Yse=(e,t)=>js(Y(()=>{let r=e,n=!1;return L(function o(){return n?ue():C(t(r),([s,a])=>(ge(a)?n=!0:r=a.value,yt(s)?g(s):o()))})})),Qse=(e,t)=>qz(e,r=>g([r,t(r)])),Xse=(e,t,r=ih)=>e>t?$a:js(Y(()=>{let n=eo(r),o=e,s=!1;return L(()=>{if(s)return ue();let a=t-o+1;if(a>n){let c=dE(o,o+n-1);return o+=n,g(c)}let i=dE(o,o+a-1);return s=!0,g(i)})})),eae=k(pH),Vi=e=>k(_u(W(e,Eo))),tae=e=>k(rz(e.channel)),Gn=l(2,(e,t)=>En(()=>{let r=0;return k(os(e.channel,kn(n=>t(n,r++))))})),rae=l(2,(e,t)=>Gn(e,()=>t)),nae=l(2,(e,t)=>e.pipe(Gn(t.onElement),oW(t.onError))),Jz=l(2,(e,t)=>k(os(e.channel,t))),mh=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,sb(t,r),os(Oe),k)),oae=l(e=>Re(e[0]),(e,t)=>mh(e,D,t)),sae=l(2,(e,t)=>k(sb(e.channel,t))),aae=e=>e.pipe(Gn(j),xh(t=>Mu(q(t)))),Gz=l(e=>Re(e[0]),(e,t,r)=>mh(e,n=>jt(t(n),n),r)),iae=l(2,(e,t)=>e.pipe(Pk(t.onError),Gz(t.onElement,{concurrency:t.concurrency}))),cae=l(2,(e,t)=>kk(e,_e(function*(r,n,o){let s=rn(),a=rn(),i,c,u=!1,f=!1,p=s.whenOpen(L(()=>{if(i){let m=i;return i=void 0,f||s.closeUnsafe(),jt(a.open,m)}return ue()}));yield*L(()=>t.transform(p,o)).pipe(m=>_d(m,h=>(u=!0,oo(h)&&(c=h.cause),a.open),!0),rr(o));let d=r.pipe(C(m=>c?$e(c):u?g(m):(i=m,a.closeUnsafe(),s.openUnsafe(),jt(a.await,m))),At(()=>c?$e(c):u?ue():(f=!0,a.closeUnsafe(),s.openUnsafe(),C(a.await,()=>c?$e(c):ue()))));return L(()=>c?$e(c):u?r:d)}))),Gl=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,lk(n=>t(n).channel,r),k)),uae=l(e=>Re(e[0]),(e,t,r)=>e.channel.pipe(jr,ZH(n=>t(n).channel,r),k)),Vz=l(e=>Re(e[0]),(e,t)=>Gl(e,D,t)),fae=e=>k(jr(e.channel)),lae=e=>k(kH(e.channel)),pae=l(2,(e,t)=>hb(e,xb(t))),dae=l(2,(e,t)=>k(OH(e.channel,t))),mae=l(2,(e,t)=>e.channel.pipe(jr,RH(t),os(Oe),k)),hae=l(2,(e,t)=>Zz(e,{duration:t,orElse:()=>$a})),Zz=l(2,(e,t)=>{let r=ct(t.duration);if(!sn(r))return e;if(Sc(r))return En(t.orElse);let n=Symbol();return tW(En(()=>{let s=Bf().getRef(vf),a=Nr(r),i,c=rn(!1);return Ok(or(e,(u,f)=>L(()=>(i=s.currentTimeMillisUnsafe()+a,c.openUnsafe(),u)).pipe(W(p=>(c.closeUnsafe(),i=void 0,p)),g)),$z(kt(function*(){for(;;)if(yield*c.await,!(i===void 0||(yield*mi(i-s.currentTimeMillisUnsafe()),i===void 0)||i-s.currentTimeMillisUnsafe()>0))return yield*yr(n)})),{haltStrategy:\"left\"})}),o=>o.reasons.find(a=>a._tag===\"Die\"&&a.defect===n)?t.orElse():Hz(o))}),xae=l(2,(e,t)=>k(Ue((r,n)=>W(we(jr(e.channel))(r,n),o=>{let s,a=kt(function*(){let i=yield*o,c=Oe(i);return s=(yield*Id(t))(i).pipe(jt(c),At(f=>(s=void 0,a))),c});return L(()=>s??a)})))),gae=e=>k(_H(e.channel)),yae=e=>Gl(e,Nu),Sae=e=>e.channel.pipe(jr,vH,k),Fu=l(2,(e,t)=>{let r=k(TH(uH(()=>bae(e,t))));return Yz.set(r,[e,t]),r}),Yz=new WeakMap;function*bae(e,t){let r=[t,e];for(;r.length>0;){let n=r.pop(),o=Yz.get(n);if(o!==void 0){r.push(o[1],o[0]);continue}let s=jz.get(n);if(s===void 0){yield n.channel;continue}try{r.push(s())}catch(a){r.push(zz(a))}yield Ou}}var Eae=l(2,(e,t)=>Fu(Nu(t),e)),Ok=l(e=>Re(e[0])&&Re(e[1]),(e,t,r)=>k(ub(Eo(e),Eo(t),r))),hb=l(2,(e,t)=>e.channel.pipe(YH(t),k)),Iae=l(2,(e,t)=>Ok(Gn(e,j),Gn(t,q))),wae=l(2,(e,t)=>hb(e,xb(t))),Aae=l(2,(e,t)=>hb(t,xb(e))),Cae=l(2,(e,t)=>Vz(Nu(e),t)),Tae=l(2,(e,t)=>Qz(e,t,(r,n)=>[r,n])),Qz=l(3,(e,t,r)=>Gl(e,n=>Gn(t,o=>r(n,o)))),hh=l(3,(e,t,r)=>En(()=>{let n=0,o=0;return Xz(e,t,(s,a)=>{let i=Math.min(s.length-n,a.length-o),c=ox(i,p=>r(s[n+p],a[o+p]));n+=i,o+=i;let u=n===s.length,f=o===a.length;return u&&(n=0),f&&(o=0),[c,u?[]:s,f?[]:a]})})),Xz=l(3,(e,t,r)=>k(ns(_e(function*(n,o){let s=yield*Bs(e.channel,o),a=yield*Bs(t.channel,o),i=kt(function*(){let p=yield*rr(s,o),d=yield*rr(a,o);return yield*x1([p,d])}),c,u;return kt(function*(){let[p,d]=c?[c,u??(yield*a)]:u?[yield*s,u]:yield*i,[m,h,y]=r(p,d);return c=yt(h)?h:void 0,u=yt(y)?y:void 0,m})})))),vae=l(2,(e,t)=>hh(e,t,(r,n)=>[r,n])),kae=l(2,(e,t)=>hh(e,t,r=>r)),Oae=l(2,(e,t)=>hh(e,t,(r,n)=>n)),_ae=l(2,(e,t)=>hh(e,t,(r,n)=>[...r,n])),Rae=e=>Gn(e,(t,r)=>[t,r]),Pae=e=>Uu(e,v,(t,r)=>{let n=0;t._tag===\"None\"&&(n=1,t=_(r[0]));let o=Qt();for(;nUu(e,v,(t,r)=>{let n=Qt();for(let o=0;oUu(e,()=>({prev:v(),current:v()}),(t,r)=>{let n=0,o;t.current._tag===\"None\"?(n=1,o=r[0],t.current=_(o)):o=t.current.value;let s=Qt();for(;nk(rb(()=>{let t=[],r=new Set,n=rn(),o=rn();return cb(ak(e.map((s,a)=>s.channel.pipe(jr,sb(i=>(t[a]=i,r.has(a)?g(Oe(t.slice())):(r.add(a),r.sizer.has(a)?ie:o.open)))),{concurrency:\"unbounded\",bufferSize:0}).pipe(gk(o.await))})),Nae=l(2,(e,t)=>_k(e,t)),Uae=l(3,(e,t,r)=>Gn(_k(e,t),([n,o])=>r(n,o))),eW=(...e)=>k(Ue((t,r)=>Y(()=>{let n,o=H0(e.map(s=>{let a=tr(r);return Bs(s.channel,a).pipe(C(i=>B0(g(i),i)),Dn(i=>i._tag===\"Success\"?n?Xe(a,i):(n=i.value[0],ie):Xe(a,i)),W(([,i])=>i))}));return L(()=>n??o)}))),Dae=l(2,(e,t)=>eW(e,t)),Lae=l(2,(e,t)=>k(MH(Eo(e),t))),$ae=l(2,(e,t)=>k(FH(Eo(e),t))),Kae=l(2,(e,t)=>k(NH(Eo(e),t))),Bae=l(2,(e,t)=>k(UH(Eo(e),t))),Rk=l(e=>Re(e[0]),_e(function*(e,t,r){let n=yield*zc,o=yield*Bs(e.channel,n),s=r?.capacity===\"unbounded\"?void 0:r?.capacity??Lz,a=yield*fo({capacity:s}),i=yield*fo({capacity:s});return yield*kt(function*(){for(;;){let c=yield*o,u=[],f=[];for(let d=0;d0){let d=Mg(a,f);d.length>0&&(p=yield*Df(Vc(a,d)))}if(u.length>0){let d=Mg(i,u);d.length>0&&(yield*Vc(i,d))}p&&(yield*xi(p))}}).pipe(Lo(c=>(Si(a,c),Si(i,c),ie)),rr(n)),[a,i]})),ph=e=>k(Ue((t,r)=>jt(xr(r,lo(e)),Zc(e)))),jae=l(e=>Re(e[0]),(e,t,r)=>W(Rk(mh(e,n=>t(n),r),n=>n,r),([n,o])=>[ph(n),ph(o)])),Hae=l(e=>Re(e[0]),(e,t,r)=>W(Rk(e,t,{capacity:r?.capacity??16}),([n,o])=>[ph(n),ph(o)])),zae=l(2,(e,t)=>t.pipe(W(r=>r?e:$a),Vi)),Wae=l(2,_e(function*(e,t){let r,n=yield*Ek(e.channel),o=nt(n,c=>(r=c,$e(c))),[s,a]=yield*vg(c=>Dk(t,o,c)),i=r?$a:js(g(n));return a&&(i=Fu(dh(a),i)),[s,i]})),qae=l(2,(e,t)=>k(oz(e.channel,t))),Jae=l(2,(e,t)=>k(nz(e.channel,t))),tW=l(2,(e,t)=>e.channel.pipe(ql(r=>t(r).channel),k)),Gae=l(2,(e,t)=>e.channel.pipe(LH(r=>t(r).channel),k)),rW=l(2,(e,t)=>e.channel.pipe(ab(t),k)),xh=l(2,(e,t)=>k(Da(e.channel,r=>t(r).channel)));var Pk=l(2,(e,t)=>e.channel.pipe(KH(t),k)),Vae=l(3,(e,t,r)=>{let n=Array.isArray(t)?o=>A(o,\"_tag\")&&t.includes(o._tag):Wt(t);return Pk(e,o=>n(o)?r(o):ie)}),Zae=l(2,(e,t)=>rW(e,r=>{let n=cd(r);return rt(n)?t(n.success):ie})),nW=l(e=>Re(e[0]),(e,t,r,n)=>k(BH(Eo(e),t,o=>r(o).channel,n&&(o=>n(o).channel)))),Mk=l(e=>Re(e[0]),(e,t,r,n)=>k(jH(Eo(e),t,o=>r(o).channel,n&&(o=>n(o).channel)))),Yae=l(e=>Re(e[0]),(e,t,r,n)=>{let o=Array.isArray(t)?s=>A(s,\"_tag\")&&t.includes(s._tag):Wt(t);return nW(e,o,r,n)}),Qae=l(e=>Re(e[0]),(e,t,r)=>{let n;return Mk(e,o=>(n??=Object.keys(t),A(o,\"_tag\")&&hg(o._tag)&&n.includes(o._tag)?j(o):q(o)),o=>t[o._tag](o),r)}),Xae=l(e=>Re(e[0]),(e,t,r,n,o)=>k(HH(Eo(e),t,r,(s,a)=>n(s,a).channel,o&&((s,a)=>o(s,a).channel)))),eie=l(e=>Re(e[0]),(e,t,r,n)=>{let o=Object.create(null);for(let a of Object.keys(r)){let i=r[a];o[a]=(c,u)=>i(c,u).channel}let s=n&&((a,i)=>n(a,i).channel);return k(zH(e.channel,t,o,s))}),tie=l(2,(e,t)=>Mk(e,r=>Wt(r,t)&&A(r,\"reason\")?j(r.reason):q(r),Jl)),oW=l(2,(e,t)=>k(WH(e.channel,t))),rie=l(3,(e,t,r)=>k($H(e.channel,t,n=>r(n).channel))),nie=l(3,(e,t,r)=>k(ib(e.channel,t,(n,o)=>r(n,o).channel))),oie=l(2,(e,t)=>k(CH(e.channel,r=>Eo(t())))),sie=l(2,(e,t)=>xh(e,r=>Mu(t(r)))),aie=e=>k(qH(e.channel)),iie=l(e=>Re(e[0]),(e,t)=>k(JH(e.channel,t))),cie=l(e=>Re(e[0]),(e,t)=>k(GH(e.channel,t))),uie=l(2,(e,t)=>k(VH(e.channel,t))),Uz=(e,t)=>Vi(W(Fo(t),r=>{let n=gr.defaultValue(),o=()=>xh(Uk(e,gr,Y(()=>n)),s=>Vi(At(W(r(s),a=>(n=a,Vi(jt(kd,o())))),()=>g(Jl(s)))));return o()})),fie=l(e=>Re(e[0]),(e,t,r)=>En(()=>{let n=r?.preventFallbackOnPartialStream??!1,o=0,s={attempt:0,stepIndex:0},a=Uk(gg,Y(()=>(s={attempt:s.attempt+1,stepIndex:o},s))),i=r?.onEvent===void 0?void 0:M0(r.onEvent,()=>s),c,u=i===void 0?D:d=>SW(bW(d,W(i.begin,m=>{c=m})),m=>L(()=>{if(c===void 0)return ie;let h=c;return c=void 0,i.end(h,m)})),f=v(),p=En(()=>{let d=t.steps[o];if(!d)return Jl(sE(f));let m=a(u(IW(e,d.provide))),h=!1;if(Ce(f)){let y=f.value,S=!1,b=m;m=En(()=>S?b:(S=!0,Jl(y))),m=Uz(m,vd(d,!1))}else{let y=vd(d,!0);m=y?Uz(m,y):m}return xh(n?EW(m,y=>(h=!0,ie)):m,y=>(o++,n&&h?Jl(y):(f=_(y),p)))});return p})),lie=l(2,(e,t)=>{let r=It(t);return r===0?$a:sW(e,(n,o)=>o===r-1)}),pie=l(3,(e,t,r)=>En(()=>{let n=Dg(t),o=BigInt(0),s=!1;return Fu(iW(e,a=>{let i=o+BigInt(a.length);return i>n?(s=!0,!1):(o=i,!0)}),En(()=>s?r():$a))})),die=l(2,(e,t)=>{let r=It(t);return r===0?$a:Uu(e,xa,(n,o)=>(Md(n,o),n.length>r&&Og(n,n.length-r),[n,La]),{onHalt(n){return yi(n)}})}),sW=l(e=>Re(e[0]),(e,t,r)=>or(e,(n,o)=>Y(()=>{let s=0,a=!1;return C(L(()=>a?ue():n),c=>{let u=c.findIndex(f=>t(f,s++));if(u>=0){a=!0;let f=c.slice(0,r?.excludeLast?u:u+1);return yt(f)?g(f):ue()}return g(c)})}))),aW=l(e=>Re(e[0]),(e,t,r)=>or(e,(n,o)=>Y(()=>{let s=0,a=!1;return kt(function*(){if(a)return yield*ue();let i=yield*n;for(let c=0;cor(e,(r,n)=>Y(()=>{let o=0,s=!1,a=C(L(()=>s?ue():r),i=>{let c=[];for(let u=0;uor(e,(r,n)=>Y(()=>{let o=!1,s=C(L(()=>o?ue():r),a=>{let i=[];for(let c=0;caW(e,(r,n)=>W(t(r,n),o=>!o),{excludeLast:!0})),Fk=l(2,(e,t)=>{let r=It(t);return r===0?e:or(e,(n,o)=>Y(()=>{let s=0,a=n.pipe(C(i=>s>=r?g(i):(s+=i.length,s<=r?a:g(i.slice(r-s)))));return a}))}),xie=l(2,(e,t)=>Fk(cW(e,(r,n)=>!t(r,n)),1)),gie=l(2,(e,t)=>Fk(uW(e,(r,n)=>W(t(r,n),o=>!o)),1)),cW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=0,a=C(r,i=>{let c=i.findIndex(u=>!t(u,s++));return c===-1?a:(o=!1,g(i.slice(c)))});return L(()=>o?a:r)}))),yie=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=C(r,a=>{let i=a.findIndex(c=>ae(t(c)));return i===-1?s:(o=!1,g(a.slice(i)))});return L(()=>o?s:r)}))),uW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s=0,a=kt(function*(){for(;;){let i=yield*r;for(let c=0;co?a:r)}))),Sie=l(2,(e,t)=>{let r=It(t);return r===0?e:or(e,(n,o)=>Y(()=>{let s=xa(),a=C(n,i=>{Md(s,i);let c=s.length-r,u=Jc(s,c);return Mr(u)?g(u):a});return a}))}),fW=e=>e.channel.pipe(os(Oe),k),lW=l(2,(e,t)=>(t=eo(t),or(e,(r,n)=>Y(()=>{let o=Qt(),s=0,a,i;return L(function c(){if(i)return $e(i);if(a===void 0)return C(r,u=>{if(o.length===0&&u.length===t)return g(u);if(o.length+u.length{if(o.length===0)return $e(c);let u=o;return i=c,o=[],g(u)}))})))),bie=l(2,(e,t)=>pW(e,t,1)),pW=l(3,(e,t,r)=>{let n=eo(t),o=eo(r);return or(e,(s,a)=>Y(()=>{let i=null,c=xa(),u=!1,f=0,p=As(s,{onSuccess(d){if(Md(c,d),f>0){let h=c.length;Og(c,f),f=Math.max(0,f-h)}if(c.length=n;)if(n===o)m.push(Jc(c,n));else{m.push(S1(c,n));let h=c.length;Og(c,o),f=Math.max(0,o-h)}return g(m)},onFailure(d){return c.length===0||u&&c.length<=n-o?$e(d):(i=d,g(Oe(yi(c))))}});return L(()=>i?$e(i):p)}))}),Eie=l(2,(e,t)=>Uu(e,Qt,(r,n)=>{let o=Qt();for(let s=0;spk(jr(e.channel),jr(t.channel),r,n).pipe(os(Oe),k)),wie=l(4,(e,t,r,n)=>k(pk(e.channel,t.channel,r,n))),Aie=l(e=>Re(e[0]),(e,t,r,n)=>k(Wl(e.channel,t,(o,s)=>{let a=Qt();for(let i=0;iRe(e[0]),(e,t,r,n)=>k(Wl(e.channel,t,(o,s)=>{let[a,i]=r(o,s);return o=a,[o,yt(i)?Oe(i):La]},n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0))),La=Qt(),Cie=l(e=>Re(e[0]),(e,t,r,n)=>e.channel.pipe(jr,Wl(t,(o,s)=>W(r(o,s),([a,i])=>[a,yt(i)?Oe(i):Qt()]),n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0),k)),Tie=l(e=>Re(e[0]),(e,t,r,n)=>e.channel.pipe(Wl(t,(o,s)=>W(r(o,s),([a,i])=>[a,yt(i)?Oe(i):La]),n?.onHalt?{onHalt(o){let s=n.onHalt(o);return yt(s)?Oe(s):La}}:void 0),k)),vie=l(3,(e,t,r)=>En(()=>{let n=t();return Fu(Mu(n),k(Wl(e.channel,()=>n,(o,s)=>{let a=Qt();for(let i=0;iEn(()=>e.channel.pipe(jr,DH(t(),r),os(Oe),k))),Oie=l(2,(e,t)=>or(e,_e(function*(r,n){let o=yield*vf,s=Nr(ct(t)),a,i,c=1/0,u=rn(),f=rn(),p=rn();yield*r.pipe(u.whenOpen,C(m=>(f.openUnsafe(),a=m,c=o.currentTimeMillisUnsafe()+s,ie)),ir({disableYield:!0}),Lo(m=>(i=m,c=o.currentTimeMillisUnsafe(),f.openUnsafe(),p.openUnsafe(),ie)),rr(n));let d=L(function m(){let h=o.currentTimeMillisUnsafe(),y=c{if(o.currentTimeMillisUnsafe(){if(i){if(a){let m=g(Oe(ax(a)));return a=void 0,m}return $e(i)}return u.openUnsafe(),f.whenOpen(d)})}))),dW=l(2,(e,t)=>{let r=t.burst??0;return t.strategy===\"enforce\"?_ie(e,t.cost,t.units,t.duration,r):Rie(e,t.cost,t.units,t.duration,r)}),_ie=(e,t,r,n,o)=>or(e,s=>qc(a=>{let i=Nr(ct(n)),c=r+o<0?Number.POSITIVE_INFINITY:r+o,u=r,f=a.currentTimeMillisUnsafe();return g(C(s,function p(d){return C(t(d),m=>{let h=a.currentTimeMillisUnsafe(),S=(h-f)/i,b=u+S*r,x=b<0?c:Math.min(b,c);return m<=x?(u=x-m,f=h,g(d)):C(s,p)})}))})),Rie=(e,t,r,n,o)=>or(e,s=>qc(a=>{let i=Nr(ct(n)),c=r+o<0?Number.POSITIVE_INFINITY:r+o,u=r,f=a.monotonicTimeNanosUnsafe();return g(C(s,p=>C(t(p),d=>{let m=a.monotonicTimeNanosUnsafe(),y=Number(m-f)/1e6/i,S=u+y*r,x=Math.min(S,c)-d;if(x>=0)return u=x,f=m,g(p);let w=-x/r,I=Math.max(0,w*i);return I>0?C(mi(I),()=>(u=x,f=m,g(p))):(u=x,f=m,g(p))})))})),Pie=l(2,(e,t)=>dW(e,{...t,cost:r=>g(t.cost(r))})),Mie=l(2,(e,t)=>fW(lW(e,t))),Fie=l(3,(e,t,r)=>Nk(e,Az(eo(t)),O0(r))),Nie=l(e=>Re(e[0]),(e,t,r)=>mW(e,_e(function*(n,o,s){for(let a=0;aRe(e[0]),(e,t,r)=>En(()=>{let n=$c();return mW(e,_e(function*(o,s,a){for(let i=0;ikk(e,_e(function*(n,o,s){let a=yield*E1();yield*xr(o,lo(a));let i=$c(),c=yield*vz({lookup:u=>Wc(fo({capacity:r?.bufferSize??4096}).pipe(Qr(f=>(Kc(i,u,f),Ln(a,[u,ph(f)])))),f=>(ci(i,u),aw(f))),idleTimeToLive:r?.idleTimeToLive??ra}).pipe(Ss(s));return yield*No({while:Cn,body:gt(C(n,u=>t(u,c,i))),step:Wr}).pipe(nt(u=>{for(let[,f]of i)Nd(f);return cr(a,u)}),rr(o)),Zc(a)})),Die=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o,s,a=Qt(),i=r.pipe(C(u=>{for(let f=0;fc?$e(c):i),u=>{if(c=u,s===void 0)return $e(u);let f=Oe([o,s]);return s=void 0,g(f)})}))),Lie=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o,s,a=L(()=>{if(s!==void 0){let c=s;return s=void 0,g(c)}return r}).pipe(Uo(c=>(o=la(c),ue()))),i=W(L(()=>t.transform(a,n)),([c,u])=>(s=u,Oe(c)));return L(()=>o||i)}))),$ie=l(2,(e,t)=>Nk(e,t,Ad)),Nk=l(3,(e,t,r)=>k(ns(_e(function*(n,o,s){let a=yield*Bs(e.channel,o),i=rn(!1),c=Symbol(),u=yield*fo({capacity:0});yield*a.pipe(i.whenOpen,C(T=>(i.closeUnsafe(),Ln(u,T))),ir,nt(T=>cr(u,T)),rr(s));let f=yield*vf,p=yield*Lc(r),d=rn(!1),m=f.currentTimeMillisUnsafe(),h=0,y=v(),S,b=T=>(d.openUnsafe()&&(h=f.currentTimeMillisUnsafe()),g(T)),x=d.await.pipe(C(()=>p(m,y)),C(([,T])=>mi(T)),C(()=>Ln(u,c)),At(()=>aw(u)),C(()=>Bc)),w=L(()=>{if(S!==void 0){let T=S;return S=void 0,b(T)}return u.state._tag===\"Open\"&&i.openUnsafe(),C(ga(u),T=>T===c?ue():b(T))}),I=C(([T,P])=>{if(d.isOpen())m+=f.currentTimeMillisUnsafe()-h;else if(u.state._tag===\"Done\")return ue();return y=_(T),S=P,g(Oe(T))});return L(()=>{if(u.state._tag===\"Done\"&&S===void 0)return u.state.exit;d.closeUnsafe();let T=I(L(()=>Dk(t,w,s)));return u.state._tag===\"Open\"?Uf(T,x):T})})))),Kie=l(2,_e(function*(e,t){let r=It(t.n),n=yield*Bie(t),o=new Array(r),s=yield*Zr;for(let a=0;aXe(i,u)),k)}return yield*Gi(e.channel,a=>XS(n,a)).pipe(Dn(a=>QS(n,a)),Lf),o})),Bie=e=>Wc(e.capacity===\"unbounded\"?YS(e):e.strategy===\"dropping\"?VS(e):e.strategy===\"sliding\"?ZS(e):GS(e),sh),hW=l(2,(e,t)=>W(CW(e,t),Wz)),jie=l(2,(e,t)=>W(Mz({acquire:hW(e,t),idleTimeToLive:t.idleTimeToLive}),r=>Vi(Fz(r)))),Hie=l(2,(e,t)=>k(fb(e.channel,t))),zie=l(2,(e,t)=>k(mk(e.channel,t))),Wie=l(2,(e,t)=>e.channel.pipe(mk(wz(t)),AH(([r,n])=>n?nb(n):Ou),k)),qie=e=>mb(AW(e)),Jie=e=>Uu(e,Qt,(t,r)=>{let n=mE(t,r);return[n,[n]]}),Gie=e=>xW(e,Z),xW=l(2,(e,t)=>or(e,(r,n)=>Y(()=>{let o=!0,s;return C(r,function a(i){let c=[],u=0;for(o&&(o=!1,s=i[0],u=1,c.push(s));uor(e,(r,n)=>Y(()=>{let o=!0,s;return C(r,_e(function*a(i){let c=[],u=0;for(o&&(o=!1,s=i[0],u=1,c.push(s));uRe(e[0]),(e,t)=>e.channel.pipe(fb(XH(t?.encoding)),k)),Yie=e=>En(()=>{let t=new TextEncoder;return Gn(e,r=>t.encode(r))}),Qie=e=>e.channel.pipe(fb(QH()),k),gW=l(2,(e,t)=>Jz(e,(r,n)=>{let o=n===0?[]:[t],s=r.length-1;for(let a=0;aMu(t.start).pipe(Fu(gW(e,t.middle)),Fu(Mu(t.end)))),ece=l(2,(e,t)=>yW(e,t,Nu(E_([!0,!1])))),yW=l(3,(e,t,r)=>k(Ue(_e(function*(n,o){let s=yield*we(jr(r.channel))(n,o),a=Symbol(),i=!1,c=!1,u=(yield*we(jr(e.channel))(n,o)).pipe(At(()=>(i=!0,g(a)))),f=(yield*we(jr(t.channel))(n,o)).pipe(At(()=>(c=!0,g(a))));return kt(function*(){for(;;){if(i&&c)return yield*ue();let p=yield*s;if(p&&i||!p&&c)continue;let d=yield*p?u:f;if(d!==a)return Oe(d)}})})))),tce=l(2,(e,t)=>k(gk(e.channel,t))),rce=l(2,(e,t)=>k(sz(e.channel,t))),SW=l(2,(e,t)=>k(uh(e.channel,t))),nce=l(2,(e,t)=>k(az(e.channel,t))),bW=l(2,(e,t)=>k(iz(e.channel,t))),EW=l(2,(e,t)=>k(yk(e.channel,r=>t(r[0])))),oce=l(2,(e,t)=>k(cz(e.channel,t))),sce=l(2,(e,t)=>k(uz(e.channel,t))),IW=l(e=>Re(e[0]),(e,t,r)=>k(fz(e.channel,t,r))),ace=l(2,(e,t)=>k(lb(e.channel,t))),ice=l(3,(e,t,r)=>k(pb(e.channel,t,r))),Uk=l(3,(e,t,r)=>k(db(e.channel,t,r))),wW=l(2,(e,t)=>k(lz(e.channel,t))),cce=l(3,(e,t,r)=>wW(e,n=>dr(n,t,r(Me(n,t))))),uce=function(){let e=Re(arguments[0]),t=e?arguments[1]:arguments[0],r=Va(e?arguments[2]:arguments[1]);if(e){let n=arguments[0];return k(Sk(n.channel,t,r))}return n=>k(Sk(n.channel,t,r))},fce=Mu({}),lce=l(3,(e,t,r)=>Gn(e,n=>({...n,[t]:r(n)})));var pce=l(e=>Re(e[0]),(e,t,r,n)=>Gl(e,o=>Gn(r(o),s=>({...o,[t]:s})),n)),dce=l(e=>Re(e[0]),(e,t,r,n)=>mh(e,o=>W(r(o),s=>({...o,[t]:s})),n)),mce=l(2,(e,t)=>Gn(e,r=>({[t]:r}))),hce=l(2,(e,t)=>vg(r=>Bs(e.channel,r).pipe(C(n=>Dk(t,n,r)),W(([n])=>n)))),Dk=(e,t,r)=>xk(e.transform(hk(t),r)),AW=e=>Pu(e.channel,()=>[],(t,r)=>{for(let n=0;nPu(e.channel,()=>0,(t,r)=>t+r.length),gce=e=>Pu(e.channel,()=>0,(t,r)=>{for(let n=0;nPu(e.channel,t,(n,o)=>{for(let s=0;sxz(e.channel,t,(n,o)=>{let s=0,a=n;return W(No({while:()=>sr(a,o[s]),step(i){a=i,s++}}),()=>a)})),bce=e=>W(mz(e.channel),Vt(k_(0))),Ece=e=>W(hz(e.channel),Vt(ax)),Ice=l(2,(e,t)=>Gi(e.channel,r=>{let n=0;return No({while:()=>nt(r[n++]),step:Wr})})),wce=l(2,(e,t)=>dz(e.channel,r=>{let n=!1,o=0;return W(No({while:()=>!n&&ot(r[o]),step(s){o++,s||(n=!0)}}),()=>!n)})),Ace=l(2,(e,t)=>Gi(e.channel,t)),xb=e=>pz(e.channel),Cce=e=>Ek(e.channel),Tce=e=>Pu(e.channel,()=>\"\",(t,r)=>t+r.join(\"\")),vce=e=>W(bk(e.channel),t=>t.buffer),kce=e=>bk(e.channel),Lk=l(e=>Re(e[0]),(e,t,r)=>{let n,o,s=!1,a=rn(!1),i=r?.signal,c=()=>o.interruptUnsafe();return new ReadableStream({start(u){o=Rd(io(Gi(nn(e.channel,f=>g(a.whenOpen(f))),f=>Y(()=>{a.closeUnsafe();for(let p=0;p{i?.removeEventListener(\"abort\",c),!s&&(f._tag===\"Failure\"&&i?.aborted!==!0?u.error(rg(f.cause)):u.close())}),i!==void 0&&o.pollUnsafe()===void 0&&(i.aborted?c():i.addEventListener(\"abort\",c,{once:!0}))},pull(){return new Promise(u=>{n=u,a.openUnsafe()})},cancel(){if(o)return s=!0,Y0(pi(Ko(o)))}},r?.strategy)}),Oce=l(e=>Re(e[0]),(e,t)=>Lk(e,Pr(),t)),_ce=l(e=>Re(e[0]),(e,t)=>W(Hc(),r=>Lk(e,r,t))),$k=l(2,(e,t)=>({[Symbol.asyncIterator](){let r=Q0(t),n=uo(t),o=so(),s,a,i,c,u=p=>{if(c)return c;let d=i;return c=r(jt(Yr(d?Ko(d):ie,Xe(o,p)),{done:!0,value:void 0})),c},f=async p=>{try{await u(p)}catch(d){await r(X0(\"Suppressed error while closing Stream async iterator\",d))}};return{async next(){if(c)return c;if(a){let m=a.next();if(!m.done)return m;a=void 0}let p=n(s??C(Bs(e.channel,o),m=>(s=m,m)));i=p;let d=await r(h1(p));if(i===p&&(i=void 0),ut(d))return a=d.value[Symbol.iterator](),a.next();if(Is(d.cause))return u(Bt);if(c&&e0(d.cause))return c;throw await f(d),rg(d.cause)},return(){return u(Bt)},async throw(p){throw await f(a0(p)),p}}}})),Rce=e=>W(Hc(),t=>$k(e,t)),Pce=e=>$k(e,Pr()),Mce=l(e=>Re(e[0]),(e,t,r)=>wk(e.channel,t,r)),Fce=l(2,(e,t)=>Sz(e.channel,t)),CW=l(2,(e,t)=>bz(e.channel,t)),Nce=l(2,(e,t)=>gz(e.channel,t)),Uce=l(2,(e,t)=>Ik(e.channel,t));var Kk=Et(\"effect/FileSystem\");var vW=Et(\"effect/Path\");function gh(e){return{_tag:\"Value\",value:e}}function yb(e,t){return{_tag:\"Record\",keys:e,value:t}}function zk(e,t){return{_tag:\"Array\",length:e,value:t}}var gb=class extends Ut(\"SourceError\"){},Du=Te(\"effect/ConfigProvider\",{defaultValue:()=>FW()}),Dce={...kr,toJSON(){return{_id:\"ConfigProvider\"}}},Lce=e=>e;function OW(e,t){let r=Object.create(Dce);return r.load=e,r.mapInput=t,r}function _W(e,t){return OW(r=>e(t(r)),r=>_W(e,n=>r(t(n))))}function RW(e,t){return OW(r=>C(e.load(r),n=>n!==void 0?g(n):t.load(r)),r=>RW(e.mapInput(r),t.mapInput(r)))}function Sb(e){return _W(e,Lce)}var jk=l(2,(e,t)=>RW(e,t)),Wk=l(2,(e,t)=>e.mapInput(t)),$ce=Wk(e=>e.map(t=>typeof t==\"number\"?t:BF(t))),Kce=l(2,(e,t)=>{let r=typeof t==\"string\"?[t]:t;return Wk(e,n=>[...r,...n])}),Bce=e=>ws(e)?pa(Du)(e):xF(Du)(e),jce=(e,t)=>pa(Du)(kt(function*(){let r=yield*Du,n=ws(e)?yield*e:e;return t?.asPrimary?jk(n,r):jk(r,n)}));function Hce(e,t){let r=t?.preserveEmptyStrings===!0;return Sb(n=>g(zce(e,n,r)))}function zce(e,t,r){let n=e;for(let o of t){if(n==null)return;if(Array.isArray(n)){if(typeof o!=\"number\"||!Number.isInteger(o)||o<0||o>=n.length)return;n=n[o];continue}if(fr(n)){if(typeof o!=\"string\"||!Object.hasOwn(n,o))return;n=n[o];continue}return}return Wce(n,r)}function Wce(e,t){if(e!=null)return typeof e==\"string\"?PW(e,t):typeof e==\"number\"||typeof e==\"boolean\"||typeof e==\"bigint\"?gh(String(e)):Array.isArray(e)?zk(e.length):fr(e)?yb(new Set(Object.keys(e))):gh(K(e))}function PW(e,t){let r=MW(e,t);return r===void 0?void 0:gh(r)}function MW(e,t){return e===\"\"&&!t?void 0:e}function qk(e,t){let r=t?.preserveEmptyStrings===!0,n=qce(e);return Sb(o=>g(Jce(n,e,o,r)))}function FW(e){let t=e?.env??{...globalThis.process?.env,...import.meta?.env};return qk(t,{preserveEmptyStrings:e?.preserveEmptyStrings})}function qce(e){let t={};for(let[r,n]of Object.entries(e)){if(n===void 0)continue;let o=r.split(\"_\"),s=t;for(let a of o){let i=s.children??=Object.create(null);s=i[a]??={}}}return t}function Jce(e,t,r,n){let o=r.map(String).join(\"_\"),s=MW(Object.hasOwn(t,o)?t[o]:void 0,n),a=Gce(e,r),i=a?.children?Object.keys(a.children):[];if(i.length===0)return s===void 0?void 0:gh(s);if(i.every(of)){let u=Math.max(...i.map(f=>parseInt(f,10)))+1;return zk(u,s)}return yb(new Set(i),s)}function Gce(e,t){if(t.length===0)return e;let r=e;for(let n of t)if(r=r?.children?.[String(n)],!r)return;return r}function NW(e,t){let r=Zce(e);return t?.expandVariables&&(r=Yce(r)),qk(r,{preserveEmptyStrings:t?.preserveEmptyStrings})}var Vce=/(?:^|^)\\s*(?:export\\s+)?([\\w.-]+)(?:\\s*=\\s*?|:\\s+?)(\\s*'(?:\\\\'|[^'])*'|\\s*\"(?:\\\\\"|[^\"])*\"|\\s*`(?:\\\\`|[^`])*`|[^#\\r\\n]+)?\\s*(?:#.*)?(?:$|$)/mg;function Zce(e){let t=Object.create(null);e=e.replace(/\\r\\n?/gm,`\n`);let r;for(;(r=Vce.exec(e))!=null;){let n=r[1],o=r[2]||\"\";o=o.trim();let s=o[0];o=o.replace(/^(['\"`])([\\s\\S]*)\\1$/gm,\"$2\"),s==='\"'&&(o=o.replace(/\\\\n/g,`\n`),o=o.replace(/\\\\r/g,\"\\r\")),t[n]=o}return t}function Yce(e){let t=Object.create(null);for(let r of Object.keys(e))t[r]=Hk(e[r],e,new Set([r])).replace(/\\\\\\$/g,\"$\");return t}function Hk(e,t,r){let n=/\\${?(\\w+)/g,o=\"\",s=0,a;for(;(a=n.exec(e))!=null;){if(a.index>0&&e[a.index-1]===\"\\\\\")continue;let[,i]=a,c=n.lastIndex,u=\"\";if(e.startsWith(\":-\",c)){c+=2;let p=c,d=0;for(;c{let a=t.join(n,...s.map(String)),i=r.readFileString(a).pipe(W(u=>PW(u.trim(),o))),c=r.readDirectory(a).pipe(W(u=>yb(new Set(u.map(f=>t.basename(f))))));return i.pipe(Uo(u=>c.pipe(Uo(f=>Bk(u)&&Bk(f)?g(void 0):F(Bk(u)?f:u)))),Do(u=>new gb({message:`Failed to read file at ${t.join(n,...s.map(String))}`,cause:u})))})}),Bk=e=>e.reason._tag===\"NotFound\";var UW=[\"All\",\"Fatal\",\"Error\",\"Warn\",\"Info\",\"Debug\",\"Trace\",\"None\"];var Gk=\"~effect/Config\",$W=e=>A(e,Gk),Zl=class{_tag=\"ConfigError\";name=\"ConfigError\";cause;constructor(t){this.cause=t}get message(){return this.cause.toString()}toString(){return`ConfigError(${this.message})`}},eue={...Lh({label:\"Config\",evaluate(e){return this.parse(e.getRef(Du))}}),[Gk]:Gk,toJSON(){return{_id:\"Config\"}}};function zs(e){let t=Object.create(eue);return t.evaluator=e,t.parse=r=>Ct(e(r,[]),jc),t}var ss=(e,t,r)=>e.evaluator(t,r),KW=l(2,(e,t)=>zs((r,n)=>W(ss(e,r,n),sr(t)))),tue=l(2,(e,t)=>zs((r,n)=>C(ss(e,r,n),mr({onSuccess:o=>ss(t(o),r,n),onFailure:o=>g(q(o))})))),rue=l(2,(e,t)=>zs((r,n)=>C(ss(e,r,n),o=>rt(o)?fn(t(o.success),j):g(q(o.failure))))),nue=l(2,(e,t)=>zs((r,n)=>As(ss(e,r,n),{onFailure:o=>{let s=r0(o);return Ce(s)&&o.reasons.every(ai)?ss(t(s.value),r,n):$e(o)},onSuccess:o=>ae(o)?ss(t(o.failure),r,n):g(o)})));function BW(e){let t=globalThis.Array.isArray(e)?e:Symbol.iterator in e?[...e]:e;return zs((r,n)=>globalThis.Array.isArray(t)?fn(Eg(t.map(o=>ss(o,r,n))),pE):fn(Eg(gc(t,o=>ss(o,r,n))),pE))}var jW=l(2,(e,t)=>zs((r,n)=>fn(ss(e,r,n),o=>ae(o)?j(t):o))),oue=e=>e.pipe(KW(_),jW(v())),HW=e=>$W(e)?e:BW(gc(e,t=>HW(t))),sue=e=>Wt(e,\"SourceError\"),aue=()=>\"\",zW=e=>t=>nt(t,r=>$e(gs(r.reasons.map(e)))),WW=(e,t)=>e.load(t).pipe(zW(r=>ai(r)?Tf(r.error).annotate(ng(r)):r),fn(r=>({provider:e,path:t,node:r,toString:aue}))),LW=(e,t)=>WW(e.provider,[...e.path,t]),Jk=(e,t)=>Oa(Jo,e,new Ke(Rt(r=>t(r)),hn())),qW=e=>{switch(e._tag){case\"Union\":return e.types.every(qW);case\"Objects\":case\"Arrays\":case\"Suspend\":return!1;default:return!0}},Vk=(e,t)=>{switch(e._tag){case\"Objects\":return t?._tag===\"Record\";case\"Arrays\":return t?._tag===\"Array\";case\"Union\":return e.types.some(r=>Vk(r,t));case\"Suspend\":return Vk(e.thunk(),t);default:return t?.value!==void 0}},iue=on(e=>{let t=new WeakSet,r=ml(n=>{switch(t.add(n),n._tag){case\"Objects\":{let o=_e(function*(s){if(s.node?._tag!==\"Record\")return;let a=s.node,i=new Set;for(let u of n.propertySignatures)typeof u.name==\"string\"&&i.add(u.name);if(n.indexSignatures.length>0){let u={};for(let f of a.keys)B(u,f,void 0);for(let f of n.indexSignatures)for(let p of Ms(u,f.parameter))typeof p==\"string\"&&i.add(p)}let c={};for(let u of i){let f=yield*LW(s,u);f.node!==void 0&&B(c,u,f)}return c});return Jk(n.recur(r,s=>s),o)}case\"Arrays\":{let o=_e(function*(s){if(s.node?._tag!==\"Array\")return;let a=[];for(let i=0;ig(o.node?.value))});return r(e)});function Tr(e,t){let r=oh(e),n=gn(r.ast),o=St(Q(iue(r.ast))),s=typeof t==\"string\"?[t]:t??[];return zs((a,i)=>{let c=[...i,...s];return WW(a,c).pipe(Ct(u=>o(u).pipe(fn(j),Kf(f=>{let p=new Zl(new Ma(c.length>0?new Ot(c,f):f));return Vk(n,u.node)?F(p):g(q(p))}))),zW(u=>QI(u)&&sue(u.defect)?Cf(new Zl(u.defect)).annotate(ng(u)):u))})}var cue=tn.check(Ls({minimum:1,maximum:65535})),uue=Jn(UW),JW=e=>qr(e)||globalThis.Array.isArray(e);function fue(e){return zs(()=>F(new Zl(e)))}function lue(e){return zs(()=>g(j(e)))}function pue(e){return Tr(H,e)}function due(e){return Tr(th,e)}function mue(e){return Tr(wu,e)}function hue(e){return Tr(Dl,e)}function xue(e){return Tr(tn,e)}function gue(e,t){return Tr(zt(e),t)}function yue(e,t){return Tr(Jn(e),t)}function Sue(e,t,r){let n=JW(t),o=n?r:t,s=Be(e),a=o?.separator??\",\",i=H.pipe(J(oh(s),{decode:q2(o),encode:Iy(hn({strict:!1}),le(c=>c.join(a)))}));return Tr(st([i,s]),n?t:void 0)}function bue(e,t,r,n){let o=JW(r),s=Na(e,t),a=pD(o?n:r),i=H.pipe(J(oh(s),{decode:a.decode,encode:Iy(hn({strict:!1}),a.encode)}));return Tr(st([s,i]),o?r:void 0)}function Eue(e){return Tr(Sv,e)}function Iue(e){return Tr(Rv,e)}function wue(e){return Tr(Kl,e)}function Aue(e){return Tr(cue,e)}function Cue(e){return Tr(uue,e)}function Tue(e){return Tr(KS(H),e)}function vue(e){return Tr(LS,e)}function kue(e){return Tr(Ll,e)}var Oue=l(2,(e,t)=>zs((r,n)=>ss(e,r,[...n,t])));var Lu={};An(Lu,{Console:()=>GW,assert:()=>_ue,clear:()=>Rue,consoleWith:()=>ur,count:()=>Pue,countReset:()=>Mue,debug:()=>Fue,dir:()=>Nue,dirxml:()=>Uue,error:()=>Due,group:()=>Lue,info:()=>$ue,log:()=>Kue,table:()=>Bue,time:()=>jue,timeLog:()=>Hue,trace:()=>zue,warn:()=>Wue,withGroup:()=>que,withTime:()=>Jue});var GW=qI,ur=e=>se(t=>e(t.getRef(GW))),_ue=(e,...t)=>ur(r=>X(()=>{r.assert(e,...t)})),Rue=ur(e=>X(()=>{e.clear()})),Pue=e=>ur(t=>X(()=>{t.count(e)})),Mue=e=>ur(t=>X(()=>{t.countReset(e)})),Fue=(...e)=>ur(t=>X(()=>{t.debug(...e)})),Nue=(e,t)=>ur(r=>X(()=>{r.dir(e,t)})),Uue=(...e)=>ur(t=>X(()=>{t.dirxml(...e)})),Due=(...e)=>ur(t=>X(()=>{t.error(...e)})),Lue=e=>ur(t=>kc(X(()=>{e?.collapsed?t.groupCollapsed(e.label):t.group(e?.label)}),()=>X(()=>{t.groupEnd()}))),$ue=(...e)=>ur(t=>X(()=>{t.info(...e)})),Kue=(...e)=>ur(t=>X(()=>{t.log(...e)})),Bue=(e,t)=>ur(r=>X(()=>{r.table(e,t)})),jue=e=>ur(t=>kc(X(()=>{t.time(e)}),()=>X(()=>{t.timeEnd(e)}))),Hue=(e,...t)=>ur(r=>X(()=>{r.timeLog(e,...t)})),zue=(...e)=>ur(t=>X(()=>{t.trace(...e)})),Wue=(...e)=>ur(t=>X(()=>{t.warn(...e)})),que=l(e=>de(e[0]),(e,t)=>ur(r=>nd(X(()=>{t?.collapsed?r.groupCollapsed(t.label):r.group(t?.label)}),()=>e,()=>X(()=>{r.groupEnd()})))),Jue=l(e=>de(e[0]),(e,t)=>ur(r=>nd(X(()=>{r.time(t)}),()=>e,()=>X(()=>{r.timeEnd(t)}))));var In={OK:200,Unauthorized:401,NotFound:404,InternalServerError:500,ServiceUnavailable:503},Zk={[In.OK]:\"OK\",[In.Unauthorized]:\"Unauthorized\",[In.NotFound]:\"Not Found\",[In.InternalServerError]:\"Internal Server Error\",[In.ServiceUnavailable]:\"Service Unavailable\"},Gue=e=>{let t=e.startsWith(\"/\"),r=[];for(let o of e.split(\"/\"))if(!(o===\"\"||o===\".\")){if(o===\"..\"){r.length>0&&r.at(-1)!==\"..\"?r.pop():t||r.push(\"..\");continue}r.push(o)}let n=r.join(\"/\");return t?`/${n}`:n||\".\"},Zi=(...e)=>Gue(e.filter(Boolean).join(\"/\")),Yl=e=>{if(e.length===0)return\".\";let t=e.length;for(;t>1&&e[t-1]===\"/\";)t-=1;let r=e.slice(0,t),n=r.lastIndexOf(\"/\");return n<0?\".\":n===0?\"/\":r.slice(0,n)},VW=e=>{if(!e.startsWith(\"/\"))throw new TypeError(\"Path must be absolute\");let t=new URL(\"file:///\");return t.pathname=e.replace(/%/g,\"%25\").replace(/\\\\/g,\"%5C\"),t};var Vue=/^[A-Za-z0-9_-]+$/u,ZW=/[*?[{]/u,bb=(e,t)=>t===e||t.startsWith(`${e.replace(/\\/+$/u,\"\")}/`),Ql=class extends an.TaggedError(\"FunctionFileSystemError\"){},Io=(e,t)=>e.lstat(t).pipe($.catch(()=>$.undefined)),$u=(e,t,r)=>$.all([e.realPath(t),e.realPath(r)],{concurrency:2}).pipe($.map(([n,o])=>bb(n,o)),$.orElseSucceed(()=>!1)),YW=(e,t,r)=>$.gen(function*(){let n=yield*Io(e,r);if(n===void 0)return!0;if(n.isSymbolicLink||!(yield*$u(e,t,r)))return!1;if(!n.isDirectory)return!0;let o=yield*e.readDirectory(r).pipe($.catch(()=>$.undefined));if(o===void 0)return!1;for(let s of o)if(!(yield*YW(e,t,Zi(r,s))))return!1;return!0}),yh=(e,t)=>t.length===0?\"\":t.startsWith(\"/\")?t:Zi(e,t),Yk=[\"deno.json\",\"deno.jsonc\"],QW=e=>Yk.includes(e.slice(e.lastIndexOf(\"/\")+1)),Zue=(e,t,r)=>$.gen(function*(){let n=Yl(Zi(r));for(;bb(t,n);){for(let s of Yk){let a=Zi(n,s),i=yield*Io(e,a);if(i!==void 0)return i.isFile&&!i.isSymbolicLink?a:void 0}let o=Yl(n);if(o===n)break;n=o}}),Yue=(e,t,r)=>$.all([e.realPath(t),e.realPath(r)],{concurrency:2}).pipe($.map(([n,o])=>n===o),$.orElseSucceed(()=>!1)),XW=$.fn(\"Functions.resolveFunctionConfig\")(function*(e){let{root:t,slug:r,overrides:n,fs:o}=e;if(!t.startsWith(\"/\")||!Vue.test(r)||r===\"_shared\"||(yield*Io(o,t))===void 0)return;let a=yield*o.realPath(t).pipe($.orElseSucceed(()=>\"\"));if(!a.startsWith(\"/\"))return;let i=yield*Io(o,a);if(i===void 0||!i.isDirectory)return;let c=e.filesRoot===void 0?a:yield*o.realPath(e.filesRoot).pipe($.orElseSucceed(()=>\"\"));if(!c.startsWith(\"/\")||!bb(c,a))return;let u=n.$default,f=n[r],p={...u,...f};if(p.enabled===!1)return;let d=Zi(a,r),m=p?.entrypointPath&&p.entrypointPath.length>0?p.entrypointPath:p.entrypoint&&p.entrypoint.length>0?p.entrypoint:\"index.ts\";if(!m.startsWith(\"/\")){let P=yield*Io(o,d);if(P===void 0||!P.isDirectory||!(yield*$u(o,a,d)))return}let h=yh(d,m);if(!(yield*$u(o,c,h)))return;let y=yield*Io(o,h);if(y===void 0||!y.isFile||y.isSymbolicLink)return;let S=f?.importMapPath??f?.import_map,b=u?.importMapRoot??u?.import_map_root,x=S!==void 0?yh(d,S):b!==void 0?yh(a,b):yh(d,\"\");if(x.length>0){if(!(yield*$u(o,c,x)))return;let P=yield*Io(o,x);if(P===void 0||!P.isFile||P.isSymbolicLink)return}else for(let P of Yk){let G=Zi(d,P),he=yield*Io(o,G);if(he!==void 0){if(!he.isFile||he.isSymbolicLink||!(yield*$u(o,c,G)))return;x=G;break}}let w=x.length===0?void 0:yield*Zue(o,c,h),I=w!==void 0&&(yield*Yue(o,w,x)),T=(p.staticFiles??p.static_files??[]).map(P=>yh(d,P));for(let P of T){if(!bb(c,P))return;let G=P.search(ZW),he=G<0?P:P.slice(0,G),me=G<0?Yl(P):he.slice(0,Math.max(0,he.lastIndexOf(\"/\")))||a;if(!(yield*YW(o,c,me)))return;if(!ZW.test(P)){let E=yield*Io(o,P);if(E!==void 0&&(!(yield*$u(o,c,P))||E.isSymbolicLink))return}}return{entrypointPath:h,importMapPath:x,importMapDiscoveredByRuntime:I,staticFiles:T,verifyJWT:p.verifyJWT??p.verify_jwt??!0,env:{...u?.env,...f?.env}}}),Que=e=>Zi(Yl(e.entrypointPath),\"package.json\"),eq=e=>{let t=new Map,r=new Map;return(n,o)=>{let s=r.get(n);if(s!==void 0)return s;let a=Yl(o.entrypointPath),i=t.get(a),c=i===void 0||i===n?a:e();return i===void 0&&t.set(a,n),r.set(n,c),c}},tq=$.fn(\"Functions.packageJsonContainedFor\")(function*(e){if(!e.root.startsWith(\"/\"))return!1;let t=yield*Io(e.fs,e.root);if(t===void 0||!t.isDirectory&&!t.isSymbolicLink)return!1;let r=yield*e.fs.realPath(e.root).pipe($.orElseSucceed(()=>\"\"));if(!r.startsWith(\"/\"))return!1;let n=yield*Io(e.fs,r);if(n===void 0||!n.isDirectory)return!1;let o=Que(e.config),s=yield*Io(e.fs,o);return s===void 0||!s.isFile||s.isSymbolicLink?!1:yield*$u(e.fs,r,o)});var Qk=new TextEncoder,Sh=new TextDecoder,Eb=new TextDecoder(\"utf-8\",{fatal:!0}),nbe=2**32;function rq(...e){let t=e.reduce((o,{length:s})=>o+s,0),r=new Uint8Array(t),n=0;for(let o of e)r.set(o,n),n+=o.length;return r}function Xl(e){let t=new Uint8Array(e.length);for(let r=0;r127)throw new TypeError(\"non-ASCII string encountered in encode()\");t[r]=n}return t}var Ib=(e,t=\"algorithm.name\")=>new TypeError(`CryptoKey does not support this operation, its ${t} must be ${e}`);function Xue(e,t){if(t&&!e.usages.includes(t))throw new TypeError(`CryptoKey does not support this operation, its usages must include ${t}.`)}function nq(e,t){let{modulusLength:r}=t.algorithm;if(typeof r!=\"number\"||r<2048)throw new TypeError(`${e} requires key modulusLength to be 2048 bits or larger`)}function oq(e,t,r){let n=e.algorithm;if(n.name!==t.name)throw Ib(t.name);if(t.hash&&n.hash?.name!==t.hash)throw Ib(t.hash,\"algorithm.hash\");if(t.namedCurve&&n.namedCurve!==t.namedCurve)throw Ib(t.namedCurve,\"algorithm.namedCurve\");if(t.length!==void 0&&n.length!==t.length)throw Ib(t.length,\"algorithm.length\");Xue(e,r)}function efe(e,t,...r){if(r.length>2){let n=r.pop();e+=`one of type ${r.join(\", \")}, or ${n}.`}else r.length===2?e+=`one of type ${r[0]} or ${r[1]}.`:e+=`of type ${r[0]}.`;return t==null?e+=` Received ${t}`:typeof t==\"function\"&&t.name?e+=` Received function ${t.name}`:typeof t==\"object\"&&t!=null&&t.constructor?.name&&(e+=` Received an instance of ${t.constructor.name}`),e}var bh=(e,t,...r)=>efe(`Key for the ${e} algorithm must be `,t,...r);var zr=class extends Error{static code=\"ERR_JOSE_GENERIC\";code=\"ERR_JOSE_GENERIC\";constructor(t,r){super(t,r),this.name=this.constructor.name,Error.captureStackTrace?.(this,this.constructor)}},Ka=class extends zr{static code=\"ERR_JWT_CLAIM_VALIDATION_FAILED\";code=\"ERR_JWT_CLAIM_VALIDATION_FAILED\";claim;reason;payload;constructor(t,r,n=\"unspecified\",o=\"unspecified\"){super(t,{cause:{claim:n,reason:o,payload:r}}),this.claim=n,this.reason=o,this.payload=r}},Eh=class extends zr{static code=\"ERR_JWT_EXPIRED\";code=\"ERR_JWT_EXPIRED\";claim;reason;payload;constructor(t,r,n=\"unspecified\",o=\"unspecified\"){super(t,{cause:{claim:n,reason:o,payload:r}}),this.claim=n,this.reason=o,this.payload=r}},wb=class extends zr{static code=\"ERR_JOSE_ALG_NOT_ALLOWED\";code=\"ERR_JOSE_ALG_NOT_ALLOWED\"},as=class extends zr{static code=\"ERR_JOSE_NOT_SUPPORTED\";code=\"ERR_JOSE_NOT_SUPPORTED\"};var wn=class extends zr{static code=\"ERR_JWS_INVALID\";code=\"ERR_JWS_INVALID\"},ep=class extends zr{static code=\"ERR_JWT_INVALID\";code=\"ERR_JWT_INVALID\"};var Ih=class extends zr{static code=\"ERR_JWKS_INVALID\";code=\"ERR_JWKS_INVALID\"},tp=class extends zr{static code=\"ERR_JWKS_NO_MATCHING_KEY\";code=\"ERR_JWKS_NO_MATCHING_KEY\";constructor(t=\"no applicable key found in the JSON Web Key Set\",r){super(t,r)}},Ab=class extends zr{[Symbol.asyncIterator]=async function*(){};static code=\"ERR_JWKS_MULTIPLE_MATCHING_KEYS\";code=\"ERR_JWKS_MULTIPLE_MATCHING_KEYS\";constructor(t=\"multiple matching keys found in the JSON Web Key Set\",r){super(t,r)}},Cb=class extends zr{static code=\"ERR_JWKS_TIMEOUT\";code=\"ERR_JWKS_TIMEOUT\";constructor(t=\"request timed out\",r){super(t,r)}},Tb=class extends zr{static code=\"ERR_JWS_SIGNATURE_VERIFICATION_FAILED\";code=\"ERR_JWS_SIGNATURE_VERIFICATION_FAILED\";constructor(t=\"signature verification failed\",r){super(t,r)}};var Xk=e=>{if(e?.[Symbol.toStringTag]===\"CryptoKey\")return!0;try{return e instanceof CryptoKey}catch{return!1}},tfe=e=>e?.[Symbol.toStringTag]===\"KeyObject\",sq=e=>Xk(e)||tfe(e);function aq(e){if(Uint8Array.fromBase64)return Uint8Array.fromBase64(e);let t=atob(e),r=new Uint8Array(t.length);for(let n=0;ntypeof o!=\"string\")||new Set(n).size!==n.length)throw new TypeError('\"key_ops\" (Key Operations) Parameter must be an array of unique strings');t.key_ops=n}return t}var nO=e=>e[Symbol.toStringTag],rfe=(e,t,r)=>{let{alg:n}=e;if(t.use!==void 0){let o=r===\"sign\"||r===\"verify\"?\"sig\":\"enc\";if(t.use!==o)throw new TypeError(`Invalid key for this operation, its \"use\" must be \"${o}\" when present`)}if(t.alg!==void 0&&t.alg!==n)throw new TypeError(`Invalid key for this operation, its \"alg\" must be \"${n}\" when present`);if(Array.isArray(t.key_ops)){let o=r===\"encrypt\"||r===\"decrypt\"?e.ops?.[r===\"encrypt\"?0:1]:r;if(o&&!t.key_ops.includes(o))throw new TypeError(`Invalid key for this operation, its \"key_ops\" must include \"${o}\" when present`)}};function nfe(e,t,r){let{alg:n,secret:o}=e,s=r===\"decrypt\"||r===\"sign\";if(o&&t instanceof Uint8Array)return[fq,t];if(Yi(t)){let a=cq(t);if(typeof a.kty!=\"string\")throw new TypeError(o?bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\",\"Uint8Array\"):bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\"));if(!(o?a.kty===\"oct\"&&typeof a.k==\"string\":a.kty!==\"oct\"&&(s?a.kty===\"AKP\"&&typeof a.priv==\"string\"||typeof a.d==\"string\":a.d===void 0&&a.priv===void 0)))throw new TypeError(o?'JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present':`JSON Web Key for this operation must be a ${s?\"private\":\"public\"} JWK`);return rfe(e,a,r),[dq,t,a]}if(!sq(t))throw new TypeError(o?bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\",\"Uint8Array\"):bh(n,t,\"CryptoKey\",\"KeyObject\",\"JSON Web Key\"));if(o){if(t.type!==\"secret\")throw new TypeError(`${nO(t)} instances for symmetric algorithms must be of type \"secret\"`)}else{if(t.type===\"secret\")throw new TypeError(`${nO(t)} instances for asymmetric algorithms must not be of type \"secret\"`);let a=s?\"private\":\"public\";if((t.type===\"public\"||t.type===\"private\")&&t.type!==a){let i=r===\"sign\"?\"signing\":r===\"verify\"?\"verifying\":`${r.slice(0,-1)}tion`;throw new TypeError(`${nO(t)} instances for asymmetric algorithm ${i} must be of type \"${a}\"`)}}return Xk(t)?[lq,t]:[pq,t]}var fq=0,lq=1,pq=2,dq=3,oO,ofe={__proto__:null,prime256v1:\"P-256\",secp384r1:\"P-384\",secp521r1:\"P-521\"};function _b(e,t,r){oO||=new WeakMap;let n=oO.get(e);return r&&(n?n[t]=r:oO.set(e,{[t]:r})),r??n?.[t]}var uq=async(e,t,r)=>_b(e,r.alg)??_b(e,r.alg,await Ob(r,{...t,alg:r.alg})),sfe=(e,t)=>{let r=_b(e,t.alg);if(r)return r;let n=e.type===\"public\",o=t.usages[n?0:1],{asymmetricKeyType:s}=e,a=ofe[e.asymmetricKeyDetails?.namedCurve],i=t.resolve?.({crv:a,asymmetricKeyType:s})??t.subtle;return _b(e,t.alg,e.toCryptoKey(i,n,o))};async function mq(e,t,r){let n=nfe(e,t,r);switch(n[0]){case fq:case lq:return n[1];case dq:{let o=n[1],s=n[2];if(s.kty===\"oct\")return wh(s.k);if(!Object.isFrozen(o)){let{key_ops:a}=o;Array.isArray(a)&&Object.freeze(a),Object.freeze(o)}return uq(o,s,e)}case pq:{let o=n[1];return o.type===\"secret\"?o.export():\"toCryptoKey\"in o&&typeof o.toCryptoKey==\"function\"?sfe(o,e):uq(o,o.export({format:\"jwk\"}),e)}}}function hq(e){let t={__proto__:null};for(let r in e)t[r]={...e[r],alg:r};return t}var xq={__proto__:null,b64:!0};function gq(e,t){if(t!==void 0&&(!Array.isArray(t)||t.some(r=>typeof r!=\"string\")))throw new TypeError(`\"${e}\" option must be an array of strings`);if(t)return new Set(t)}function yq(e,t,r,n,o){if(o.crit!==void 0&&n?.crit===void 0)throw new e('\"crit\" (Critical) Header Parameter MUST be integrity protected');if(!n||n.crit===void 0)return[];if(!Array.isArray(n.crit)||n.crit.length===0||n.crit.some(a=>typeof a!=\"string\"||a.length===0))throw new e('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');let s=r===void 0?t:{__proto__:null,...r,...t};for(let a of n.crit){if(!(a in s))throw new as(`Extension Header Parameter \"${a}\" is not recognized`);if(!Object.hasOwn(o,a)||o[a]===void 0)throw new e(`Extension Header Parameter \"${a}\" is missing`);if(s[a]&&(!Object.hasOwn(n,a)||n[a]===void 0))throw new e(`Extension Header Parameter \"${a}\" MUST be integrity protected`)}return n.crit}function Sq(e,t){if(t.includes(\"b64\")){let r=e.b64;if(typeof r!=\"boolean\")throw new wn('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');return r}return!0}async function afe(e,t,r){return t instanceof Uint8Array?crypto.subtle.importKey(\"raw\",t,e.subtle,!1,[r]):(oq(t,e.subtle,r),e.minRsaBits&&nq(e.alg,t),t)}async function bq(e,t,r,n){let o=await afe(e,t,\"verify\");try{return await crypto.subtle.verify(e.signing,o,r,n)}catch{return!1}}var Ah=[[\"verify\"],[\"sign\"]];function sO(e){let t={name:\"HMAC\",hash:`SHA-${e}`};return{kty:[\"oct\"],secret:!0,subtle:t,signing:t,usages:Ah}}function rp(e,t){let n={name:t?\"RSA-PSS\":\"RSASSA-PKCS1-v1_5\",hash:`SHA-${e}`};return{kty:[\"RSA\"],subtle:n,signing:t?{...n,saltLength:t}:n,usages:Ah,minRsaBits:2048}}function aO(e,t){return{kty:[\"EC\"],crv:e,subtle:{name:\"ECDSA\",namedCurve:e},signing:{name:\"ECDSA\",hash:`SHA-${t}`},usages:Ah}}function Eq(){let e={name:\"Ed25519\"};return{kty:[\"OKP\"],crv:\"Ed25519\",subtle:e,signing:e,usages:Ah}}function iO(e){let r={name:`ML-DSA-${e}`};return{kty:[\"AKP\"],subtle:r,signing:r,usages:Ah}}var cO=hq({HS256:sO(256),HS384:sO(384),HS512:sO(512),RS256:rp(256),RS384:rp(384),RS512:rp(512),PS256:rp(256,32),PS384:rp(384,48),PS512:rp(512,64),ES256:aO(\"P-256\",256),ES384:aO(\"P-384\",384),ES512:aO(\"P-521\",512),EdDSA:Eq(),Ed25519:Eq(),\"ML-DSA-44\":iO(44),\"ML-DSA-65\":iO(65),\"ML-DSA-87\":iO(87)});function Iq(e){let t=typeof e==\"string\"?cO[e]:void 0;if(!t)throw new as(`alg ${e} is not supported either by JOSE or your javascript runtime`);return t}function wq(e){return[e&&gq(\"algorithms\",e.algorithms),e?.crit]}function ife(e,t=e===void 0?{}:kb(e,wn,\"JWS Protected Header is invalid\")){return t}function cfe(e,t,r){let n=Sq(e,yq(wn,xq,r[1],e,t)),o=t.alg;if(typeof o!=\"string\"||!o)throw new wn('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');if(r[0]&&!r[0].has(o))throw new wb('\"alg\" (Algorithm) Header Parameter value not allowed');return[n,o]}function ufe(e){try{return Xl(e)}catch{throw new wn(\"JWS Compact Serialization payload must use only ASCII characters\")}}async function ffe(e,t,r,n,o,s,a){let i=!1;typeof r==\"function\"&&(r=await r(o,e),i=!0);let c=typeof a==\"string\",u=Iq(s),f=rq(n!==void 0?Xl(n):new Uint8Array,Xl(\".\"),c?t[2]??=iq(a,\"payload\",wn):a),p=tO(e.signature,\"signature\",wn),d=await mq(u,r,\"verify\");if(!await bq(u,d,p,f))throw new Tb;return[c?tO(a,\"payload\",wn):a,o,c,d,i]}async function Aq(e,t,r){if(e instanceof Uint8Array&&(e=Sh.decode(e)),typeof e!=\"string\")throw new wn(\"Compact JWS must be a string or Uint8Array\");let{0:n,1:o,2:s,length:a}=e.split(\".\");if(a!==3)throw new wn(\"Invalid Compact JWS\");let i={payload:o,protected:n,signature:s},c=ife(n),[u,f]=cfe(c,c,t),p=u?o:ufe(o);return ffe(i,t,r,n,c,f,p)}var lfe=e=>Math.floor(e.getTime()/1e3),pfe={s:1,m:60,h:3600,d:86400,w:604800,y:31557600},dfe=/^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i,np=\"check_failed\";function uO(){throw new TypeError(\"Invalid time period format\")}function Cq(e){typeof e!=\"string\"&&uO();let t=dfe.exec(e);(!t||t[4]&&t[1])&&uO();let r=parseFloat(t[2]),n=Math.round(r*pfe[t[3][0].toLowerCase()]);return Number.isFinite(n)||uO(),t[1]===\"-\"||t[4]===\"ago\"?-n:n}function fO(e,t){if(!Number.isFinite(t))throw new TypeError(`Invalid ${e} input`);return t}var Tq=e=>{let t=e.toLowerCase();return e.includes(\"/\")?t:`application/${t}`},mfe=(e,t)=>typeof e==\"string\"?t.includes(e):Array.isArray(e)?t.some(r=>e.includes(r)):!1;function lO(e,t,r=!1){let n=e[t];if(!(n===void 0&&!r)){if(typeof n!=\"number\")throw new Ka(`\"${t}\" claim must be a number`,e,t,\"invalid\");return n}}function pO(e,t){throw new Ka(`unexpected \"${t}\" claim value`,e,t,np)}function vq(e,t,r={}){let n;try{n=JSON.parse(Eb.decode(t))}catch{}if(!Yi(n))throw new ep(\"JWT Claims Set must be a top-level JSON object\");let{typ:o}=r;if(o!==void 0&&(typeof e.typ!=\"string\"||Tq(e.typ)!==Tq(o)))throw new Ka('unexpected \"typ\" JWT header value',n,\"typ\",np);let{requiredClaims:s=[],issuer:a,subject:i,audience:c,maxTokenAge:u}=r,f=[...s];u!==void 0&&f.push(\"iat\"),c!==void 0&&f.push(\"aud\"),i!==void 0&&f.push(\"sub\"),a!==void 0&&f.push(\"iss\");for(let x of new Set(f.reverse()))if(!Object.hasOwn(n,x))throw new Ka(`missing required \"${x}\" claim`,n,x,\"missing\");a!==void 0&&!(Array.isArray(a)?a:[a]).includes(n.iss)&&pO(n,\"iss\"),i!==void 0&&n.sub!==i&&pO(n,\"sub\"),c!==void 0&&!mfe(n.aud,typeof c==\"string\"?[c]:c)&&pO(n,\"aud\");let{clockTolerance:p}=r,d=0;if(typeof p==\"string\")d=Cq(p);else if(p!==void 0){if(typeof p!=\"number\")throw new TypeError(\"Invalid clockTolerance option type\");d=p}fO(\"clockTolerance option\",d);let{currentDate:m}=r,h=fO(\"currentDate option\",lfe(m===void 0?new Date:m)),y=lO(n,\"iat\",u!==void 0),S=lO(n,\"nbf\");if(S!==void 0&&S>h+d)throw new Ka('\"nbf\" claim timestamp check failed',n,\"nbf\",np);let b=lO(n,\"exp\");if(b!==void 0&&b<=h-d)throw new Eh('\"exp\" claim timestamp check failed',n,\"exp\",np);if(u!==void 0){let x=h-y,w=fO(\"maxTokenAge option\",typeof u==\"number\"?u:Cq(u));if(x-d>w)throw new Eh('\"iat\" claim timestamp check failed (too far in the past)',n,\"iat\",np);if(x<-d)throw new Ka('\"iat\" claim timestamp check failed (it should be in the past)',n,\"iat\",np)}return n}async function Rb(e,t,r){let n=await Aq(e,wq(r),t);if(!n[2])throw new ep(\"JWTs MUST NOT use unencoded payload\");let s={payload:vq(n[1],n[0],r),protectedHeader:n[1]};return typeof t==\"function\"?{...s,key:n[3]}:s}function hfe(e,t,r,n){let{kty:o,key_ops:s,ext:a,kid:i,alg:c,use:u,crv:f}=rO(e),p=Array.isArray(s)?[...s]:s;return(a===void 0||typeof a==\"boolean\")&&(p===void 0||Array.isArray(p)&&p.every((d,m)=>typeof d==\"string\"&&p.indexOf(d)===m)&&p.includes(\"verify\"))&&t.kty.includes(o)&&(n===void 0||typeof n==\"string\"&&n===i)&&(c===void 0?o!==\"AKP\":r===c)&&(u===void 0||u===\"sig\")&&(!t.crv||f===t.crv)}async function kq(e,t,r){let n=e.get(t)||e.set(t,{}).get(t),{alg:o}=r;if(n[o]===void 0){let s=await Ob(r,{...t,alg:o,ext:!0});if(s.type!==\"public\")throw new Ih(\"JSON Web Key Set members must be public keys\");n[o]=s}return n[o]}function Ku(e){let t;try{t=structuredClone(e)}catch{}if(!vb(t))throw new Ih(\"JSON Web Key Set malformed\");let r=new WeakMap;return Object.defineProperty(async(o,s)=>{let{alg:a,kid:i}={...o,...s?.header},c=typeof a==\"string\"?cO[a]:void 0;if(!c||c.secret)throw new as('Unsupported \"alg\" value for a JSON Web Key Set');let u=t.keys.filter(d=>hfe(d,c,a,i)),{0:f,length:p}=u;if(!p)throw new tp;if(p!==1){let d=new Ab;throw d[Symbol.asyncIterator]=async function*(){for(let m of u)try{yield await kq(r,m,c)}catch{}},d}return kq(r,f,c)},\"jwks\",{value:()=>structuredClone(t)})}function xfe(){return typeof WebSocketPair<\"u\"||typeof navigator<\"u\"&&navigator.userAgent===\"Cloudflare-Workers\"||typeof EdgeRuntime<\"u\"&&EdgeRuntime===\"vercel\"}var dO;(typeof navigator>\"u\"||!navigator.userAgent?.startsWith?.(\"Mozilla/5.0 \"))&&(dO=\"jose/v6.2.10\");var _q=Symbol();async function gfe(e,t,r,n=fetch){let o=await n(e,{method:\"GET\",signal:r,redirect:\"manual\",headers:t}).catch(s=>{throw s.name===\"TimeoutError\"?new Cb:s});if(o.status!==200)throw new zr(\"Expected 200 OK from the JSON Web Key Set HTTP response\");try{return await o.json()}catch{throw new zr(\"Failed to parse the JSON Web Key Set HTTP response as JSON\")}}var Rq=Symbol();function Ch(e,t){return Number.isFinite(e)&&Date.now(){if(d&&xfe()&&(d=void 0),!d){let x=++m,w=d=gfe(r,c,AbortSignal.timeout(s),u).then(I=>{let T=Ku(I);if(x<=h)return;y=T;let P=Date.now();f&&(f.uat=P,f.jwks=I),p=P,h=x}).finally(()=>{d===w&&(d=void 0)})}await d};return Object.defineProperties(async(x,w)=>{(!y||!Ch(p,i))&&await S();try{return await y(x,w)}catch(I){if(I instanceof tp&&!Ch(p,a))return await S(),y(x,w);throw I}},{coolingDown:{get:()=>Ch(p,a),enumerable:!0},fresh:{get:()=>Ch(p,i),enumerable:!0},reload:{value:S,enumerable:!0},reloading:{get:()=>!!d,enumerable:!0},jwks:{value:()=>y?.jwks(),enumerable:!0}})}function hO(e){let t;if(typeof e==\"string\"){let n=e.split(\".\");(n.length===3||n.length===5)&&([t]=n)}else if(typeof e==\"object\"&&e)if(\"protected\"in e)t=e.protected;else throw new TypeError(\"Token does not contain a Protected Header\");let r=\"Invalid Token or Protected Header formatting\";if(typeof t!=\"string\"||!t)throw new TypeError(r);return kb(t,TypeError,r)}var Sfe=new Set([\"HOME\",\"HOSTNAME\",\"PATH\",\"PWD\"]),Vn=$.runSync($.gen(function*(){let e=t=>t.pipe(Hr.option);return{hostPort:yield*e(Hr.String(\"SUPABASE_INTERNAL_HOST_PORT\")),hostUrl:yield*e(Hr.String(\"SUPABASE_INTERNAL_HOST_URL\")),functionsRoot:yield*e(Hr.String(\"SUPABASE_INTERNAL_FUNCTIONS_ROOT\")),filesRoot:yield*e(Hr.String(\"SUPABASE_INTERNAL_FUNCTIONS_FILES_ROOT\")),jwtSecret:yield*e(Hr.String(\"SUPABASE_INTERNAL_JWT_SECRET\")),supabaseUrl:yield*e(Hr.String(\"SUPABASE_URL\")),wallclock:yield*e(Hr.String(\"SUPABASE_INTERNAL_WALLCLOCK_LIMIT_SEC\")),publishableKey:yield*e(Hr.String(\"SUPABASE_INTERNAL_PUBLISHABLE_KEY\")),secretKey:yield*e(Hr.String(\"SUPABASE_INTERNAL_SECRET_KEY\")),functionsConfig:yield*e(Hr.String(\"SUPABASE_INTERNAL_FUNCTIONS_CONFIG\")),debug:yield*e(Hr.String(\"SUPABASE_INTERNAL_DEBUG\")),jwks:yield*e(Hr.String(\"SUPABASE_JWKS\"))}}).pipe($.provideService(Vl.ConfigProvider,Vl.fromEnvRecord(Deno.env.toObject(),{preserveEmptyStrings:!0})))),ju=(e,t=\"\")=>ye.getOrElse(e,()=>t),bfe=ju(Vn.hostPort,\"8081\"),Pq=ju(Vn.hostUrl,`http://127.0.0.1:${bfe}`),Lq=ju(Vn.functionsRoot),Efe=ju(Vn.jwtSecret),Ife=ju(Vn.supabaseUrl,\"http://127.0.0.1:54321\"),wfe=new URL(\"/auth/v1/.well-known/jwks.json\",Ife),Mq=Number.parseInt(ju(Vn.wallclock,\"400\"),10),Fq=ye.getOrUndefined(Vn.publishableKey),Nq=ye.getOrUndefined(Vn.secretKey),Ba={BootError:In.ServiceUnavailable,InvalidWorkerResponse:In.InternalServerError,WorkerLimit:546},Afe={[Ba.BootError]:\"BOOT_ERROR\",[Ba.InvalidWorkerResponse]:\"WORKER_ERROR\",[Ba.WorkerLimit]:\"WORKER_LIMIT\"},Cfe={[Ba.BootError]:\"Worker failed to boot (please check logs)\",[Ba.InvalidWorkerResponse]:\"Function exited due to an error (please check logs)\",[Ba.WorkerLimit]:\"Worker failed to respond due to a resource limit (please check logs)\"},Tfe=new Map([[Deno.errors.InvalidWorkerCreation,Ba.BootError],[Deno.errors.InvalidWorkerResponse,Ba.InvalidWorkerResponse],[Deno.errors.WorkerRequestCancelled,Ba.WorkerLimit]]),vfe=e=>{let t=Deno.errors.WorkerAlreadyRetired;return t!==void 0&&e instanceof t},kfe=(s=>(s.MissingAuthHeader=\"UNAUTHORIZED_NO_AUTH_HEADER\",s.InvalidLegacyJWT=\"UNAUTHORIZED_JWT\",s.InvalidAsymmetricJWT=\"UNAUTHORIZED_ASYMMETRIC_JWT\",s.InvalidTokenFormat=\"UNAUTHORIZED_INVALID_JWT_FORMAT\",s.UnsupportedTokenAlgorithm=\"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM\",s))(kfe||{}),Ofe=Ie.Struct({enabled:Ie.optionalKey(Ie.Boolean),verifyJWT:Ie.optionalKey(Ie.Boolean),verify_jwt:Ie.optionalKey(Ie.Boolean),entrypointPath:Ie.optionalKey(Ie.String),entrypoint:Ie.optionalKey(Ie.String),importMapPath:Ie.optionalKey(Ie.String),import_map:Ie.optionalKey(Ie.String),importMapRoot:Ie.optionalKey(Ie.String),import_map_root:Ie.optionalKey(Ie.String),staticFiles:Ie.optionalKey(Ie.Array(Ie.String)),static_files:Ie.optionalKey(Ie.Array(Ie.String)),env:Ie.optionalKey(Ie.Record(Ie.String,Ie.String))}),_fe=Ie.Record(Ie.String,Ofe),Rfe=Ie.declare(e=>typeof e==\"object\"&&e!==null&&\"keys\"in e&&Array.isArray(e.keys)&&e.keys.every(t=>typeof t==\"object\"&&t!==null)),Pfe=()=>ye.match(Vn.functionsConfig,{onNone:()=>({}),onSome:e=>$.runSync(Ie.decodeEffect(Ie.fromJsonString(_fe))(e).pipe($.orElseSucceed(()=>({}))))}),xO=Pfe();if(ye.getOrUndefined(Vn.debug)===\"true\"){let e=Object.fromEntries(Object.entries(xO).map(([t,r])=>[t,Object.fromEntries(Object.entries(r).filter(([n])=>n!==\"env\"))]));$.runSync(Lu.log(\"Functions config:\",JSON.stringify(e,null,2)))}var Bu=(e,t,r={})=>{let n={...r},o=null;return e!=null&&(typeof e==\"object\"?(n[\"Content-Type\"]=\"application/json\",o=JSON.stringify(e)):(n[\"Content-Type\"]=\"text/plain\",o=typeof e==\"string\"?e:JSON.stringify(e)??null)),new Response(o,{status:t,headers:n})},op={\"Access-Control-Allow-Origin\":\"*\",\"Access-Control-Allow-Headers\":\"authorization, x-client-info, apikey\",\"Access-Control-Expose-Headers\":\"sb-error-code\"},Uq=({code:e,message:t=\"Invalid JWT\"})=>Bu({code:e,message:t,msg:t},In.Unauthorized,{...op,\"sb-error-code\":e}),Mfe=e=>{for(let[t,r]of Tfe.entries())if(t!==void 0&&e instanceof t)return Bu({code:Afe[r],message:Cfe[r]},r,op);return Bu({code:Zk[In.InternalServerError],message:\"Request failed due to an internal server error\"},In.InternalServerError,op)};function Ffe(e){let t=e.split(\" \");return t.length===2&&t[0]===\"Bearer\"?t[1]:null}var Nfe=e=>{let t=e.headers.get(\"authorization\"),r=e.headers.get(\"sb-api-key\")?.replace(\"Bearer\",\"\").trim();if(!t&&!r)return{code:\"UNAUTHORIZED_NO_AUTH_HEADER\",message:\"Missing authorization header\"};let n=Ffe(t??\"\"),o=!n||n.startsWith(\"sb_\")?r:n;return o||{code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"}},sp=class extends an.TaggedError(\"BootstrapOperationError\"){},Ufe=$.runSync(ye.match(Vn.jwks,{onNone:()=>$.succeed(ye.some(Ku({keys:[]}))),onSome:e=>$.gen(function*(){let t=yield*Ie.decodeEffect(Ie.fromJsonString(Rfe))(e);return yield*$.try({try:()=>Ku(t),catch:r=>new sp({cause:r})})}).pipe($.option)})),Dfe=ye.getOrElse(Ufe,()=>mO(wfe)),Qi=e=>$.tryPromise({try:e,catch:t=>new sp({cause:t})}),Lfe=e=>$.gen(function*(){return yield*Qi(()=>Rb(e,Dfe)),ye.none()}).pipe($.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_ASYMMETRIC_JWT\"})));function $fe(e,t){return $.gen(function*(){let r=yield*$.try({try:()=>hO(t).alg,catch:n=>new sp({cause:n})});return r?r===\"HS256\"?yield*Qi(()=>Rb(t,new TextEncoder().encode(e))).pipe($.as(ye.none()),$.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_JWT\"}))):r===\"ES256\"||r===\"RS256\"?yield*Lfe(t):ye.some({code:\"UNAUTHORIZED_UNSUPPORTED_TOKEN_ALGORITHM\",message:`Unsupported JWT algorithm ${r}`}):ye.some({code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"})}).pipe($.orElseSucceed(()=>ye.some({code:\"UNAUTHORIZED_INVALID_JWT_FORMAT\",message:\"Invalid JWT format\"})))}var $q={lstat:e=>Qi(()=>Deno.lstat(e)).pipe($.mapError(t=>new Ql({cause:t})),$.map(t=>({isDirectory:t.isDirectory,isFile:t.isFile,isSymbolicLink:t.isSymlink}))),realPath:e=>Qi(()=>Deno.realPath(e)).pipe($.mapError(t=>new Ql({cause:t}))),readDirectory:e=>Hs.suspend(()=>Hs.fromAsyncIterable(Deno.readDir(e),t=>new sp({cause:t})).pipe(Hs.map(t=>t.name))).pipe(Hs.runCollect,$.mapError(t=>new Ql({cause:t})))},Kfe=e=>XW({root:Lq,filesRoot:ye.getOrUndefined(Vn.filesRoot),slug:e,overrides:xO,fs:$q}),Dq=new Set,Bfe=(e,t)=>t.importMapDiscoveredByRuntime||!QW(t.importMapPath)||Dq.has(e)?$.void:$.sync(()=>Dq.add(e)).pipe($.andThen(Lu.warn(`[functions] ${e}: ${t.importMapPath} is not the nearest Deno config of ${t.entrypointPath}, so Edge Runtime loads it as a plain import map without comments or jsr:/npm: subpath imports. Move it next to the entrypoint or into a parent directory without a closer deno.json(c).`))),jfe=eq(()=>Deno.makeTempDirSync({prefix:\"supabase-worker-\"})),Hfe=e=>e.importMapPath?$.succeed(!1):tq({root:ju(Vn.filesRoot,Lq),config:e,fs:$q}),Kq=e=>Hs.fromEffectRepeat(Qi(()=>e.read()).pipe($.flatMap(t=>t.done?er.done():$.succeed(t.value)))),zfe=e=>e===void 0?$.void:Hs.runDrain(Kq(e)).pipe($.ignore);function Wfe(e,t){let r=new URL(e.url),n=e.headers.get(\"x-forwarded-host\");n&&(r.hostname=n);let o=new Request(r.href,{method:e.method,headers:e.headers,body:t===void 0?null:Hs.toReadableStream(Kq(t)),signal:e.signal,duplex:\"half\"});return o.headers.delete(\"sb-api-key\"),EdgeRuntime.applySupabaseTag(e,o),o}Deno.serve({handler:e=>$.runPromiseExit($.gen(function*(){let t=yield*$.acquireRelease($.sync(()=>e.body?.getReader()),u=>$.interruptible(zfe(u))),{pathname:r}=new URL(e.url);if(r===\"/_internal/health\")return Bu({message:\"ok\"},In.OK);if(r===\"/_internal/metric\")return Response.json(yield*Qi(()=>EdgeRuntime.getRuntimeMetrics()));let n=r.split(\"/\")[1];if(!n)return Bu(\"Function not found\",In.NotFound,op);let o=yield*Kfe(n);if(!o)return Bu(\"Function not found\",In.NotFound,op);if(yield*Bfe(n,o),e.method!==\"OPTIONS\"&&o.verifyJWT){let u=Nfe(e);if(typeof u!=\"string\")return Uq(u);let f=yield*$fe(Efe,u);if(ye.isSome(f))return Uq(f.value)}let s={...Deno.env.toObject(),...Object.fromEntries(Object.entries(o.env??{}).filter(([u])=>!u.startsWith(\"SUPABASE_\"))),SUPABASE_FUNCTION_SLUG:n};Fq&&(s.SUPABASE_PUBLISHABLE_KEYS=yield*Ie.encodeEffect(Ie.fromJsonString(Ie.Unknown))({default:Fq})),Nq&&(s.SUPABASE_SECRET_KEYS=yield*Ie.encodeEffect(Ie.fromJsonString(Ie.Unknown))({default:Nq}));let a=Object.entries(s).filter(([u])=>!Sfe.has(u)&&!u.startsWith(\"SUPABASE_INTERNAL_\")),i=!(yield*Hfe(o));return yield*$.gen(function*(){let u=yield*Qi(()=>EdgeRuntime.userWorkers.create({servicePath:jfe(n,o),memoryLimitMb:256,workerTimeoutMs:Number.isFinite(Mq)?Mq*1e3:4e5,noModuleCache:!1,noNpm:i,envVars:a,forceCreate:!0,customModuleRoot:\"\",cpuTimeSoftLimitMs:1e3,cpuTimeHardLimitMs:2e3,decoratorType:\"tc39\",maybeEntrypoint:VW(o.entrypointPath).href,context:{useReadSyncFileAPI:!0,...o.importMapPath===\"\"||o.importMapDiscoveredByRuntime?{}:{importMapPath:o.importMapPath}},staticPatterns:o.staticFiles}));return yield*Qi(()=>u.fetch(Wfe(e,t)))}).pipe($.retry({times:1,while:({cause:u})=>e.body===null&&vfe(u)}),$.catchTag(\"BootstrapOperationError\",({cause:u})=>Lu.error(\"[functions] worker error\",u).pipe($.andThen($.succeed(Mfe(u))))))}).pipe($.scoped),{signal:e.signal}).then(t=>{if(Or.isSuccess(t))return t.value;if(e.signal.aborted&&er.hasInterruptsOnly(t.cause))return new Response(null,{status:499});throw er.squash(t.cause)}),onListen:()=>{let t=Object.keys(xO).slice(0,5).map(r=>` - ${Pq}/functions/v1/${r}`);$.runSync(Lu.log(`Serving functions on ${Pq}/functions/v1/${t.length?`\n${t.join(`\n`)}`:\"\"}\nUsing ${Deno.version.deno}`))},onError:()=>Bu({code:Zk[500],message:\"Request failed due to an internal server error\"},500,op)});export{kfe as RequestErrors,Ffe as extractBearerToken,Wfe as prepareUserRequest};\n"; diff --git a/packages/stack/src/functions/serve.main.ts b/packages/stack/src/functions/serve.main.ts index 1082e4c9ad..6bbd6b4c04 100644 --- a/packages/stack/src/functions/serve.main.ts +++ b/packages/stack/src/functions/serve.main.ts @@ -76,6 +76,7 @@ const bootstrapConfig = Effect.runSync( const read = (config: Config.Config) => config.pipe(Config.option); return { hostPort: yield* read(Config.String("SUPABASE_INTERNAL_HOST_PORT")), + hostUrl: yield* read(Config.String("SUPABASE_INTERNAL_HOST_URL")), functionsRoot: yield* read(Config.String("SUPABASE_INTERNAL_FUNCTIONS_ROOT")), filesRoot: yield* read(Config.String("SUPABASE_INTERNAL_FUNCTIONS_FILES_ROOT")), jwtSecret: yield* read(Config.String("SUPABASE_INTERNAL_JWT_SECRET")), @@ -97,6 +98,8 @@ const bootstrapConfig = Effect.runSync( const valueOr = (value: Option.Option, fallback = "") => Option.getOrElse(value, () => fallback); const HOST_PORT = valueOr(bootstrapConfig.hostPort, "8081"); +/* The host's HTTPS API origin when the stack serves TLS, otherwise plain loopback on its port. */ +const HOST_URL = valueOr(bootstrapConfig.hostUrl, `http://127.0.0.1:${HOST_PORT}`); const FUNCTIONS_ROOT = valueOr(bootstrapConfig.functionsRoot); const JWT_SECRET = valueOr(bootstrapConfig.jwtSecret); const SUPABASE_URL = valueOr(bootstrapConfig.supabaseUrl, "http://127.0.0.1:54321"); @@ -516,12 +519,10 @@ Deno.serve({ }), onListen: () => { const names = Object.keys(configured); - const examples = names - .slice(0, 5) - .map((name) => ` - http://127.0.0.1:${HOST_PORT}/functions/v1/${name}`); + const examples = names.slice(0, 5).map((name) => ` - ${HOST_URL}/functions/v1/${name}`); Effect.runSync( Console.log( - `Serving functions on http://127.0.0.1:${HOST_PORT}/functions/v1/${examples.length ? `\n${examples.join("\n")}` : ""}\nUsing ${Deno.version.deno}`, + `Serving functions on ${HOST_URL}/functions/v1/${examples.length ? `\n${examples.join("\n")}` : ""}\nUsing ${Deno.version.deno}`, ), ); }, diff --git a/packages/stack/src/host/Endpoints.ts b/packages/stack/src/host/Endpoints.ts index 4778908b84..b10254998f 100644 --- a/packages/stack/src/host/Endpoints.ts +++ b/packages/stack/src/host/Endpoints.ts @@ -219,7 +219,8 @@ export const backendAddress = (endpoint: ServiceEndpoint): BackendAddress => ? { path: endpoint.path } : { host: endpoint.host ?? "127.0.0.1", port: endpoint.port }; -export const publicUrl = (host: string, port: number) => `http://${host}:${port}`; +export const publicUrl = (host: string, port: number, scheme: "http" | "https" = "http") => + `${scheme}://${host}:${port}`; const postgresUrl = ( host: string, @@ -233,6 +234,7 @@ const postgresUrl = ( interface EndpointAddress { readonly host: string; readonly port: number; + readonly scheme?: "https"; } export type EndpointAddressFor = ( @@ -252,12 +254,14 @@ export const outputsFor = ( address: EndpointAddressFor, ): Readonly>> => { const output = (name: string) => - address(name, "runtime").pipe(Effect.map(({ host, port }) => publicUrl(host, port))); + address(name, "runtime").pipe( + Effect.map(({ host, port, scheme }) => publicUrl(host, port, scheme)), + ); const outputs: Record> = {}; if (endpointNames(creation).includes("http")) { outputs.url = output("http"); outputs.hostUrl = address("http", "host").pipe( - Effect.map(({ host, port }) => publicUrl(host, port)), + Effect.map(({ host, port, scheme }) => publicUrl(host, port, scheme)), ); outputs.runtimeUrl = output("http"); } @@ -268,6 +272,7 @@ export const outputsFor = ( if (creation.service === "database" && endpointNames(creation).includes("sql")) { for (const [name, role, database] of [ ["databaseUrl", "supabase_admin", "postgres"], + ["functionsDatabaseUrl", "postgres", "postgres"], ["authenticatorUrl", "authenticator", "postgres"], ["authDatabaseUrl", "supabase_auth_admin", "postgres"], ["storageDatabaseUrl", "supabase_storage_admin", "postgres"], @@ -292,8 +297,8 @@ export const credentialsFor = Effect.fn("Endpoints.credentialsFor")(function* = {}; if (endpointNames(creation).includes("http")) { - const { host, port } = yield* address("http", from); - const origin = publicUrl(host, port); + const { host, port, scheme } = yield* address("http", from); + const origin = publicUrl(host, port, scheme); credentials.url = `${origin}${apiRoute(creation.service) ?? ""}`; if (apiRoute(creation.service) !== undefined) credentials.apiUrl = origin; } @@ -316,6 +321,7 @@ export const credentialsFor = Effect.fn("Endpoints.credentialsFor")(function* {} +export const ApiTls = Schema.Struct({ cert: Schema.String, key: Schema.String }); +export type ApiTls = Schema.Schema.Type; + export const StackCredentials = Schema.Struct({ jwtSecret: Schema.String, postgresRootKey: Schema.String, @@ -71,6 +74,8 @@ export const SavedStack = Schema.Struct({ ), composition: CompositionConfig, credentials: Schema.optionalKey(StackCredentials), + /** The pair the shared API port serves HTTPS with; absent is plain. */ + apiTls: Schema.optionalKey(ApiTls), }); export interface SavedStack extends Schema.Schema.Type {} diff --git a/packages/stack/src/runtime/ApiTlsSupport.integration.test.ts b/packages/stack/src/runtime/ApiTlsSupport.integration.test.ts new file mode 100644 index 0000000000..4c52ef4cdf --- /dev/null +++ b/packages/stack/src/runtime/ApiTlsSupport.integration.test.ts @@ -0,0 +1,349 @@ +import { NodeServices } from "@effect/platform-node"; +import { describe, expect, it } from "@effect/vitest"; +import { Data, Effect, FileSystem, Path, Ref } from "effect"; +import { ChildProcess, ChildProcessSpawner } from "effect/process"; +import { createServer, type Socket } from "node:net"; +import { API_TLS_CHECK_PATH, makeHttpProxy } from "../HttpProxy.ts"; +import { apiTlsRuntimeLabel, checkApiTlsReach, probeApiTls } from "./ApiTlsSupport.ts"; +import { hostBash, onCi } from "../../tests/api-tls.ts"; +import { DOCKER_HOST_ALIAS, type EngineTarget } from "./Container.ts"; + +/* The probe needs bash >= 4 on this host; without one these tests skip, and fail on CI. */ +const bash = await Effect.runPromise(hostBash.pipe(Effect.provide(NodeServices.layer))); +const ci = Effect.runSync(onCi); + +/* A container the fake engine lists, with its labels as `key=value`. */ +interface ListedContainer { + readonly name: string; + readonly labels: ReadonlyArray; +} + +/* Answers the engine's `ps` with `containers`, keeping only listed ones carrying every filtered + label, and runs its `exec` scripts with this host's bash, where the stack alias is loopback, so + the probe reaches the API port as a database container would; a `refusing` engine fails each + exec, and a `writeAfterReset` engine holds the request until the listener reset the + connection, failing the exec with 97 when no reset arrives. `commands` records every engine + command. */ +const engineOnHost = ( + containers: string | ReadonlyArray, + commands: Array> = [], + refusing = false, + writeAfterReset = false, +) => + Effect.gen(function* () { + const delegate = yield* ChildProcessSpawner.ChildProcessSpawner; + if (bash === undefined) + return yield* Effect.die( + "the start check probe tests need bash >= 4 on PATH, /opt/homebrew/bin or /usr/local/bin (macOS ships 3.2: `brew install bash`)", + ); + return ChildProcessSpawner.make((command) => { + if (!ChildProcess.isStandardCommand(command)) return delegate.spawn(command); + commands.push(command.args.map(String)); + const [verb] = command.args; + if (verb === "ps") { + const args = command.args.map(String); + const filters = args.flatMap((arg, index) => + args[index - 1] === "--filter" && arg.startsWith("label=") ? [arg.slice(6)] : [], + ); + const listed = + typeof containers === "string" + ? containers + : containers + .filter(({ labels }) => filters.every((label) => labels.includes(label))) + .map(({ name }) => `${name}\n`) + .join(""); + return delegate.spawn(ChildProcess.make("printf", ["%s", listed])); + } + if (refusing) + return delegate.spawn( + ChildProcess.make(bash, ["-c", "printf 'Error: container is not running' >&2; exit 1"]), + ); + const script = command.args.at(-1); + const held = writeAfterReset + ? `printf() { unset -f printf; IFS= read -r -t 5 -u 3 _; [ $? -eq 1 ] || exit 97; builtin printf "$@"; }; ` + : ""; + return delegate.spawn( + ChildProcess.make(bash, [ + "-c", + typeof script === "string" + ? `${held}${script.replaceAll(DOCKER_HOST_ALIAS, "127.0.0.1")}` + : "", + ]), + ); + }); + }); + +/* The API port serving TLS, whose readiness route answers with what `answering` arms. */ +const tlsProxy = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const certs = path.join(import.meta.dirname, "..", "..", "tests", "certs"); + const armed = yield* Ref.make(undefined); + const proxy = yield* makeHttpProxy({ + host: "127.0.0.1", + port: 0, + tls: { + cert: yield* fs.readFileString(path.join(certs, "trusted.crt")), + key: yield* fs.readFileString(path.join(certs, "localhost.key")), + check: Ref.get(armed), + }, + }); + const answering = (body: string, check: Effect.Effect) => + Effect.acquireUseRelease( + Ref.set(armed, body), + () => check, + () => Ref.set(armed, undefined), + ); + return { port: proxy.port, armed, answering }; +}); + +class ApiTlsTestError extends Data.TaggedError("ApiTlsTestError")<{ readonly message: string }> {} + +/* A raw listener on loopback that hands each accepted connection, once its request arrived or on + accept, to `reply`; it never closes what `reply` leaves open until the scope ends. */ +const rawPort = (reply: (socket: Socket) => void, onAccept = false) => + Effect.gen(function* () { + const sockets = new Set(); + const server = createServer((socket) => { + sockets.add(socket); + socket.on("error", () => socket.destroy()); + if (onAccept) reply(socket); + else socket.once("data", () => reply(socket)); + }); + return yield* Effect.acquireRelease( + Effect.callback((resume) => { + const onError = (cause: Error) => + resume(Effect.fail(new ApiTlsTestError({ message: cause.message }))); + server.once("error", onError); + server.listen(0, "127.0.0.1", () => { + server.off("error", onError); + const address = server.address(); + resume( + address === null || typeof address === "string" + ? Effect.fail(new ApiTlsTestError({ message: "no address" })) + : Effect.succeed(address.port), + ); + }); + return Effect.sync(() => server.off("error", onError)); + }), + () => + Effect.callback((resume) => { + server.close(() => resume(Effect.void)); + for (const socket of sockets) socket.destroy(); + }), + ); + }); + +const target: EngineTarget = { engine: "docker", argv: [], daemonId: "test" }; +const stack = { id: "stack", root: "/data/stack", database: "db-instance" }; +const body = "supabase-stack stack 3f1c"; + +class StopError extends Data.TaggedError("StopError")<{ readonly message: string }> {} + +/* The start check on `port`, arming the readiness route through `answering` while it probes. */ +const reach = (options: { + readonly port: number; + readonly answering?: (body: string, check: Effect.Effect) => Effect.Effect; + readonly stop: Effect.Effect; + readonly containers?: string; + readonly refusing?: boolean; + readonly writeAfterReset?: boolean; + readonly readSeconds?: number; +}) => + Effect.gen(function* () { + return yield* checkApiTlsReach({ + spawner: yield* engineOnHost( + options.containers ?? "stack-db\n", + [], + options.refusing, + options.writeAfterReset, + ), + target, + stack, + runtime: "test runtime", + port: options.port, + path: API_TLS_CHECK_PATH, + answering: options.answering ?? ((_body: string, check: Effect.Effect) => check), + body: Effect.succeed(body), + stop: options.stop, + ...(options.readSeconds === undefined ? {} : { readSeconds: options.readSeconds }), + }); + }); + +describe.skipIf(bash === undefined && !ci)("start check probe over this host's bash", () => { + it.live("passes start when the database container reads this check's readiness reply", () => + Effect.scoped( + Effect.gen(function* () { + const { port, armed, answering } = yield* tlsProxy; + let stops = 0; + yield* reach({ + port, + answering, + stop: Effect.sync(() => { + stops += 1; + }), + }); + expect(stops).toBe(0); + /* The route is armed only while the probe runs. */ + expect(yield* Ref.get(armed)).toBeUndefined(); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.live("stops the stack and fails start on a close, a timeout or another reply", () => + Effect.scoped( + Effect.gen(function* () { + const { port } = yield* tlsProxy; + let stops = 0; + const stop = Effect.sync(() => { + stops += 1; + }); + const failed = (options: Omit[0], "stop">) => + Effect.flip(reach({ ...options, stop })).pipe(Effect.map(({ message }) => message)); + const foreign = (on: number, detail: string) => + `api.tls: the api port ${on} on test runtime isn't answering this stack's start check (${detail}); its services stopped: check what else listens on port ${on}, then start the stack again`; + + const unsupported = + "api.tls: unsupported networking on test runtime: containers must reach the api from loopback (the database container's plain request was closed without a reply); its services stopped: turn off `[api.tls]`, or use a runtime whose containers reach this host from loopback (on macOS: Docker Desktop, colima or Podman machine), then start the stack again"; + const closing = yield* rawPort((socket) => socket.end()); + expect(yield* failed({ port: closing })).toBe(unsupported); + const resetting = yield* rawPort((socket) => socket.resetAndDestroy(), true); + expect(yield* failed({ port: resetting, writeAfterReset: true })).toBe(unsupported); + const silent = yield* rawPort(() => undefined); + expect(yield* failed({ port: silent, readSeconds: 1 })).toBe( + foreign(silent, "no complete reply within 1 s"), + ); + /* Unarmed, the readiness path is an unknown route. */ + expect(yield* failed({ port })).toBe(foreign(port, "replied HTTP/1.1 404 Not Found")); + expect(stops).toBe(4); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.live("names what failed when the probe can't run, and the stack that did not stop", () => + Effect.scoped( + Effect.gen(function* () { + const { port, answering } = yield* tlsProxy; + let stops = 0; + const stop = Effect.sync(() => { + stops += 1; + }); + const unreachable = (detail: string) => + `api.tls: containers can't reach the api port ${port} on test runtime (${detail}); its services stopped: let test runtime containers reach the api port, or turn off \`[api.tls]\`, then start the stack again`; + expect((yield* Effect.flip(reach({ port, answering, stop, containers: "" }))).message).toBe( + unreachable("no database container"), + ); + expect((yield* Effect.flip(reach({ port, answering, stop, refusing: true }))).message).toBe( + unreachable( + `probe failed for ${DOCKER_HOST_ALIAS}:${port}: Error: container is not running`, + ), + ); + expect(stops).toBe(2); + const stuck = yield* Effect.flip( + reach({ port, stop: Effect.fail(new StopError({ message: "engine gone" })) }), + ); + expect(stuck.message).toBe( + `api.tls: the api port ${port} on test runtime isn't answering this stack's start check (replied HTTP/1.1 404 Not Found); its services did not stop (engine gone), run \`supabase stack stop --stack-id stack\` to stop them`, + ); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); + + it.live( + "probes from the primary database container, never a one-off job or data helper of the stack", + () => + Effect.scoped( + Effect.gen(function* () { + const { port, answering } = yield* tlsProxy; + const commands: Array> = []; + const instance = [ + "com.supabase.stack=stack", + "com.supabase.stack-root=/data/stack", + "com.supabase.instance=db-instance", + ]; + yield* answering( + body, + probeApiTls( + yield* engineOnHost( + [ + { + name: "supabase-db-helper-1c2d3e4f", + labels: [...instance, "com.docker.compose.service=database-helper"], + }, + { + name: "supabase-app-database-task-0a1b2c3d4e5f", + labels: [...instance, "com.supabase.service=database"], + }, + { + name: "supabase-app-database-9f8e7d6c5b4a", + labels: [...instance, "com.supabase.service=database"], + }, + ], + commands, + ), + target, + stack, + "test runtime", + { port, path: API_TLS_CHECK_PATH, body }, + ), + ); + expect(commands[0]).toEqual([ + "ps", + "--filter", + "label=com.supabase.stack=stack", + "--filter", + "label=com.supabase.stack-root=/data/stack", + "--filter", + "label=com.supabase.instance=db-instance", + "--filter", + "label=com.supabase.service=database", + "--format", + "{{.Names}}", + ]); + expect(commands.slice(1).map((args) => args.slice(0, 2))).toEqual([ + ["exec", "supabase-app-database-9f8e7d6c5b4a"], + ]); + const none = yield* Effect.flip( + probeApiTls( + yield* engineOnHost("supabase-app-database-task-0a1b2c3d4e5f\n"), + target, + stack, + "test runtime", + { port, path: API_TLS_CHECK_PATH, body }, + ), + ); + expect(none.detail).toBe("no database container"); + }), + ).pipe(Effect.provide(NodeServices.layer)), + ); +}); + +it.live("has nothing to check while the API serves no TLS, and stops nothing", () => + Effect.gen(function* () { + let stops = 0; + yield* checkApiTlsReach({ + spawner: yield* ChildProcessSpawner.ChildProcessSpawner, + target, + stack, + runtime: "test runtime", + port: undefined, + path: API_TLS_CHECK_PATH, + answering: (_body, check) => check, + body: Effect.succeed(body), + stop: Effect.sync(() => { + stops += 1; + }), + }); + expect(stops).toBe(0); + }).pipe(Effect.provide(NodeServices.layer)), +); + +it("names the runtime by the host OS and the engine, rootless Podman included", () => { + expect(apiTlsRuntimeLabel(target, "linux")).toBe("linux docker"); + expect(apiTlsRuntimeLabel({ ...target, engine: "podman", rootless: true }, "darwin")).toBe( + "macos rootless podman", + ); + expect(apiTlsRuntimeLabel({ ...target, engine: "podman", rootless: false }, "win32")).toBe( + "windows podman", + ); +}); diff --git a/packages/stack/src/runtime/ApiTlsSupport.ts b/packages/stack/src/runtime/ApiTlsSupport.ts new file mode 100644 index 0000000000..7e8c49aced --- /dev/null +++ b/packages/stack/src/runtime/ApiTlsSupport.ts @@ -0,0 +1,194 @@ +import { Data, Effect } from "effect"; +import type { ChildProcessSpawner } from "effect/process"; +import { DOCKER_HOST_ALIAS, runRaw, type EngineTarget } from "./Container.ts"; + +const platformName = (platform: NodeJS.Platform) => + platform === "darwin" ? "macos" : platform === "win32" ? "windows" : platform; + +/** The runtime a failed start check names, like `macos rootless podman`. */ +export const apiTlsRuntimeLabel = ( + target: EngineTarget, + platform: NodeJS.Platform = process.platform, +) => { + const rootless = target.engine === "podman" && target.rootless ? "rootless " : ""; + return `${platformName(platform)} ${rootless}${target.engine}`; +}; + +/** The stack the start check probes from, by its primary database instance. */ +interface ApiTlsStack { + readonly id: string; + readonly root: string; + readonly database: string | undefined; +} + +class ApiTlsCheckError extends Data.TaggedError("ApiTlsCheckError")<{ + readonly message: string; + /** What the probe saw: no database container, the engine's error, or the reply. */ + readonly detail: string; + /** What to do once the stack's services stopped. */ + readonly next: string; +}> {} + +/** + * Classifies the probe's output, ` `: only status 1 (the end of the reply) + * with a 200 and exactly `body` passes; above 128 is a timeout, 0 a NUL byte. + */ +export const readApiTlsCheck = ( + output: string, + body: string, + readSeconds: number, +): + | { readonly outcome: "passed" } + | { readonly outcome: "closed" } + | { readonly outcome: "foreign"; readonly detail: string } => { + const space = output.indexOf(" "); + const status = output.slice(0, space); + const reply = output.slice(space + 1); + if (reply === "" && status === "1") return { outcome: "closed" }; + if (Number(status) > 128) + return { outcome: "foreign", detail: `no complete reply within ${readSeconds} s` }; + const [head = "", ...rest] = reply.split("\r\n\r\n"); + const statusLine = (head.split("\r\n")[0] ?? "").slice(0, 40).replace(/[^\x20-\x7e]/gu, "?"); + if (!/^HTTP\/1\.[01] 200\b/u.test(statusLine)) + return { + outcome: "foreign", + detail: statusLine === "" ? "replied without a status line" : `replied ${statusLine}`, + }; + if (status !== "1") return { outcome: "foreign", detail: "a 200 with a NUL byte" }; + return rest.join("\r\n\r\n") === body + ? { outcome: "passed" } + : { outcome: "foreign", detail: "a 200 with another body" }; +}; + +/** + * One plain `GET` from the running database container to the API port's readiness route, read to + * its end. Bash builtins only: the slim image has no coreutils. + */ +export const probeApiTls = Effect.fn("ApiTlsSupport.probe")(function* ( + spawner: ChildProcessSpawner.ChildProcessSpawner["Service"], + target: EngineTarget, + stack: ApiTlsStack, + runtime: string, + check: { readonly port: number; readonly path: string; readonly body: string }, + readSeconds = 5, +) { + const failed = (message: string, detail: string, next: string) => + new ApiTlsCheckError({ message, detail, next }); + const unreachable = (detail: string) => + failed( + `api.tls: containers can't reach the api port ${check.port} on ${runtime}`, + detail, + `let ${runtime} containers reach the api port, or turn off \`[api.tls]\`, then start the stack again`, + ); + if (stack.database === undefined) return yield* unreachable("no database container"); + const names = yield* runRaw( + spawner, + target.engine, + [ + "ps", + "--filter", + `label=com.supabase.stack=${stack.id}`, + "--filter", + `label=com.supabase.stack-root=${stack.root}`, + "--filter", + `label=com.supabase.instance=${stack.database}`, + "--filter", + "label=com.supabase.service=database", + "--format", + "{{.Names}}", + ], + target.argv, + ).pipe(Effect.mapError((error) => unreachable(error.message))); + /* One-off jobs of the database instance carry its labels too, under a `-task-` name. */ + const name = names + .split("\n") + .map((line) => line.trim()) + .find((line) => line.length > 0 && !/-task-[^-]+$/u.test(line)); + if (name === undefined) return yield* unreachable("no database container"); + const authority = `${DOCKER_HOST_ALIAS}:${check.port}`; + /* Once connected it exits 0 and prints what `readApiTlsCheck` reads, also when the listener + reset the connection before the request was written. */ + const script = `trap '' PIPE; exec 3<>/dev/tcp/${DOCKER_HOST_ALIAS}/${check.port} && { printf 'GET ${check.path} HTTP/1.0\\r\\nHost: ${authority}\\r\\nConnection: close\\r\\n\\r\\n' >&3 2>/dev/null; IFS= read -r -d '' -t ${readSeconds} reply <&3; printf '%s %s' "$?" "$reply"; }`; + const output = yield* runRaw( + spawner, + target.engine, + ["exec", name, "bash", "-c", script], + target.argv, + ).pipe( + Effect.mapError((error) => unreachable(`probe failed for ${authority}: ${error.message}`)), + ); + const read = readApiTlsCheck(output, check.body, readSeconds); + if (read.outcome === "closed") + return yield* failed( + `api.tls: unsupported networking on ${runtime}: containers must reach the api from loopback`, + "the database container's plain request was closed without a reply", + "turn off `[api.tls]`, or use a runtime whose containers reach this host from loopback (on macOS: Docker Desktop, colima or Podman machine), then start the stack again", + ); + if (read.outcome === "foreign") + return yield* failed( + `api.tls: the api port ${check.port} on ${runtime} isn't answering this stack's start check`, + read.detail, + `check what else listens on port ${check.port}, then start the stack again`, + ); +}); + +/** + * The start check after a start or restart, when the API listener serves TLS: a failed probe + * stops the stack's services and fails with what the probe saw. + */ +export const checkApiTlsReach = Effect.fn("ApiTlsSupport.checkReach")(function* (options: { + readonly spawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; + readonly target: EngineTarget; + readonly stack: ApiTlsStack; + /** The engine every failure names, like `linux docker`. */ + readonly runtime: string; + /** The API listener's port while it serves TLS; undefined skips the check. */ + readonly port: number | undefined; + readonly path: string; + /** Runs the probe while the readiness route answers with this body. */ + readonly answering: (body: string, check: Effect.Effect) => Effect.Effect; + readonly body: Effect.Effect; + readonly stop: Effect.Effect; + readonly readSeconds?: number; +}) { + const { stack } = options; + if (options.port === undefined) return; + const port = options.port; + const body = yield* options.body; + yield* options + .answering( + body, + probeApiTls( + options.spawner, + options.target, + stack, + options.runtime, + { port, path: options.path, body }, + options.readSeconds, + ), + ) + .pipe( + Effect.catchTag("ApiTlsCheckError", (error) => + Effect.gen(function* () { + yield* Effect.logWarning(`${error.message}: ${error.detail}`); + const unstopped = yield* options.stop.pipe( + Effect.as(undefined), + Effect.catch((cause) => + Effect.logError(`api.tls: stopping the stack failed: ${cause.message}`).pipe( + Effect.as(cause.message), + ), + ), + ); + const recovery = + unstopped === undefined + ? `; its services stopped: ${error.next}` + : `; its services did not stop (${unstopped}), run \`supabase stack stop --stack-id ${stack.id}\` to stop them`; + return yield* new ApiTlsCheckError({ + message: `${error.message} (${error.detail})${recovery}`, + detail: error.detail, + next: error.next, + }); + }), + ), + ); +}); diff --git a/packages/stack/src/runtime/ApiTlsSupport.unit.test.ts b/packages/stack/src/runtime/ApiTlsSupport.unit.test.ts new file mode 100644 index 0000000000..2b4b8ccd37 --- /dev/null +++ b/packages/stack/src/runtime/ApiTlsSupport.unit.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it } from "@effect/vitest"; +import { readApiTlsCheck } from "./ApiTlsSupport.ts"; + +const body = "supabase-stack s1 3f1c"; +const ok = (reply: string) => `HTTP/1.1 200 OK\r\nContent-Length: ${reply.length}\r\n\r\n${reply}`; +const foreign = (detail: string) => ({ outcome: "foreign", detail }); + +describe("api.tls start check reply", () => { + it("passes only a 200 with exactly this check's body, read to its end", () => { + expect(readApiTlsCheck(`1 ${ok(body)}`, body, 5)).toEqual({ outcome: "passed" }); + expect(readApiTlsCheck(`1 HTTP/1.0 200 OK\r\n\r\n${body}`, body, 5)).toEqual({ + outcome: "passed", + }); + /* The body is everything after the head, compared byte for byte. */ + const split = "a\r\n\r\nb"; + expect(readApiTlsCheck(`1 ${ok(split)}`, split, 5)).toEqual({ outcome: "passed" }); + expect(readApiTlsCheck(`1 ${ok(`${body}\n`)}`, body, 5)).toEqual( + foreign("a 200 with another body"), + ); + expect(readApiTlsCheck(`1 ${ok("supabase-stack s1 9a0b")}`, body, 5)).toEqual( + foreign("a 200 with another body"), + ); + }); + + it("reads a reply closed with nothing as closed, and a read cut short as foreign", () => { + expect(readApiTlsCheck("1 ", body, 5)).toEqual({ outcome: "closed" }); + for (const output of ["142 ", `142 ${ok(body)}`]) + expect(readApiTlsCheck(output, body, 3), output).toEqual( + foreign("no complete reply within 3 s"), + ); + /* `read` stops at a NUL with status 0, so the rest of the reply was never read. */ + expect(readApiTlsCheck(`0 ${ok(body)}`, body, 5)).toEqual(foreign("a 200 with a NUL byte")); + }); + + it("names any other status line, its control bytes masked", () => { + expect(readApiTlsCheck("1 HTTP/1.1 404 Not Found\r\n\r\nNot Found", body, 5)).toEqual( + foreign("replied HTTP/1.1 404 Not Found"), + ); + expect(readApiTlsCheck("1 HTTP/1.1 502 Bad Gateway\r\n\r\n", body, 5)).toEqual( + foreign("replied HTTP/1.1 502 Bad Gateway"), + ); + expect(readApiTlsCheck("1 \u001b[31mSSH-2.0\u0007\tx", body, 5)).toEqual( + foreign("replied ?[31mSSH-2.0??x"), + ); + expect(readApiTlsCheck(`1 \r\n${ok(body)}`, body, 5)).toEqual( + foreign("replied without a status line"), + ); + expect(readApiTlsCheck(`1 HTTP/1.1 2000 OK\r\n\r\n${body}`, body, 5)).toEqual( + foreign("replied HTTP/1.1 2000 OK"), + ); + }); +}); diff --git a/packages/stack/src/runtime/Container.integration.test.ts b/packages/stack/src/runtime/Container.integration.test.ts index c431ac9791..18d3ba4ba3 100644 --- a/packages/stack/src/runtime/Container.integration.test.ts +++ b/packages/stack/src/runtime/Container.integration.test.ts @@ -1550,7 +1550,7 @@ describe("container process adapter", { timeout: 120_000 }, () => { ); it.effect( - "names the stalled engine subcommand and its stderr when an engine command times out", + "names the stalled engine subcommand, its stderr, and the container state when start times out", () => Effect.gen(function* () { const engine = yield* makeStalledStartSpawner("Error: waiting for network sandbox"); @@ -1572,7 +1572,7 @@ describe("container process adapter", { timeout: 120_000 }, () => { expect(failure instanceof ContainerLaunchError).toBe(true); expect(failureKind(failure)).toBe("engine-timeout"); expect(failure instanceof ContainerLaunchError ? failure.failure.message : undefined).toBe( - "Engine command 'start' did not finish within 30s; stderr: Error: waiting for network sandbox", + "Engine command 'start' did not finish within 30s; stderr: Error: waiting for network sandbox; container state: status=created started=0001-01-01T00:00:00Z pid=0 error=", ); }).pipe(Effect.provide([NodeServices.layer, NodeCrypto.layer])), ); @@ -2236,7 +2236,7 @@ const successfulHandle = (stdout = "") => unref: Effect.succeed(Effect.void), }); -/** Answers every engine command except `start`, which writes `stderr` and never exits. */ +/** Answers every engine command except `start`, which writes `stderr` and never exits, leaving the container created. */ const makeStalledStartSpawner = Effect.fn("ContainerTest.stalledStartSpawner")(function* ( stderr: string, ) { @@ -2244,6 +2244,10 @@ const makeStalledStartSpawner = Effect.fn("ContainerTest.stalledStartSpawner")(f const spawner = ChildProcessSpawner.make((command) => { if (!ChildProcess.isStandardCommand(command)) return Effect.die("unexpected piped command"); if (command.args[0] === "info") return Effect.succeed(successfulHandle("fake-daemon-id")); + if (command.args[0] === "inspect") + return Effect.succeed( + successfulHandle("status=created started=0001-01-01T00:00:00Z pid=0 error="), + ); if (command.args[0] !== "start") return Effect.succeed(successfulHandle()); // The second pull only happens once the reader has consumed the stderr line. const stalledStderr = Stream.succeed(new TextEncoder().encode(stderr)).pipe( diff --git a/packages/stack/src/runtime/Container.ts b/packages/stack/src/runtime/Container.ts index 57842c385e..df2f25be14 100644 --- a/packages/stack/src/runtime/Container.ts +++ b/packages/stack/src/runtime/Container.ts @@ -193,7 +193,7 @@ const transientPullFailure = (error: ContainerError) => * Runs one engine CLI invocation outside the owner's command runner, for resolving its target * itself. `pin` precedes `args` so the failure names the subcommand, not a pin flag. */ -const runRaw = ( +export const runRaw = ( spawner: ChildProcessSpawner.ChildProcessSpawner["Service"], engine: ContainerEngine, args: ReadonlyArray, @@ -1044,7 +1044,35 @@ export const makeContainerRuntime = (options: { ) .pipe(Effect.mapError((cause) => errorFor("start", cause))) : undefined; - if (!interactive) yield* run(["start", name]); + if (!interactive) + yield* run(["start", name]).pipe( + // Whether the engine stalled before or after starting the process decides the fix. + Effect.catchTag("ContainerError", (failure) => + failure.kind !== "engine-timeout" + ? Effect.fail(failure) + : run( + [ + "inspect", + "--format", + "status={{.State.Status}} started={{.State.StartedAt}} pid={{.State.Pid}} error={{.State.Error}}", + name, + ], + { timeout: "5 seconds" }, + ).pipe( + Effect.orElseSucceed(() => "unavailable"), + Effect.flatMap((state) => + Effect.fail( + new ContainerError({ + operation: failure.operation, + message: `${failure.message}; container state: ${state}`, + cause: failure.cause, + kind: failure.kind, + }), + ), + ), + ), + ), + ); const wait: Effect.Effect = attached === undefined ? run(["wait", name], {}).pipe( diff --git a/packages/stack/src/services/Functions.integration.test.ts b/packages/stack/src/services/Functions.integration.test.ts index b594c1d395..42f7afb6bf 100644 --- a/packages/stack/src/services/Functions.integration.test.ts +++ b/packages/stack/src/services/Functions.integration.test.ts @@ -920,7 +920,7 @@ it.effect("passes the API host port and debug mode to the docker Functions runti deps, Functions.makeSpec(fakeBootstrap, deps.path, deps.fs), ); - const capture = Effect.fn(function* (apiUrl: string) { + const capture = Effect.fn(function* (apiUrl: string, hostApiUrl?: string) { const scope = yield* Scope.make(); yield* recipe.definition .launch({ @@ -931,6 +931,7 @@ it.effect("passes the API host port and debug mode to the docker Functions runti config: { functionsRoot: "/project/supabase/functions", apiUrl, + ...(hostApiUrl === undefined ? {} : { hostApiUrl }), debug: true, env: { PLAIN: "plain" }, }, @@ -944,10 +945,18 @@ it.effect("passes the API host port and debug mode to the docker Functions runti const spec = yield* capture("http://host.supabase.internal:61121"); expect(spec?.env.SUPABASE_INTERNAL_HOST_PORT).toBe("61121"); + expect(spec?.env).not.toHaveProperty("SUPABASE_INTERNAL_HOST_URL"); expect(spec?.env.SUPABASE_INTERNAL_DEBUG).toBe("true"); expect(spec?.args).toContain("--verbose"); expect(spec?.env.PLAIN).toBe("plain"); expect((yield* capture("http://127.0.0.1:80"))?.env.SUPABASE_INTERNAL_HOST_PORT).toBe("80"); + /* Under API TLS the runtime URL and port stay, and the banner gets the HTTPS host origin. */ + const tls = yield* capture("http://host.supabase.internal:61121", "https://127.0.0.1:61121"); + expect(tls?.env).toMatchObject({ + SUPABASE_URL: "http://host.supabase.internal:61121", + SUPABASE_INTERNAL_HOST_PORT: "61121", + SUPABASE_INTERNAL_HOST_URL: "https://127.0.0.1:61121", + }); }), ).pipe( Effect.provide( diff --git a/packages/stack/src/services/Functions.ts b/packages/stack/src/services/Functions.ts index 33da70b38e..bc49e4e964 100644 --- a/packages/stack/src/services/Functions.ts +++ b/packages/stack/src/services/Functions.ts @@ -38,6 +38,8 @@ export const Config = Schema.Struct({ databaseUrl: Schema.optionalKey(Schema.String), env: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)), apiUrl: Schema.optionalKey(Schema.String), + /** The host's HTTPS API origin while the API serves TLS, which the banner prefers. */ + hostApiUrl: Schema.optionalKey(Schema.String), jwtSecret: Schema.optionalKey(Schema.String), jwks: Schema.optionalKey(Schema.String), anonKey: Schema.optionalKey(Schema.String), @@ -192,6 +194,9 @@ export const makeSpec = ( }), ...(creation.config.apiUrl === undefined ? {} : { SUPABASE_URL: creation.config.apiUrl }), ...(hostPort === undefined ? {} : { SUPABASE_INTERNAL_HOST_PORT: hostPort }), + ...(creation.config.hostApiUrl === undefined + ? {} + : { SUPABASE_INTERNAL_HOST_URL: creation.config.hostApiUrl }), ...(creation.config.debug === true ? { SUPABASE_INTERNAL_DEBUG: "true" } : {}), ...(creation.config.databaseUrl === undefined ? {} diff --git a/packages/stack/src/services/Rest.ts b/packages/stack/src/services/Rest.ts index 84207f835b..af071021ca 100644 --- a/packages/stack/src/services/Rest.ts +++ b/packages/stack/src/services/Rest.ts @@ -12,6 +12,7 @@ export const Config = Schema.Struct({ jwtSecret: Schema.optionalKey(Schema.String), jwks: Schema.optionalKey(Schema.String), maxRows: Schema.optionalKey(Schema.Finite), + dbPool: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))), }); export interface Config extends Schema.Schema.Type {} @@ -46,6 +47,9 @@ export const makeSpec = (): ProcessRecipeSpec => ({ : { PGRST_DB_EXTRA_SEARCH_PATH: creation.config.extraSearchPath }), PGRST_DB_ANON_ROLE: creation.config.anonRole ?? "anon", PGRST_DB_MAX_ROWS: String(creation.config.maxRows ?? 1000), + ...(creation.config.dbPool === undefined + ? {} + : { PGRST_DB_POOL: String(creation.config.dbPool) }), // `info` logs every request, which Studio's PostgREST logs page shows. PGRST_LOG_LEVEL: "info", ...(jwtSecret === undefined ? {} : { PGRST_JWT_SECRET: jwtSecret }), diff --git a/packages/stack/src/services/ServiceIdentity.unit.test.ts b/packages/stack/src/services/ServiceIdentity.unit.test.ts index 5bb4575414..6cef788881 100644 --- a/packages/stack/src/services/ServiceIdentity.unit.test.ts +++ b/packages/stack/src/services/ServiceIdentity.unit.test.ts @@ -1,5 +1,5 @@ import { expect, it } from "@effect/vitest"; -import { Effect, Schema } from "effect"; +import { Effect, Exit, Schema } from "effect"; import * as Realtime from "./Realtime.ts"; import type { ServiceEndpoint } from "./Recipe.ts"; import * as Rest from "./Rest.ts"; @@ -55,6 +55,20 @@ it.effect("probes PostgREST readiness on its admin server port", () => }), ); +it.effect("forwards the PostgREST pool size only when dbPool is set", () => + Effect.gen(function* () { + const restEnv = (config: Rest.Config) => + Schema.decodeEffect(Rest.Creation)({ service: "rest", pin: selection.rest, config }).pipe( + Effect.flatMap((creation) => Rest.makeSpec().env(creation, new Map(), false)), + ); + const databaseUrl = "postgresql://localhost/postgres"; + + expect((yield* restEnv({ databaseUrl, dbPool: 10 })).PGRST_DB_POOL).toBe("10"); + expect(yield* restEnv({ databaseUrl })).not.toHaveProperty("PGRST_DB_POOL"); + expect(Exit.isFailure(yield* Effect.exit(restEnv({ databaseUrl, dbPool: 0 })))).toBe(true); + }), +); + it("forwards Realtime JWKS while retaining its default JWT secret", () => { const creation = Schema.decodeSync(Realtime.Creation)({ service: "realtime", diff --git a/packages/stack/tests/api-tls.ts b/packages/stack/tests/api-tls.ts new file mode 100644 index 0000000000..74de609a9d --- /dev/null +++ b/packages/stack/tests/api-tls.ts @@ -0,0 +1,127 @@ +import { Config, Data, Deferred, Effect, Stream } from "effect"; +import { ChildProcess, ChildProcessSpawner } from "effect/process"; +import { createServer, type Socket } from "node:net"; +import { networkInterfaces } from "node:os"; +import { defaultArtifactSelection } from "../src/Artifacts.ts"; +import { DOCKER_HOST_ALIAS, type EngineTarget } from "../src/runtime/Container.ts"; + +class ApiTlsFixtureError extends Data.TaggedError("ApiTlsFixtureError")<{ + readonly message: string; +}> {} + +const external = Object.values(networkInterfaces()) + .flat() + .find((entry) => entry?.family === "IPv4" && !entry.internal)?.address; + +/** This host's first non-loopback IPv4; a test that needs one fails rather than skips without it. */ +export const externalAddress = + external === undefined + ? Effect.die("no external IPv4 address to reach the API from the LAN side") + : Effect.succeed(external); + +/** Whether a peer address, `::ffff:`-mapped or not, is loopback. */ +export const isLoopback = (address: string) => { + const unmapped = address.startsWith("::ffff:") ? address.slice(7) : address; + return unmapped === "::1" || /^127\.\d+\.\d+\.\d+$/u.test(unmapped); +}; + +/** Runs `command` to its end, answering its stdout, stderr and exit code. */ +export const runCommand = (command: string, args: ReadonlyArray) => + Effect.scoped( + Effect.gen(function* () { + const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const child = yield* spawner.spawn( + ChildProcess.make(command, args, { stdin: "ignore", stdout: "pipe", stderr: "pipe" }), + ); + const [stdout, stderr, code] = yield* Effect.all( + [ + Stream.mkString(Stream.decodeText(child.stdout)), + Stream.mkString(Stream.decodeText(child.stderr)), + child.exitCode, + ], + { concurrency: "unbounded" }, + ); + return { stdout, stderr, code: Number(code) }; + }), + ); + +/** + * A bash of at least 4 on this host, which the start check's probe needs, or none: bash 3.2 + * (macOS's `/bin/bash`) reports a `read -t` timeout like an end of input. + */ +export const hostBash = Effect.gen(function* () { + for (const candidate of ["bash", "/opt/homebrew/bin/bash", "/usr/local/bin/bash"]) { + const major = yield* runCommand(candidate, ["-c", 'printf %s "${BASH_VERSINFO[0]}"']).pipe( + Effect.map(({ stdout, code }) => (code === 0 ? Number(stdout) : 0)), + Effect.orElseSucceed(() => 0), + ); + if (major >= 4) return candidate; + } + return undefined; +}); + +/** + * The address a container of `target`'s engine arrives from at a listener on every interface of + * this host, measured with the database image and a bash `/dev/tcp` request to the stack alias, + * independently of the stack's own start check. + */ +export const containerPeer = (target: Pick) => + Effect.scoped( + Effect.gen(function* () { + const peer = yield* Deferred.make(); + /* An engine's forwarder may keep its side open after the container exits. */ + const sockets = new Set(); + const server = createServer((socket) => { + sockets.add(socket); + socket.on("error", () => socket.destroy()); + Deferred.doneUnsafe(peer, Effect.succeed(socket.remoteAddress ?? "")); + socket.end("HTTP/1.0 200 OK\r\nContent-Length: 4\r\n\r\npeer"); + }); + const port = yield* Effect.acquireRelease( + Effect.callback((resume) => { + const onError = (cause: Error) => + resume(Effect.fail(new ApiTlsFixtureError({ message: cause.message }))); + server.once("error", onError); + server.listen(0, "0.0.0.0", () => { + server.off("error", onError); + const address = server.address(); + resume( + address === null || typeof address === "string" + ? Effect.fail(new ApiTlsFixtureError({ message: "no listener address" })) + : Effect.succeed(address.port), + ); + }); + return Effect.sync(() => server.off("error", onError)); + }), + () => + Effect.callback((resume) => { + server.close(() => resume(Effect.void)); + for (const socket of sockets) socket.destroy(); + }), + ); + const script = `exec 3<>/dev/tcp/${DOCKER_HOST_ALIAS}/${port} && printf 'GET / HTTP/1.0\\r\\n\\r\\n' >&3 && IFS= read -r -d '' -t 5 reply <&3; printf '%s' "$reply"`; + const probe = yield* runCommand(target.engine, [ + ...target.argv, + "run", + "--rm", + "--add-host", + `${DOCKER_HOST_ALIAS}:host-gateway`, + "--entrypoint", + "bash", + defaultArtifactSelection().database.image, + "-c", + script, + ]); + if (probe.code !== 0 || !probe.stdout.endsWith("peer")) + return yield* new ApiTlsFixtureError({ + message: `the container peer probe failed (${probe.code}): ${probe.stdout}${probe.stderr}`, + }); + return yield* Deferred.await(peer); + }), + ); + +/** Whether this run is on CI, where a test whose host prerequisites are missing fails, not skips. */ +export const onCi = Config.String("CI").pipe( + Config.withDefault(""), + Config.map((value) => value !== ""), +); diff --git a/packages/stack/tests/certs/dns-only.crt b/packages/stack/tests/certs/dns-only.crt new file mode 100644 index 0000000000..79bc050aa5 --- /dev/null +++ b/packages/stack/tests/certs/dns-only.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBczCCARqgAwIBAgIUKmR8Is8HWpsAFL/1kHTzc4DrmM8wCgYIKoZIzj0EAwIw +FDESMBAGA1UEAwwJMTI3LjAuMC4xMCAXDTI2MTExMDE2NTQyOVoYDzIxMjYxMDE3 +MTY1NDI5WjAUMRIwEAYDVQQDDAkxMjcuMC4wLjEwWTATBgcqhkjOPQIBBggqhkjO +PQMBBwNCAAQIfuJnJzdla3/UnD8VaHOJSCyfUrxWhjp5+XSl6P5+qWBYXc81ragc +S4L6qYGJIAahVIN4rRCi4l/Q9xFO24zIo0gwRjAdBgNVHQ4EFgQUZyCDbVf8AFPH +wlGIVKm3PpOHLSkwDwYDVR0TAQH/BAUwAwEB/zAUBgNVHREEDTALgglsb2NhbGhv +c3QwCgYIKoZIzj0EAwIDRwAwRAIgMvxosSXy+u31IfN6OLCYbv3izvW4lvc6uGAI +RVuI+1ECIF9MlKL+85r1ENzza52YLFEU2tIMnnF4nog4caxIVMp7 +-----END CERTIFICATE----- diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49ff64c6f6..5de086b3e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -350,8 +350,8 @@ importers: specifier: 'catalog:' version: 2.112.4 '@supabase/typegen': - specifier: 0.3.2 - version: 0.3.2(oxfmt@0.66.0) + specifier: 0.3.4 + version: 0.3.4(oxfmt@0.66.0) '@tsconfig/bun': specifier: 'catalog:' version: 1.0.11 @@ -2906,8 +2906,8 @@ packages: resolution: {integrity: sha512-uaubtPSeg2TR4wrtfQoQWgkTAe+a0qWX2KhmwvTfNl5mGN9+U7owiJt6abk3o/V6O899PSRD1yzxs5RlF4xTug==} engines: {node: '>=22.0.0'} - '@supabase/postgrest-typegen@0.7.0': - resolution: {integrity: sha512-B1Wh2arVChXsX9ACdOv6CuX7m1+5S7jYFjB0b+yhNWJq63RFkOTgRlz4Q1uGI/M9nSPXtM3XC03KxpvKzTknCg==} + '@supabase/postgrest-typegen@0.8.1': + resolution: {integrity: sha512-PvD7+L7TznK+9lq3SrLv535vS7tkH/ydlqGe0g16gAXTW0qbYjkaFMAWwnqkfvRjtPgAjkQ3lLJLDhe74sizRg==} engines: {node: '>=22.12.0'} peerDependencies: oxfmt: 0.66.0 @@ -2932,8 +2932,8 @@ packages: '@opentelemetry/api': optional: true - '@supabase/typegen@0.3.2': - resolution: {integrity: sha512-b48/ZCYnKtl6qdjDlkuXpU33lWEYo0x4pvZCaFyLaY+mbJ0DxZAoS6Jpsa0pBUYGwcDVupBLpDKcjXQPSZPNJA==} + '@supabase/typegen@0.3.4': + resolution: {integrity: sha512-yNxQVf3h6yx9XYFk47YK0Bb9ghcthl1J3I5lLUQrWYkpTb4Yyg1yz4KbkqbtEUDd+F9WNKZjt5MKqpZGuJWlDQ==} engines: {node: '>=22.12.0'} peerDependencies: oxfmt: 0.66.0 @@ -8638,7 +8638,7 @@ snapshots: dependencies: tslib: 2.8.1 - '@supabase/postgrest-typegen@0.7.0(oxfmt@0.66.0)': + '@supabase/postgrest-typegen@0.8.1(oxfmt@0.66.0)': dependencies: arktype: 2.2.9 optionalDependencies: @@ -8662,9 +8662,9 @@ snapshots: '@supabase/realtime-js': 2.112.4 '@supabase/storage-js': 2.112.4 - '@supabase/typegen@0.3.2(oxfmt@0.66.0)': + '@supabase/typegen@0.3.4(oxfmt@0.66.0)': dependencies: - '@supabase/postgrest-typegen': 0.7.0(oxfmt@0.66.0) + '@supabase/postgrest-typegen': 0.8.1(oxfmt@0.66.0) optionalDependencies: oxfmt: 0.66.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7604013415..b49a4fbf73 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -109,8 +109,8 @@ minimumReleaseAgeExclude: - "@effect/vitest@4.1.2" - "@supabase/pg-delta@1.0.0-alpha.60" - "@supabase/pg-topo@1.0.0-alpha.8" - - "@supabase/postgrest-typegen@0.7.0" - - "@supabase/typegen@0.3.2" + - "@supabase/postgrest-typegen@0.8.1" + - "@supabase/typegen@0.3.4" - "effect@4.1.2" - "turbo@2.10.11" - "ws@8.22.1"