From 643cc643bf606cffae472996e906cdf9e45b79de Mon Sep 17 00:00:00 2001 From: Roman Melnikov Date: Sun, 1 Nov 2026 01:21:49 +0300 Subject: [PATCH 1/2] Support Orleans 10.4.2 and strengthen behavioral tests --- .github/workflows/ci.yml | 61 +- CHANGELOG.md | 22 + Directory.Packages.props | 10 +- README.md | 5 +- docs/compatibility.md | 66 +- docs/faq.md | 5 +- docs/release-status.md | 29 +- docs/streaming-replies.md | 12 +- docs/streaming.md | 15 +- .../FunctionalObserver.cs | 9 +- .../FunctionalTransportSerialization.cs | 22 +- .../FunctionalInteropIntegrationTests.fs | 28 +- .../FunctionalPhaseFFixture.fs | 12 +- .../FunctionalPhaseFIntegrationTests.fs | 46 +- .../FunctionalPlacementIntegrationTests.fs | 4 + .../FunctionalStateRestartTests.fs | 34 +- .../GrainLifecycleTests.fs | 15 +- .../StreamingIntegrationTests.fs | 70 +- .../FunctionalCodecTests.fs | 22 + ...FunctionalPersistenceSerializationTests.fs | 15 +- .../GrainHandlerStateMachineProperties.fs | 29 +- .../GrainResilienceTests.fs | 59 +- website/package-lock.json | 1655 ++++++++--------- website/public/llms-full.txt | 127 +- website/src/content/docs/compatibility.md | 68 +- website/src/content/docs/faq.md | 5 +- website/src/content/docs/release-status.md | 29 +- website/src/content/docs/streaming-replies.md | 12 +- website/src/content/docs/streaming.md | 15 +- 29 files changed, 1415 insertions(+), 1086 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebbc7f5..82147d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,9 +33,9 @@ jobs: - label: floor arg: '' version: '10.1.0' - - label: 10.3.1 (newest) - arg: '-p:OrleansVersion=10.3.1' - version: '10.3.1' + - label: 10.4.2 (newest) + arg: '-p:OrleansVersion=10.4.2' + version: '10.4.2' steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # The SDK is PINNED, not floated. FSharp.Control.TaskSeq 1.1.1 implements the dynamic @@ -132,8 +132,8 @@ jobs: include: - label: floor arg: '' - - label: 10.3.1 (newest) - arg: '-p:OrleansVersion=10.3.1' + - label: 10.4.2 (newest) + arg: '-p:OrleansVersion=10.4.2' services: redis: image: redis:7-alpine @@ -393,7 +393,7 @@ jobs: if [[ "$GITHUB_REF" == refs/tags/v5.* ]]; then candidate="${GITHUB_REF_NAME#v}" else - candidate="5.0.0-ci.${GITHUB_RUN_ID}.${GITHUB_RUN_ATTEMPT}" + candidate="5.0.2-ci.${GITHUB_RUN_ID}.${GITHUB_RUN_ATTEMPT}" fi echo "version=$candidate" >> "$GITHUB_OUTPUT" echo "Release candidate: $candidate" @@ -460,6 +460,55 @@ jobs: --no-build \ --no-restore | tee "$RUNNER_TEMP/template-smoke.out" python3 scripts/check-template-smoke.py "$RUNNER_TEMP/template-smoke.out" + - name: Run the same floor-built packages on newest Orleans + timeout-minutes: 5 + env: + NEWEST_ORLEANS_VERSION: '10.4.2' + shell: bash + run: | + set -o pipefail + # Upgrade only the generated application. Its Orleans.FSharp dependencies remain the + # exact nupkgs packed above against the floor, not ProjectReferences rebuilt for newest. + python3 - <<'PY' + import json + import os + from pathlib import Path + import subprocess + + root = Path(os.environ["RUNNER_TEMP"]) / "template-smoke" + project = root / "src/TemplateSmoke.Silo/TemplateSmoke.Silo.fsproj" + assets = json.loads((project.parent / "obj/project.assets.json").read_text()) + packages = sorted({key.split("/")[0] for key in assets["libraries"] + if key.startswith("Microsoft.Orleans.")}) + if not packages: + raise SystemExit("No Orleans dependencies discovered in the package consumer") + for package in packages: + subprocess.run(["dotnet", "add", str(project), "package", package, + "--version", os.environ["NEWEST_ORLEANS_VERSION"], + "--no-restore"], check=True) + PY + dotnet restore "$RUNNER_TEMP/template-smoke/TemplateSmoke.sln" \ + --source "$RUNNER_TEMP/nupkgs" --source https://api.nuget.org/v3/index.json + dotnet build "$RUNNER_TEMP/template-smoke/TemplateSmoke.sln" \ + --configuration Release --no-restore --verbosity minimal + # Do not accept a successful run which silently resolved a mixed/older Orleans set. + python3 - <<'PY' + import json + import os + from pathlib import Path + + root = Path(os.environ["RUNNER_TEMP"]) / "template-smoke/src/TemplateSmoke.Silo/obj" + assets = json.loads((root / "project.assets.json").read_text()) + expected = os.environ["NEWEST_ORLEANS_VERSION"] + wrong = [key for key in assets["libraries"] + if key.startswith("Microsoft.Orleans.") and key.rsplit("/", 1)[1] != expected] + if wrong: + raise SystemExit(f"Unexpected Orleans runtime resolution: {wrong}") + PY + dotnet run \ + --project "$RUNNER_TEMP/template-smoke/src/TemplateSmoke.Silo/TemplateSmoke.Silo.fsproj" \ + --configuration Release --no-build --no-restore | tee "$RUNNER_TEMP/template-newest.out" + python3 scripts/check-template-smoke.py "$RUNNER_TEMP/template-newest.out" - name: Run the packed F# analyzer in its matching CLI host run: | python3 scripts/test-analyzer-package-report.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a7447b1..0610b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ ## [Unreleased] +### Fixed + +- Align all seven fixed-transport and observer deep copiers with Orleans 10.4's nullable input + contract. Preserve the Orleans 10.1.0 minimum and existing wire format. +- Upgrade build-only SourceLink tooling from 8.0.0 to 10.0.403, removing the Git task affected by + CVE-2026-62900 without disabling NuGet auditing. +- Refresh the documentation site's compatible dependency lockfile to resolve nine reported + vulnerabilities, without a framework major-version change. +- Resolve the Dashboard 10.4.2 OpenTelemetry.Api dependency without a central downgrade. + +### Changed + +- Move the newest Orleans CI and Redis-durability matrix legs to 10.4.2. +- Compare stream checkpoint resumption with a native Orleans control, preserving the 10.4.2 + inclusive replay behavior instead of asserting the older runtime's exclusive boundary. +- Strengthen retry, state-machine, persistence-codec, key-isolation, deactivation, and recovery + tests. Characterize TaskSeq wrappers using complete sequences, including empty and singleton + streams, while retaining strict direct-delivery and disposal checks. +- Document Orleans 10.4 upgrade boundaries and useful future helpers. TaskSeq remains 1.1.1 and + SDK 10.0.201 stays pinned: no stable TaskSeq fix or stable SDK containing the compiler backport + has been verified. DurableGrain and Durable Jobs remain deferred prereleases. + ## [5.0.1] - 2026-09-07 ### Fixed diff --git a/Directory.Packages.props b/Directory.Packages.props index 1c4cd1c..61a08aa 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -32,9 +32,9 @@ - - + + @@ -85,7 +85,9 @@ - + + diff --git a/README.md b/README.md index 9c0bbea..688b47f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![NuGet](https://img.shields.io/nuget/v/Orleans.FSharp.svg)](https://www.nuget.org/packages/Orleans.FSharp) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![.NET 10](https://img.shields.io/badge/.NET-10.0-512BD4)](https://dotnet.microsoft.com/) -[![Orleans 10](https://img.shields.io/badge/Orleans-10.1.0%20%E2%80%93%2010.3.1-blue)](https://learn.microsoft.com/dotnet/orleans/) +[![Orleans 10](https://img.shields.io/badge/Orleans-10.1.0%20%E2%80%93%2010.4.2-blue)](https://learn.microsoft.com/dotnet/orleans/) [![F#](https://img.shields.io/badge/F%23-9%2B-378BBA)](https://fsharp.org/) Orleans.FSharp keeps the Microsoft Orleans runtime and gives it an F#-first authoring model: @@ -26,6 +26,9 @@ This README documents **Orleans.FSharp 5.0.1**, the current stable release. Appl from 4.x should review the [breaking changes](CHANGELOG.md#500---2026-09-07) and [Legacy migration guide](docs/legacy/migration.md). +The development branch prepares **5.0.2** with an Orleans **10.4.2** compatibility target; +the minimum remains 10.1.0. See [compatibility notes](docs/compatibility.md) for the update's scope. + ## Why Orleans.FSharp? - **F# APIs stay F#.** A grain surface is a typed record of functions using records, diff --git a/docs/compatibility.md b/docs/compatibility.md index 5ffc8fa..13a5128 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -2,8 +2,9 @@ **Supported version policy, verified runtimes, and relevant changes in new Orleans releases.** -This page describes framework compatibility for Orleans.FSharp 5.0.1, the current published stable -release. See [Release and Production Status](release-status.md) for production boundaries. +This page describes the upcoming Orleans.FSharp 5.0.2 compatibility update. The current published +stable release is still 5.0.1; the 10.4.2 source-compatibility changes below belong to the update, +not retroactively to that release. See [Release and Production Status](release-status.md). ## Version policy @@ -16,11 +17,61 @@ current event-sourcing surface uses `JournaledGrain.ClearLogAsync`, which is abs |---|---|---| | 10.0.x | Not supported | Missing an API required by the current Orleans.FSharp assemblies | | 10.1.0 | Supported floor | The version used to compile packages and one end of the CI matrix | -| 10.3.1 | Latest stable Orleans release | The newest-version compatibility target | +| 10.3.1 | Previous compatibility target | Covered by the 5.0.1 release checks | +| 10.4.2 | Latest stable Orleans release as of 1 November 2026 | The newest-version compatibility target for 5.0.2 | The package floor should move only when Orleans.FSharp starts using a newer Orleans API. A new Orleans release alone is not a reason to force every consumer to upgrade. +## What changed in Orleans 10.4 + +Target **10.4.2**, including the servicing fixes after 10.4.0. The official notes for +[10.4.0](https://github.com/dotnet/orleans/releases/tag/v10.4.0), +[10.4.1](https://github.com/dotnet/orleans/releases/tag/v10.4.1), and +[10.4.2](https://github.com/dotnet/orleans/releases/tag/v10.4.2) describe several changes relevant +to functional grains: + +- Read-only request isolation, timer scheduling, and queued-request handling during activation + migration/retirement were corrected. Applications inherit these fixes from their Orleans runtime. +- Serializer type-authorization checks were hardened. ADO.NET streaming redelivery and Azure + membership interoperability also received fixes; the latter providers still need their own + application-level upgrade checks. +- `IDeepCopier` now describes nullable input explicitly. Seven hand-written Orleans.FSharp + transport/observer copiers are aligned with that contract in 5.0.2, including direct null-input + regression tests. This changes nullable annotations, not transport bytes or public F# APIs. +- Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint + event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; + consumers must not depend on exclusive resumption. See [checkpoint replay](streaming.md#resuming-subscriptions-after-reactivation). +- The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build + dependency is updated without raising the Orleans package floor. +- RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a + serialized parameter ordinal. Audit application-owned C# grain interfaces before a rolling + upgrade, particularly tokens placed before other arguments. Our fixed transport places its + token last and writes the envelope with its existing explicit field ID; source inspection found + no corresponding ordinal change. This is not a blanket proof for arbitrary application interfaces. +- `SiloAddress.GetUniformHashCodes` changes its return type from an array to an immutable array. + Applications using that low-level API need a rebuild. Orleans.FSharp does not expose it as part + of its functional API. +- Request latency metrics move to `orleans-app-requests-latency`, a fractional-millisecond + histogram. Review dashboards/alerts, and apply the updated Orleans SQL scripts when using + existing SQLite storage databases. + +### Useful additions, separate from this compatibility update + +| Addition | How it fits Orleans.FSharp | +|---|---| +| Explicit stream subscription start: `Latest` / `EarliestAvailable` | A useful next F# helper, not added in 5.0.2. `EarliestAvailable` means the oldest retained **local queue-cache** item, not all provider history. Native 10.4 APIs are usable when the application targets that version; upgrade pulling-agent silos before enabling the feature. | +| Cancellation-aware framework operations | Evaluate helpers individually. Public stream subscribe/resume/unsubscribe still have no cancellation-token overload; cancelling only the wait can leak a subscription created later. Existing functional-call cancellation is separate. | +| Management `DeactivateGrain` | Usable through the native management grain on 10.4.1+; a dedicated F# convenience wrapper is optional. | +| New provider/cache configuration | Configure through native Orleans hosting APIs; no replacement F# configuration layer is required. | +| `Microsoft.Orleans.Journaling` / Durable Jobs | Still prerelease (`10.4.2-alpha.1`), deliberately deferred. They are not the log-consistency model wrapped by `journaledGrainFor`. | + +Adding first-class start-position helpers while retaining the 10.1 floor needs an explicit +unsupported-runtime error and tests for provider defaults, retained/empty caches, batch delivery, +and subscription cleanup. Falling back silently to ordinary live delivery would hide a semantic +change. The [upstream enum contract](https://github.com/dotnet/orleans/blob/v10.4.2/src/Orleans.Streaming/Core/StreamSubscriptionStartPosition.cs) +defines the cache boundary. + ## What changed in Orleans 10.3 Orleans 10.3.0 was released on 27 August 2026. Its @@ -45,7 +96,7 @@ version-contract analyzer metadata plus tests and documentation. See its [release notes](https://github.com/dotnet/orleans/releases/tag/v10.3.1) and [NuGet package](https://www.nuget.org/packages/Microsoft.Orleans.Server/10.3.1). -## Newly available Orleans surface +## Orleans 10.3 additions already assessed The release also highlights: @@ -57,7 +108,7 @@ The release also highlights: - incremental source generation and new Orleans application templates; - directory, membership, and rolling-upgrade reliability improvements. -These additions fall into three different categories: +Their compatibility boundaries are: | Category | Orleans.FSharp position | |---|---| @@ -76,6 +127,11 @@ The CI matrix keeps the package floor and newest stable Orleans separate. Its ne solution and runs unit tests, functional integration tests, separate-process rolling-update tests, stream tests, the functional sample, and the Dashboard smoke test against the selected release. +The N/N+1 rolling tests change **application** contracts and durable schemas with one Orleans +version per test run. They do not, by themselves, prove a cluster mixing Orleans 10.1 and 10.4 +binaries. Rebuilding against both versions is also different from running a floor-built NuGet +package on the newer runtime; package-consumer smoke checks cover that additional boundary. + This verifies the Orleans.FSharp surface exercised by those suites. It does **not** certify every third-party storage, clustering, or stream provider, nor does it prove that application-specific persisted data can be rolled back without an explicit schema migration strategy. For that, follow diff --git a/docs/faq.md b/docs/faq.md index de0ee1e..0e977f1 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -37,7 +37,10 @@ The returned value has the exact API-record type. ## Which Orleans versions are supported? -The current package range starts at Orleans 10.1.0 and is tested against both 10.1.0 and 10.3.1. A NuGet lower bound means older 10.0.x versions are not selected. See [Orleans Compatibility](compatibility.md) for release-specific notes. +The package range starts at Orleans 10.1.0. The published 5.0.1 release was tested through +10.3.1; the upcoming 5.0.2 update moves the newest compatibility target to 10.4.2 without raising +the minimum. A NuGet lower bound means older 10.0.x versions are not selected. See +[Orleans Compatibility](compatibility.md) for release-specific notes and verification boundaries. ## Does event sourcing support snapshots? diff --git a/docs/release-status.md b/docs/release-status.md index 3284341..63e22bd 100644 --- a/docs/release-status.md +++ b/docs/release-status.md @@ -19,6 +19,18 @@ tag while planning their migration. The runtime APIs are unchanged from 5.0.0. Version 5.0.1 corrects the packaged project template and adds startup regression coverage to the release gate. +### Upcoming 5.0.2 update + +The current branch prepares compatibility with **Orleans 10.4.2**, retaining the **10.1.0** +minimum and the existing public F# API. It aligns the transport copiers with Orleans' nullable +contract and updates build-time SourceLink tooling to remove a vulnerable Git task dependency. +Test hardening checks concrete state, retry outcomes, JSON bytes, and stream contents instead of +weaker count-only or paired round-trip assertions. This section is a candidate status, not a +claim that 5.0.2 has already been published. + +See [Orleans Compatibility](compatibility.md#what-changed-in-orleans-104) for runtime changes, +upgrade caveats, and new APIs considered separately from this patch. + The Legacy archive receives no new Legacy release line, features, compatibility work, or security fixes. New applications should use `grainContract`, `grainFor`, `journaledGrainFor`, typed API records, and `FunctionalGrain.ref`. @@ -44,8 +56,21 @@ initializes the grain definition and an end-to-end template process check in the Direct enumeration of a functional streaming reply is the supported path. With `FSharp.Control.TaskSeq` 1.1.1 on the repository's verified static resumable-code path, wrapping a runtime-returned `IAsyncEnumerable` with `TaskSeq.map` or -`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. TaskSeq -over ordinary producers such as lists, ranges, and database cursors is not affected. +`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. The +repository's ordinary list/range producers do not reproduce this wrapping problem; that is not +a guarantee about every third-party async source. + +As of **1 November 2026**, NuGet still publishes TaskSeq **1.1.1** and +[TaskSeq #452](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The merged reproduction-test PR is not a library fix. The F# compiler fix for Debug resumable-code +lowering was merged and [backported](https://github.com/dotnet/fsharp/pull/20692), but is not included +in stable SDK 10.0.403. The verified repository SDK remains 10.0.201; a closed compiler issue alone +is not sufficient evidence to lift that pin. + +The `UpstreamBoundary` integration cases compare actual item order and contents for empty, +single-item, and longer streams. Only the exact known final duplicate is tolerated for wrappers; +direct enumeration must match exactly. Green characterization tests therefore do **not** mean +the TaskSeq defect is fixed. Delivery, cancellation, and producer disposal have separate strict tests. When one grain relays another grain's streaming reply, return a direct delegating `IAsyncEnumerable`/enumerator instead of using those wrapping forms. The exact pattern and the SDK diff --git a/docs/streaming-replies.md b/docs/streaming-replies.md index 6f41ab7..cc8ab4d 100644 --- a/docs/streaming-replies.md +++ b/docs/streaming-replies.md @@ -270,7 +270,7 @@ The handler returns the BCL `IAsyncEnumerable<'Item>` and nothing else, so any w works. `taskSeq { }` from `FSharp.Control.TaskSeq` is the natural F# tool and this library already depends on that package, so using it adds nothing to your closure. -> **One caveat, and it is not about this runtime.** In `FSharp.Control.TaskSeq` 1.1.1, the +> **Known TaskSeq/Orleans interoperability boundary.** In `FSharp.Control.TaskSeq` 1.1.1, the > *wrapping* forms — `TaskSeq.map`, and `taskSeq { for x in someStream do yield x }` — over an > `IAsyncEnumerable` returned by **this** runtime were measured yielding the last item twice under > an activation's task scheduler; direct enumeration is correct. So when one grain re-streams @@ -284,12 +284,18 @@ depends on that package, so using it adds nothing to your closure. > upstream.GetAsyncEnumerator ct }) > ``` > -> Producing from a `taskSeq { }` over ordinary data — a list, a range, a database cursor — is not -> affected and is what every example here does. This repository tests the Orleans-specific case +> The list/range producers used in these examples do not reproduce this wrapping problem; this +> is not a guarantee for every external async source. This repository tests the Orleans-specific case > against both its minimum and newest supported Orleans versions. The repository remains pinned > to SDK 10.0.201: TaskSeq's dynamic path under SDK 10.0.400 avoids this `taskSeq { for ... }` > duplication, but currently regresses stream delivery and producer-disposal propagation. +As of 1 November 2026, TaskSeq 1.1.1 is still the latest stable package and +[the upstream issue](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The compiler fix/backport has not reached stable SDK 10.0.403. The characterization tests allow +only the exact final-item duplicate, not arbitrary sequences with the same length; they are not +evidence that wrapping is production-safe. + This is tracked as an upstream production boundary, separate from the 4.1-versus-5.0 package split, in [Release and Production Status](release-status.md#taskseq-is-an-upstream-boundary-when-wrapping-streaming-replies). diff --git a/docs/streaming.md b/docs/streaming.md index 94d7322..1a243ec 100644 --- a/docs/streaming.md +++ b/docs/streaming.md @@ -253,10 +253,17 @@ subscription. The corresponding new-subscription functions are `subscribeFromHan Build the argument to `resumeAllHandlers` with `StreamHandlers.withToken` when every resumed subscription must continue exposing provider cursors; a separate alias is unnecessary. -There is one deliberate Orleans distinction: `subscribeFrom*` creates a new subscription and the -tested memory provider includes the checkpoint event, while `resumeFrom` / `resumeBatchFrom` -reattach a handle which already acknowledged that event and continue after it. Keep that -new-subscription versus existing-handle distinction in migration tests for your chosen provider. +These helpers pass the checkpoint token to Orleans unchanged. **Do not assume that resuming an +existing handle is exclusive.** In our memory-provider tests, Orleans 10.1.0 skipped the already +acknowledged checkpoint event on `resumeFrom` / `resumeBatchFrom`; Orleans 10.4.2 replays it. +New `subscribeFrom*` subscriptions include that event on both versions. The integration tests +compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical +suffix, rather than imposing the older runtime's boundary on every version. + +Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests +for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in +[streaming replies](streaming-replies.md#authoring-a-producer); it does not justify dropping the +last item of an arbitrary stream. --- diff --git a/src/Orleans.FSharp.Abstractions/FunctionalObserver.cs b/src/Orleans.FSharp.Abstractions/FunctionalObserver.cs index 97aee5b..315c9c3 100644 --- a/src/Orleans.FSharp.Abstractions/FunctionalObserver.cs +++ b/src/Orleans.FSharp.Abstractions/FunctionalObserver.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -524,15 +525,17 @@ internal sealed class FunctionalNotificationEnvelopeActivator : IActivator { /// - public FunctionalNotificationEnvelope DeepCopy(FunctionalNotificationEnvelope input, CopyContext context) => input; + [return: NotNullIfNotNull(nameof(input))] + public FunctionalNotificationEnvelope? DeepCopy(FunctionalNotificationEnvelope? input, CopyContext context) => input; } /// Deep copier for the observer handle, which is likewise immutable. internal sealed class FunctionalObserverHandleCopier : IDeepCopier> { /// - public FunctionalObserverHandle DeepCopy( - FunctionalObserverHandle input, + [return: NotNullIfNotNull(nameof(input))] + public FunctionalObserverHandle? DeepCopy( + FunctionalObserverHandle? input, CopyContext context) => input; } diff --git a/src/Orleans.FSharp.Abstractions/FunctionalTransportSerialization.cs b/src/Orleans.FSharp.Abstractions/FunctionalTransportSerialization.cs index 535bcc9..a3d71d4 100644 --- a/src/Orleans.FSharp.Abstractions/FunctionalTransportSerialization.cs +++ b/src/Orleans.FSharp.Abstractions/FunctionalTransportSerialization.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -696,7 +697,8 @@ public FunctionalStreamRequest ReadValue(ref Reader reader, Fiel internal sealed class FunctionalRequestEnvelopeCopier : IDeepCopier { /// - public FunctionalRequestEnvelope DeepCopy(FunctionalRequestEnvelope input, CopyContext context) => input; + [return: NotNullIfNotNull(nameof(input))] + public FunctionalRequestEnvelope? DeepCopy(FunctionalRequestEnvelope? input, CopyContext context) => input; } /// @@ -706,7 +708,8 @@ internal sealed class FunctionalRequestEnvelopeCopier : IDeepCopier { /// - public FunctionalReply DeepCopy(FunctionalReply input, CopyContext context) => input; + [return: NotNullIfNotNull(nameof(input))] + public FunctionalReply? DeepCopy(FunctionalReply? input, CopyContext context) => input; } /// @@ -717,11 +720,12 @@ internal sealed class FunctionalReplyCopier : IDeepCopier internal sealed class FunctionalRequestCopier : IDeepCopier { /// - public FunctionalRequest DeepCopy(FunctionalRequest input, CopyContext context) + [return: NotNullIfNotNull(nameof(input))] + public FunctionalRequest? DeepCopy(FunctionalRequest? input, CopyContext context) { if (input is null) { - return null!; + return null; } if (context.TryGetCopy(input, out var existing) && existing is not null) @@ -771,11 +775,12 @@ public FunctionalTransactionRequestCopier( } /// - public FunctionalTransactionRequest DeepCopy(FunctionalTransactionRequest input, CopyContext context) + [return: NotNullIfNotNull(nameof(input))] + public FunctionalTransactionRequest? DeepCopy(FunctionalTransactionRequest? input, CopyContext context) { if (input is null) { - return null!; + return null; } if (context.TryGetCopy(input, out var existing) && existing is not null) @@ -821,11 +826,12 @@ public FunctionalStreamRequestCopier(ICodecProvider codecProvider) => _baseCopier = codecProvider.GetBaseCopier>(); /// - public FunctionalStreamRequest DeepCopy(FunctionalStreamRequest input, CopyContext context) + [return: NotNullIfNotNull(nameof(input))] + public FunctionalStreamRequest? DeepCopy(FunctionalStreamRequest? input, CopyContext context) { if (input is null) { - return null!; + return null; } if (context.TryGetCopy(input, out var existing) && existing is not null) diff --git a/tests/Orleans.FSharp.Integration/FunctionalInteropIntegrationTests.fs b/tests/Orleans.FSharp.Integration/FunctionalInteropIntegrationTests.fs index 1f92c8a..01b7b67 100644 --- a/tests/Orleans.FSharp.Integration/FunctionalInteropIntegrationTests.fs +++ b/tests/Orleans.FSharp.Integration/FunctionalInteropIntegrationTests.fs @@ -40,6 +40,8 @@ type IProbeFacade = abstract Peek: unit -> Task /// A tuple argument, packed from two parameters. abstract Tag: name: string * value: string -> Task + /// Reads the state published by Tag, rather than echoing the current argument. + abstract StateRead: unit -> Task /// An F# record argument and a discriminated-union reply, both through the F# binary codec. abstract Note: note: Note -> Task /// A one-way operation, declared as the bare Task a C# author writes. @@ -105,8 +107,10 @@ type InteropTests(fixture: FunctionalClusterFixture) = [] member _.``the same facade interface binds independently to two keys``() = task { - let first = facade "interop-first" - let second = facade "interop-second" + let firstKey = $"interop-first-{Guid.NewGuid():N}" + let secondKey = $"interop-second-{Guid.NewGuid():N}" + let first = facade firstKey + let second = facade secondKey let! a = first.Echo "a" let! b = second.Echo "b" @@ -115,8 +119,20 @@ type InteropTests(fixture: FunctionalClusterFixture) = // Distinct activations: each key has its own state, so what the first wrote is not // what the second reads. - let! firstTag = first.Tag("owner", "first") - let! secondTag = second.Tag("owner", "second") - Assert.Equal("owner=first", firstTag) - Assert.Equal("owner=second", secondTag) + let! firstTag = first.Tag("first-owner", "first") + let! secondTag = second.Tag("second-owner", "second") + Assert.Equal("first-owner=first", firstTag) + Assert.Equal("second-owner=second", secondTag) + + // Echo/Tag replies alone still pass if facade caching collapses both keys onto + // one grain. Read after BOTH writes, and cross-check with the native bound API + // so two consistently misbound facade methods cannot mask the routing error. + let! firstState = first.StateRead() + let! secondState = second.StateRead() + Assert.Equal("first-owner", firstState) + Assert.Equal("second-owner", secondState) + let! nativeFirst = (fixture.Probe firstKey).api.stateRead () + let! nativeSecond = (fixture.Probe secondKey).api.stateRead () + Assert.Equal("first-owner", nativeFirst) + Assert.Equal("second-owner", nativeSecond) } diff --git a/tests/Orleans.FSharp.Integration/FunctionalPhaseFFixture.fs b/tests/Orleans.FSharp.Integration/FunctionalPhaseFFixture.fs index ed576fa..4079c09 100644 --- a/tests/Orleans.FSharp.Integration/FunctionalPhaseFFixture.fs +++ b/tests/Orleans.FSharp.Integration/FunctionalPhaseFFixture.fs @@ -256,10 +256,10 @@ let tickerDefinition = type RelayApi = { /// Opens `watch` on the named ticker key and re-yields every item's note. relay: string * string * int -> IAsyncEnumerable - /// Consumes the same upstream stream twice INSIDE the grain — once directly, once through - /// `taskSeq { for … }` — and reports both counts. Nothing of the streaming reply path is - /// involved, so a difference is a property of the consuming construct alone. - probe: string * string * int -> Task + /// Consumes upstream streams INSIDE the grain directly, through `TaskSeq.map`, and through + /// `taskSeq { for … }`. Return the actual notes, not counts: equal counts can hide item + /// loss, replacement, or reordering. No streaming reply wrapper is involved. + probe: string * string * int -> Task whereAmI: unit -> Task } type RelayActor = private RelayActor of unit @@ -279,7 +279,7 @@ let relayDefinition = defaultState (fun () -> ()) // Hand-written rather than `taskSeq { for tick in upstream.watch … do yield tick.note }`. - // FSharp.Control.TaskSeq 0.6.0's wrapping combinators over an IAsyncEnumerable produced by + // FSharp.Control.TaskSeq 1.1.1's wrapping combinators over an IAsyncEnumerable produced by // this runtime yield the last item twice when they run under an activation's task // scheduler — see the `probe` operation below and the discriminator test that measures it. // This is the shape a `taskSeq` relay is meant to be, and it is exactly `await foreach`. @@ -324,7 +324,7 @@ let relayDefinition = } ) - return state, (List.length direct, List.length viaMap, List.length viaFor) + return state, (direct |> List.map _.note, viaMap, viaFor) }) handle (_.whereAmI) (fun context state () -> diff --git a/tests/Orleans.FSharp.Integration/FunctionalPhaseFIntegrationTests.fs b/tests/Orleans.FSharp.Integration/FunctionalPhaseFIntegrationTests.fs index 578ca28..522c58d 100644 --- a/tests/Orleans.FSharp.Integration/FunctionalPhaseFIntegrationTests.fs +++ b/tests/Orleans.FSharp.Integration/FunctionalPhaseFIntegrationTests.fs @@ -32,7 +32,7 @@ type FunctionalPhaseFTests(fixture: FunctionalPhaseFFixture) = /// GetAsyncEnumerator, MoveNextAsync until it answers false, then /// DisposeAsync. Deliberately not TaskSeq.toListAsync — a test that proves this /// runtime's streams must depend on nothing but the BCL contract, and - /// FSharp.Control.TaskSeq 0.6.0 has a wrapping defect over exactly these enumerators + /// FSharp.Control.TaskSeq 1.1.1 has a wrapping defect over exactly these enumerators /// (see the discriminator test at the end of this file). /// let collect (stream: IAsyncEnumerable<'T>) : Task<'T list> = @@ -626,31 +626,47 @@ type FunctionalPhaseFTests(fixture: FunctionalPhaseFFixture) = /// /// A discriminator, kept because the answer decided how the relay above is written: the same - /// upstream stream consumed inside the grain directly, and through - /// taskSeq { for … do yield … }. Nothing of the streaming REPLY path takes part, so a - /// difference between the two counts is a property of the consuming construct alone. + /// upstream stream consumed inside the grain directly, through TaskSeq.map, and through + /// taskSeq { for … do yield … }. This characterizes a known upstream boundary; passing + /// does NOT declare the wrappers correct. Direct delivery must be exact, while wrappers may + /// only add one final duplicate. No other loss, replacement, or reordering is accepted. /// - [] - member _.``taskSeq wrappers stay within the known final-item duplication``() = + [] + [] + [] + [] + [] + [] + member _.``taskSeq wrappers stay within the known final-item duplication``(count: int) = task { let suffix = unique () let key = $"probe-{suffix}" let label = $"probe-{suffix}" - PhaseFGates.releaseAll $"{label}-direct" 3 - PhaseFGates.releaseAll $"{label}-map" 3 - PhaseFGates.releaseAll $"{label}-for" 3 + PhaseFGates.releaseAll $"{label}-direct" count + PhaseFGates.releaseAll $"{label}-map" count + PhaseFGates.releaseAll $"{label}-for" count - let! (direct, viaMap, viaFor) = (relay key).probe (key, label, 3) + let! (direct, viaMap, viaFor) = (relay key).probe (key, label, count) // What this runtime owns: enumerating its own stream yields exactly the items the // producer yielded. - test <@ direct = 3 @> + let expected (suffix: string) = [ for index in 0 .. count - 1 -> $"{label}-{suffix}#{index}" ] + test <@ direct = expected "direct" @> // TaskSeq 1.1.1's static path (SDK 10.0.201) still duplicates the final item for both - // wrappers under Orleans 10.1.0 and 10.2.2. Allow that single known upstream defect - // while rejecting item loss or larger amplification. An upstream fix remains green. - test <@ viaMap = direct || viaMap = direct + 1 @> - test <@ viaFor = direct || viaFor = direct + 1 @> + // wrappers. Allow exactly that known defect, not arbitrary sequences of N or N+1 + // items. An upstream fix remains green; an empty producer must stay empty. + let assertKnownBoundary (suffix: string) (actual: string list) = + let wanted = expected suffix + let knownDuplicate = + match List.tryLast wanted with + | Some last -> wanted @ [ last ] + | None -> [] + + test <@ actual = wanted || actual = knownDuplicate @> + + assertKnownBoundary "map" viaMap + assertKnownBoundary "for" viaFor } /// diff --git a/tests/Orleans.FSharp.Integration/FunctionalPlacementIntegrationTests.fs b/tests/Orleans.FSharp.Integration/FunctionalPlacementIntegrationTests.fs index 893e027..4efe08a 100644 --- a/tests/Orleans.FSharp.Integration/FunctionalPlacementIntegrationTests.fs +++ b/tests/Orleans.FSharp.Integration/FunctionalPlacementIntegrationTests.fs @@ -492,9 +492,13 @@ type FunctionalPlacementFixture() = (cluster.Primary :?> InProcessSiloHandle) .SiloHost.Services.GetRequiredService() + // ReadAllAsync was added after our Orleans 10.1 floor. Keep the common contract; + // 10.4 retains ReadAll as an obsolete forwarding API. Suppress only this call. +#nowarn "44" membershipTable.ReadAll().GetAwaiter().GetResult().Members |> Seq.map fst |> Seq.toArray +#warnon "44" member _.Client = cluster.Client diff --git a/tests/Orleans.FSharp.Integration/FunctionalStateRestartTests.fs b/tests/Orleans.FSharp.Integration/FunctionalStateRestartTests.fs index c154f3a..14d5f76 100644 --- a/tests/Orleans.FSharp.Integration/FunctionalStateRestartTests.fs +++ b/tests/Orleans.FSharp.Integration/FunctionalStateRestartTests.fs @@ -107,27 +107,45 @@ let ``explicitly written state reloads on a silo which never saw the write`` () let name = $"restart-{Guid.NewGuid():N}" let api = ledgerRef cluster.Client name + // Keep the development membership table and client gateway alive. Pin only the + // initial activation; after loss, recovery must use ordinary placement. + let secondary = cluster.SecondarySilos |> Seq.head + let! hostingSilo = + task { + let hintKey = Placement.IPlacementDirector.PlacementHintKey + let previousHint = RequestContext.Get hintKey + try + RequestContext.Set(hintKey, secondary.SiloAddress) + return! api.whereAmI () + finally + if isNull previousHint then + RequestContext.Remove hintKey |> ignore + else + RequestContext.Set(hintKey, previousHint) + } + Assert.Equal(string secondary.SiloAddress, hostingSilo) + do! api.writeNow "durable" + do! api.auditWrite 11 + // Recovery must distinguish a committed record from the latest in-memory state. + // Without this divergence, silently persisting every handler return goes unnoticed. + let! _ = api.append "never-written" let! before = api.snapshot () - Assert.Equal("v1:[activated,durable]", before) - - let! hostingSilo = api.whereAmI () - - let handle = - cluster.Silos - |> Seq.find (fun silo -> string silo.SiloAddress = hostingSilo) + Assert.Equal("v2:[activated,durable,never-written]", before) // Remove the silo which owns the activation. Its in-memory state is gone with it; // only the explicitly written record remains. - do! cluster.StopSiloAsync handle + do! cluster.StopSiloAsync secondary do! cluster.WaitForLivenessToStabilizeAsync() let! after = api.snapshot () + let! audit = api.auditPeek () let! newSilo = api.whereAmI () Assert.NotEqual(hostingSilo, newSilo) // The new activation loaded the written record and ran its own activation hook. Assert.Equal("v1:[activated,durable,activated]", after) + Assert.Equal(11, audit) finally cluster.StopAllSilos() cluster.Dispose() diff --git a/tests/Orleans.FSharp.Integration/GrainLifecycleTests.fs b/tests/Orleans.FSharp.Integration/GrainLifecycleTests.fs index cd69cf2..cf85884 100644 --- a/tests/Orleans.FSharp.Integration/GrainLifecycleTests.fs +++ b/tests/Orleans.FSharp.Integration/GrainLifecycleTests.fs @@ -185,7 +185,7 @@ type DeactivationControlIntegrationTests(fixture: ClusterFixture) = } [] - member _.``grain continues to process commands before deactivation takes effect`` () = + member _.``deactivation replies with current state then a fresh activation processes commands`` () = task { let grain = FSharpGrain.ref @@ -202,6 +202,19 @@ type DeactivationControlIntegrationTests(fixture: ClusterFixture) = // Request deactivation — grain should still respond to this call let! afterRequest = FSharpGrain.send DeactivCtrlRequestDeactivation grain test <@ afterRequest.Processed = 10 @> + + // A no-op deactivateOnIdle would satisfy every assertion above. This grain has + // no persistent state: observing its seed again proves the old activation ended. + let deadline = System.DateTime.UtcNow.AddSeconds 30.0 + let mutable processed = afterRequest.Processed + while processed <> 0 && System.DateTime.UtcNow < deadline do + do! System.Threading.Tasks.Task.Delay 25 + let! current = FSharpGrain.send DeactivCtrlGetProcessed grain + processed <- current.Processed + test <@ processed = 0 @> + + let! afterReactivation = FSharpGrain.send (DeactivCtrlProcess 4) grain + test <@ afterReactivation.Processed = 4 @> } #warnon "44" diff --git a/tests/Orleans.FSharp.Integration/StreamingIntegrationTests.fs b/tests/Orleans.FSharp.Integration/StreamingIntegrationTests.fs index d194010..a192110 100644 --- a/tests/Orleans.FSharp.Integration/StreamingIntegrationTests.fs +++ b/tests/Orleans.FSharp.Integration/StreamingIntegrationTests.fs @@ -488,6 +488,48 @@ type StreamingIntegrationTests(fixture: ClusterFixture) = do! Stream.unsubscribe allSub } + /// Independently observe native ResumeAsync on this provider/runtime. The wrapper must + /// preserve its checkpoint boundary, while both routes must deliver the full ordered suffix. + member private this.NativeCheckpointReplay(batch: bool) = + task { + let provider = fixture.Client.GetStreamProvider("StreamProvider") + let streamRef = Stream.getStream provider "native-resume-control" (Guid.NewGuid().ToString()) + let! seed, checkpoint = this.SeedCheckpoint(streamRef, 5, 3) + let received = ConcurrentQueue() + + let! handle = + if batch then + let observer = + { new IAsyncBatchObserver with + member _.OnNextAsync(items) = + for item in items do + received.Enqueue item.Item + Task.CompletedTask + member _.OnCompletedAsync() = Task.CompletedTask + member _.OnErrorAsync(error) = Task.FromException(error) } + seed.Handle.ResumeAsync(observer, checkpoint) + else + let observer = + { new IAsyncObserver with + member _.OnNextAsync(item, _) = + received.Enqueue item + Task.CompletedTask + member _.OnCompletedAsync() = Task.CompletedTask + member _.OnErrorAsync(error) = Task.FromException(error) } + seed.Handle.ResumeAsync(observer, checkpoint) + + try + do! this.NudgeUntil(streamRef, 6, fun () -> Seq.contains 4 received && Seq.contains 5 received) + finally + handle.UnsubscribeAsync().GetAwaiter().GetResult() + + let replay = received |> Seq.filter ((<>) 6) |> Seq.toList + // Both observed native boundaries are safe to compare, but an empty, unordered, + // duplicated, or incomplete suffix is not a valid oracle. + test <@ replay = [ 4; 5 ] || replay = [ 3; 4; 5 ] @> + return replay + } + [] member this.``resumeFrom and subscribeFromHandlers rewind item callbacks`` () = task { @@ -503,14 +545,14 @@ type StreamingIntegrationTests(fixture: ClusterFixture) = (StreamHandlers.create (fun item -> task { resumed.Enqueue item })) do! this.NudgeUntil(resumeRef, 6, fun () -> Seq.contains 4 resumed && Seq.contains 5 resumed) - // ResumeAsync reattaches the existing durable handle. Since that handle already - // acknowledged the checkpoint event, Orleans continues after it rather than - // redelivering it as a new SubscribeAsync(..., token) call does. - test <@ not (Seq.contains 3 resumed) @> - test <@ not (Seq.contains 1 resumed) @> - test <@ not (Seq.contains 2 resumed) @> do! Stream.unsubscribe resumedSub + // Compare to the native API, not to a frozen assumption about acknowledged-token + // replay: Orleans 10.1 skipped item 3 on an existing handle; 10.4 replays it. + let! nativeReplay = this.NativeCheckpointReplay(false) + let actualReplay = resumed |> Seq.filter ((<>) 6) |> Seq.toList + test <@ actualReplay = nativeReplay @> + let subscribeRef = Stream.getStream streamProvider "subscribe-from-handlers-ns" (Guid.NewGuid().ToString()) @@ -531,10 +573,9 @@ type StreamingIntegrationTests(fixture: ClusterFixture) = fun () -> Seq.contains 4 subscribed && Seq.contains 5 subscribed ) - test <@ Seq.contains 3 subscribed @> - test <@ not (Seq.contains 1 subscribed) @> - test <@ not (Seq.contains 2 subscribed) @> do! Stream.unsubscribe subscribedSub + let subscribedReplay = subscribed |> Seq.filter ((<>) 6) |> Seq.toList + test <@ subscribedReplay = [ 3; 4; 5 ] @> } [] @@ -590,10 +631,9 @@ type StreamingIntegrationTests(fixture: ClusterFixture) = fun () -> Seq.contains 4 subscribed && Seq.contains 5 subscribed ) - test <@ Seq.contains 3 subscribed @> - test <@ not (Seq.contains 1 subscribed) @> - test <@ not (Seq.contains 2 subscribed) @> do! Stream.unsubscribe subscribedSub + let subscribedReplay = subscribed |> Seq.filter ((<>) 6) |> Seq.toList + test <@ subscribedReplay = [ 3; 4; 5 ] @> let resumeRef = Stream.getStream streamProvider "resume-from-batch-ns" (Guid.NewGuid().ToString()) let! resumeSource, resumeCheckpoint = this.SeedCheckpoint(resumeRef, 5, 3) @@ -606,10 +646,10 @@ type StreamingIntegrationTests(fixture: ClusterFixture) = ) do! this.NudgeUntil(resumeRef, 6, fun () -> Seq.contains 4 resumed && Seq.contains 5 resumed) - test <@ not (Seq.contains 3 resumed) @> - test <@ not (Seq.contains 1 resumed) @> - test <@ not (Seq.contains 2 resumed) @> do! Stream.unsubscribe resumedSub + let! nativeReplay = this.NativeCheckpointReplay(true) + let actualReplay = resumed |> Seq.filter ((<>) 6) |> Seq.toList + test <@ actualReplay = nativeReplay @> } [] diff --git a/tests/Orleans.FSharp.Tests/FunctionalCodecTests.fs b/tests/Orleans.FSharp.Tests/FunctionalCodecTests.fs index 5d0d034..46791aa 100644 --- a/tests/Orleans.FSharp.Tests/FunctionalCodecTests.fs +++ b/tests/Orleans.FSharp.Tests/FunctionalCodecTests.fs @@ -18,6 +18,7 @@ open Orleans.CodeGeneration open Orleans.Serialization open Orleans.Serialization.Buffers open Orleans.Serialization.Codecs +open Orleans.Serialization.Cloning open Orleans.Serialization.Session open Orleans.Serialization.Invocation open Orleans.Serialization.WireProtocol @@ -549,6 +550,27 @@ let ``the envelope and reply copy as the immutable values they are`` () = test <@ obj.ReferenceEquals((copier ()).Copy value, value) @> test <@ obj.ReferenceEquals((copier ()).Copy reply, reply) @> +[] +let ``every functional copier preserves null input directly`` () = + let provider = services.Value.GetRequiredService() + use context = services.Value.GetRequiredService().GetContext() + + // Invoke the registered copiers themselves: DeepCopier.Copy(null) can short-circuit before + // reaching them and would miss a null dereference introduced by an Orleans contract update. + let assertNull (expectedCopier: Type) (input: 'T) = + let registered = provider.GetDeepCopier<'T>() + Assert.IsType(expectedCopier, registered) |> ignore + let copy: 'T = registered.DeepCopy(input, context) + Assert.Null(box copy) + + assertNull typeof (null: FunctionalRequestEnvelope) + assertNull typeof (null: FunctionalReply) + assertNull typeof (null: FunctionalRequest) + assertNull typeof (null: FunctionalTransactionRequest) + assertNull typeof (null: FunctionalStreamRequest) + assertNull typeof (null: FunctionalNotificationEnvelope) + assertNull typeof> (null: FunctionalObserverHandle) + // ────────────────────────────────────────────────────────────────────────────── // Request argument surface and cancellation // ────────────────────────────────────────────────────────────────────────────── diff --git a/tests/Orleans.FSharp.Tests/FunctionalPersistenceSerializationTests.fs b/tests/Orleans.FSharp.Tests/FunctionalPersistenceSerializationTests.fs index 8d44c5d..8de79c1 100644 --- a/tests/Orleans.FSharp.Tests/FunctionalPersistenceSerializationTests.fs +++ b/tests/Orleans.FSharp.Tests/FunctionalPersistenceSerializationTests.fs @@ -174,8 +174,15 @@ let ``functional persistence payload limit must be positive`` () = [] let ``functional FSharp JSON encoding round-trips without using the Orleans payload codec`` () = - let services, binary = binaryCodec () - use services = services + let binary = + { new IFunctionalPayloadCodec with + member _.Serialize<'T>(_value: 'T) : byte[] = + failwith "The JSON writer must not use the Orleans binary codec." + + member _.Deserialize<'T>(_bytes: byte[]) : 'T = + failwith "The JSON reader must not use the Orleans binary codec." + + member _.MaxPayloadBytes = FunctionalPersistenceCodec.DefaultMaxPayloadBytes } let encoded = FunctionalPersistenceEncoding.encode FunctionalPersistenceCodec.FSharpJson binary payload @@ -187,6 +194,10 @@ let ``functional FSharp JSON encoding round-trips without using the Orleans payl FunctionalPersistenceEncoding.FSharpJsonId encoded + // An independent JSON reader must understand the durable bytes, not only our paired decoder. + let independentlyRestored = JsonSerializer.Deserialize(encoded, FSharpJson.serializerOptions) + + test <@ independentlyRestored = payload @> test <@ restored = payload @> [] diff --git a/tests/Orleans.FSharp.Tests/GrainHandlerStateMachineProperties.fs b/tests/Orleans.FSharp.Tests/GrainHandlerStateMachineProperties.fs index aeedb25..9b1e0eb 100644 --- a/tests/Orleans.FSharp.Tests/GrainHandlerStateMachineProperties.fs +++ b/tests/Orleans.FSharp.Tests/GrainHandlerStateMachineProperties.fs @@ -118,20 +118,21 @@ let private applyViaHandler #warnon "44" [] -let ``handleState score-tracker: total games = Wins + Losses + Draws`` (cmds: ScoreTrackerCommand list) = - let s = applyViaHandler scoreTrackerHandleState cmds - let nonResetCmds = - cmds - |> List.fold (fun (acc, live) cmd -> - match cmd with - | Reset -> acc, false - | Win | Lose | Draw when live -> acc + 1, live - | GetScore -> acc, live - | _ -> acc, live) (0, true) - |> fst - // After all resets, the last "live" segment determines the totals - // Simpler invariant: Wins + Losses + Draws >= 0 always - s.Wins >= 0 && s.Losses >= 0 && s.Draws >= 0 +let ``score-tracker handlers count exactly the games after the last reset`` (cmds: ScoreTrackerCommand list) = + // Derive the model from the command log, not by repeating a handler's state transitions. + // A mandatory suffix covers every outcome and a mid-sequence reset even for an empty input. + let commands = [ Win; Lose; Draw; Reset ] @ cmds @ [ Draw; Win; GetScore; Lose; Draw ] + let sinceReset = commands |> List.rev |> List.takeWhile ((<>) Reset) + let count command = sinceReset |> List.filter ((=) command) |> List.length + let wins, losses, draws = count Win, count Lose, count Draw + + [ scoreTrackerHandleState; scoreTrackerHandleTyped; scoreTrackerCancellable ] + |> List.forall (fun definition -> + let state = applyViaHandler definition commands + state.Wins = wins + && state.Losses = losses + && state.Draws = draws + && state.NetScore = wins - losses) [] let ``handleState score-tracker: net score equals wins minus losses`` (cmds: ScoreTrackerCommand list) = diff --git a/tests/Orleans.FSharp.Tests/GrainResilienceTests.fs b/tests/Orleans.FSharp.Tests/GrainResilienceTests.fs index 35ec7fa..69ea0f8 100644 --- a/tests/Orleans.FSharp.Tests/GrainResilienceTests.fs +++ b/tests/Orleans.FSharp.Tests/GrainResilienceTests.fs @@ -608,46 +608,31 @@ let ``buildPipeline rejects options outside the bounds Polly validates`` () = // --------------------------------------------------------------------------- [] -let ``retry count is bounded: actual calls <= maxAttempts + 1`` (attempts: PositiveInt) = - let maxAttempts = min attempts.Get 10 // cap to avoid slow tests - let callCount = ref 0 - - let f () = - task { - System.Threading.Interlocked.Increment(callCount) |> ignore - raise (InvalidOperationException("always fails")) - return 0 - } - - try - GrainResilience.retry maxAttempts TimeSpan.Zero f |> ignore - with _ -> - () - - // Wait for the task to complete (it always throws here) - let mutable waited = false +let ``retry exhausts exactly its budget and preserves the terminal failure`` (attempts: NonNegativeInt) = + // FsCheck accepts Async properties; the operation itself remains a Task and is fully awaited. + async { + let maxAttempts = min attempts.Get 10 + let callCount = ref 0 + // Each attempt has a distinct failure: returning the first exception after exhausting + // the budget must not look like preserving the terminal exception. + let failures = + Array.init (maxAttempts + 1) (fun index -> InvalidOperationException($"attempt {index + 1}")) - let task = - try - GrainResilience.retry maxAttempts TimeSpan.Zero (fun () -> - task { - System.Threading.Interlocked.Increment(callCount) |> ignore - raise (InvalidOperationException("always fails")) - return 0 - }) - with _ -> - waited <- true - Task.FromResult(0) + let operation () = + task { + // Force asynchronous completion so a fire-and-forget wrapper cannot pass. + do! Task.Yield() + let attempt = System.Threading.Interlocked.Increment(callCount) + return raise failures.[attempt - 1] + } - if not waited then - try - task.Wait() - with _ -> - () + let! actual = + Assert.ThrowsAsync(fun () -> + GrainResilience.retry maxAttempts TimeSpan.Zero operation :> Task) + |> Async.AwaitTask - // The call count accumulated from both runs (initial + retries per run) is bounded - // We just check the property is structurally satisfied (no infinite retry) - !callCount <= (maxAttempts + 1) * 2 + return obj.ReferenceEquals(actual, failures.[maxAttempts]) && !callCount = maxAttempts + 1 + } [] let ``execute with 0 retries calls the function exactly once`` (value: int) = diff --git a/website/package-lock.json b/website/package-lock.json index 8c7ef7b..e1cf974 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -15,29 +15,46 @@ } }, "node_modules/@astrojs/compiler-binding": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.4.0.tgz", - "integrity": "sha512-x2RjDUuWfwLNtc3mjAdSRInwqh/rqbLar9cm/5FOMbHvmYZB7yfKewzSclAxWjIZsypJDXv1lhaP2WG+P8TK3g==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding/-/compiler-binding-0.5.2.tgz", + "integrity": "sha512-lEn76+0JcMQ5RDXU0wSMWJg2ZppiZvSULpghC29cfv4o9bhvWFDbQjsCtvjjXN9iVLFQ7fL3wTR2L2UU13mP8g==", "license": "MIT", "engines": { "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@astrojs/compiler-binding-darwin-arm64": "0.4.0", - "@astrojs/compiler-binding-darwin-x64": "0.4.0", - "@astrojs/compiler-binding-linux-arm64-gnu": "0.4.0", - "@astrojs/compiler-binding-linux-arm64-musl": "0.4.0", - "@astrojs/compiler-binding-linux-x64-gnu": "0.4.0", - "@astrojs/compiler-binding-linux-x64-musl": "0.4.0", - "@astrojs/compiler-binding-wasm32-wasi": "0.4.0", - "@astrojs/compiler-binding-win32-arm64-msvc": "0.4.0", - "@astrojs/compiler-binding-win32-x64-msvc": "0.4.0" + "@astrojs/compiler-binding-android-arm64": "0.5.2", + "@astrojs/compiler-binding-darwin-arm64": "0.5.2", + "@astrojs/compiler-binding-darwin-x64": "0.5.2", + "@astrojs/compiler-binding-linux-arm64-gnu": "0.5.2", + "@astrojs/compiler-binding-linux-arm64-musl": "0.5.2", + "@astrojs/compiler-binding-linux-x64-gnu": "0.5.2", + "@astrojs/compiler-binding-linux-x64-musl": "0.5.2", + "@astrojs/compiler-binding-wasm32-wasi": "0.5.2", + "@astrojs/compiler-binding-win32-arm64-msvc": "0.5.2", + "@astrojs/compiler-binding-win32-x64-msvc": "0.5.2" + } + }, + "node_modules/@astrojs/compiler-binding-android-arm64": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-android-arm64/-/compiler-binding-android-arm64-0.5.2.tgz", + "integrity": "sha512-kckIxon6Rm/Bxzh9mGPYpRRqUbToUQoHptCmpMmE+Yt0Xumq8CqrKUidyYhrBsrHVO7bxuRzzWUUqvpf+iYceQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@astrojs/compiler-binding-darwin-arm64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.4.0.tgz", - "integrity": "sha512-ZVUwHundaQyFNjE6uoa0usaC0WOCitDCLS/4mdb4rOiJXwVUuKJBMxI5WMzXLWmamsXtK/Z//ifLXvV5Yeh4Hw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-arm64/-/compiler-binding-darwin-arm64-0.5.2.tgz", + "integrity": "sha512-1ZG5Ar3dD8HtodX9XH1mRmE0qBXZlvjYXSFfpgFwocqfWnvhFuqtGUNseL8wgfImiRMztIjpQqlogQFQQtgiag==", "cpu": [ "arm64" ], @@ -51,9 +68,9 @@ } }, "node_modules/@astrojs/compiler-binding-darwin-x64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.4.0.tgz", - "integrity": "sha512-FI6G8AY8u6fR1SI/QRR5yGMwtvZwP34CDmZpZ5HwJGa50UM1VISTLhqkhV4a476pmgd25X1Aur2dqw6hUnrlKA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-darwin-x64/-/compiler-binding-darwin-x64-0.5.2.tgz", + "integrity": "sha512-+kl35S7hiHJ2cb7eujwEsPFYYuSgE11uEE2Z20lAJ+undpgulMcW+weQqFPOSSZccEKHOiLIY+kQHkb4e4092w==", "cpu": [ "x64" ], @@ -67,9 +84,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-arm64-gnu": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.4.0.tgz", - "integrity": "sha512-lB9gLFJK7m82EnjaU8nlRBEfcwGNeHidW3sSjODTUjMNaoewVuUz9fwwdY5M4jiSXIqWLH3yl6TX8FTDKA74Sw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-gnu/-/compiler-binding-linux-arm64-gnu-0.5.2.tgz", + "integrity": "sha512-BqlR0EHNQLPLwgL9+xogjsAc7zGf0cHho2CPdhv0P1yqbVMwGVaGAqrANP6VYAXCqSC43AF4Czcxc2n+oqdesg==", "cpu": [ "arm64" ], @@ -86,9 +103,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-arm64-musl": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.4.0.tgz", - "integrity": "sha512-HPbvWqbxFxyaoQJhLxCaSjtYBx9KBo7JGVzEFZCmMl968a2PsSH0UfiODYgYPXofTOIsIH2aoCcrHXML0IA3ig==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-arm64-musl/-/compiler-binding-linux-arm64-musl-0.5.2.tgz", + "integrity": "sha512-GRGyby3AZWw5d6JQzidyxPyvGgHWsSusrpgKyFVpDTKctABF7L3Pd5V1cRJbV36/rcu+Eh292/wL7pF7MkmGkQ==", "cpu": [ "arm64" ], @@ -105,9 +122,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-x64-gnu": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.4.0.tgz", - "integrity": "sha512-tQKolMxoJ/+0AmLWm1PmJ/i+z3i10ZU1bNuVjEDulCf48azEMtUNjTZgHJ5MPtpYRNc7dlETr8QujUfduzoC7Q==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-gnu/-/compiler-binding-linux-x64-gnu-0.5.2.tgz", + "integrity": "sha512-9XAqGTMQAtIslMsjK3xdyY6OI9d59OZqcLBB6pvD/DcoR0daYswfrKx2azdDERDY4AqAnWPC7odVM1BmxYv3Vw==", "cpu": [ "x64" ], @@ -124,9 +141,9 @@ } }, "node_modules/@astrojs/compiler-binding-linux-x64-musl": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.4.0.tgz", - "integrity": "sha512-5v5YymudsxMHp3NBLCS8BUlu5CRqeLtWD9cKS/4nIhIEHCbpz9okmVV6I0HWqmBAPhWYcDa3vw/vltYPrOQCTA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-linux-x64-musl/-/compiler-binding-linux-x64-musl-0.5.2.tgz", + "integrity": "sha512-jOViewGeTh9bSfS8vK72ECxoy2yvmA+Pd/ZcEvBI5c7+7IcfHwZ5qA4L9fRYuOhSrAifvQ2dV4vm1XAtloaWBw==", "cpu": [ "x64" ], @@ -143,25 +160,27 @@ } }, "node_modules/@astrojs/compiler-binding-wasm32-wasi": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.4.0.tgz", - "integrity": "sha512-m/phuH3x3PREvv1OnkM44NoPh4MatUadix1fB1u5SvMLCyDTUZykDJbKnWf1cjnYmHdlB8HcjTjl6JrCqAIXcw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-wasm32-wasi/-/compiler-binding-wasm32-wasi-0.5.2.tgz", + "integrity": "sha512-Z7p64doar1uvR5C9Xs6j1CV9lGlPVQX7OQ2aAtZ/xKC5aGS6GB13nyc2UfQXTQLvZrvVwsyaflTQy6ziY5Bekw==", "cpu": [ "wasm32" ], "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.2.2" + "@emnapi/core": "1.11.3", + "@emnapi/runtime": "1.11.3", + "@napi-rs/wasm-runtime": "^1.2.5" }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@astrojs/compiler-binding-win32-arm64-msvc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.4.0.tgz", - "integrity": "sha512-B9zYf3okEY83kM8gydlpH2BHP00w4ifxPqlYlWrgTwuD6wnkrJDCwBlgy1q31cERjCJRXN1lrE2VmkLvFjv/6g==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-arm64-msvc/-/compiler-binding-win32-arm64-msvc-0.5.2.tgz", + "integrity": "sha512-Tr13bh+ahTWsjXjzctK7pFpWV+dUU4FtBfETlR7gO+ueex0F+RDch7eRr0YfKysaRhk9tWm14lsCJ5uWyFPNHQ==", "cpu": [ "arm64" ], @@ -175,9 +194,9 @@ } }, "node_modules/@astrojs/compiler-binding-win32-x64-msvc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.4.0.tgz", - "integrity": "sha512-zB0Nrv0dGc0zZWPGDRmmETTPhDRqyZjAjk+gWMlVrJX5U89obpB3VUUE1ZiHxOCN5LQojeLK6O8L/dnoHolvNQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-binding-win32-x64-msvc/-/compiler-binding-win32-x64-msvc-0.5.2.tgz", + "integrity": "sha512-SfKkI+jOQYLh6wojPvVPV0lFfQnxisweN9B+qCzRvZp7DHAuGif8Y0WcC5PUgN4jb8VKy57LggQDtggR46Du1g==", "cpu": [ "x64" ], @@ -191,12 +210,12 @@ } }, "node_modules/@astrojs/compiler-rs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.4.0.tgz", - "integrity": "sha512-koVikeon1kreEy+/JzLQRy3vzHHQVOjycs4degg4vFufKApZOwMZvSSAEztYNhmcQVfNVsVZZI4cEge3cexAbQ==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler-rs/-/compiler-rs-0.5.2.tgz", + "integrity": "sha512-IvwYLB8t1M86rKO4oPdBi9GP4gzXcgrVlNgocjwos1jeeUuEIV8d9Crn1PvYD/5IKteWOxpIHomf7e8iYlkE+Q==", "license": "MIT", "dependencies": { - "@astrojs/compiler-binding": "0.4.0" + "@astrojs/compiler-binding": "0.5.2" }, "engines": { "node": ">=22.12.0" @@ -218,31 +237,6 @@ "unified": "^11.0.5" } }, - "node_modules/@astrojs/markdown-remark": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.4.tgz", - "integrity": "sha512-MvspGMynWKAjTe4/lTUdmBPHIFKNVLTCF6UlyWGogTGzNrTvjD+D4n48k7h8swxsEPKHK2TwxkZO7uoaCv1Pow==", - "license": "MIT", - "dependencies": { - "@astrojs/internal-helpers": "0.10.4", - "@astrojs/prism": "4.0.2", - "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "hast-util-to-text": "^4.0.2", - "mdast-util-definitions": "^6.0.0", - "rehype-raw": "^7.0.0", - "rehype-stringify": "^10.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-smartypants": "^3.0.2", - "unified": "^11.0.5", - "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.1.0", - "unist-util-visit-parents": "^6.0.2", - "vfile": "^6.0.3" - } - }, "node_modules/@astrojs/markdown-satteri": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.3.8.tgz", @@ -477,6 +471,31 @@ } } }, + "node_modules/@astrojs/mdx/node_modules/@astrojs/markdown-remark": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.4.tgz", + "integrity": "sha512-MvspGMynWKAjTe4/lTUdmBPHIFKNVLTCF6UlyWGogTGzNrTvjD+D4n48k7h8swxsEPKHK2TwxkZO7uoaCv1Pow==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.10.4", + "@astrojs/prism": "4.0.2", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.1.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, "node_modules/@astrojs/prism": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", @@ -547,24 +566,24 @@ } }, "node_modules/@astrojs/telemetry": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.3.tgz", - "integrity": "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.4.2.tgz", + "integrity": "sha512-2JOMRUxJrBSfiVDfeKLv1wBmvSIx1Y6u2YEO8awZ9qSq3u/rNAiUyFdOYi8dHv91kHrmYEQX7pRDw0J4xyj3UA==", "license": "MIT", "dependencies": { "ci-info": "^4.4.0", "dset": "^3.1.4", "is-docker": "^4.0.0", - "package-manager-detector": "^1.6.0" + "package-manager-detector": "^1.9.0" }, "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" + "node": ">=22.23.4" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "version": "7.29.11", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.11.tgz", + "integrity": "sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -580,12 +599,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", - "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "version": "7.29.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.12.tgz", + "integrity": "sha512-WJ7JBp/Q4+z/ImydtI7jS6NVco5++632ExBemSX+Ysb+G1lCwQ5BVo3SY+jGGOcZXI4ZccbZSUSJLNBW6eEpJg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.8" + "@babel/types": "^7.29.11" }, "bin": { "parser": "bin/babel-parser.js" @@ -595,12 +614,12 @@ } }, "node_modules/@babel/types": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", - "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "version": "7.29.11", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.11.tgz", + "integrity": "sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-string-parser": "^7.29.11", "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { @@ -785,9 +804,9 @@ } }, "node_modules/@clack/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.3.tgz", - "integrity": "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz", + "integrity": "sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ==", "license": "MIT", "dependencies": { "fast-wrap-ansi": "^0.2.0", @@ -798,12 +817,12 @@ } }, "node_modules/@clack/prompts": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.7.0.tgz", - "integrity": "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.8.1.tgz", + "integrity": "sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==", "license": "MIT", "dependencies": { - "@clack/core": "1.4.3", + "@clack/core": "1.5.1", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" @@ -827,7 +846,6 @@ "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" @@ -849,427 +867,10 @@ "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", - "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", - "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", - "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", - "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", - "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", - "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", - "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", - "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", - "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", - "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", - "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", - "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", - "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", - "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", - "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", - "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", - "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", - "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", - "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", - "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", - "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", - "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", - "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", - "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", - "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", - "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@expressive-code/core": { "version": "0.44.1", "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.44.1.tgz", @@ -1325,9 +926,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", - "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz", + "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==", "cpu": [ "arm64" ], @@ -1343,13 +944,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.3.3" + "@img/sharp-libvips-darwin-arm64": "1.3.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", - "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz", + "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==", "cpu": [ "x64" ], @@ -1365,20 +966,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.3.3" + "@img/sharp-libvips-darwin-x64": "1.3.4" } }, "node_modules/@img/sharp-freebsd-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", - "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz", + "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==", "license": "Apache-2.0", "optional": true, "os": [ "freebsd" ], "dependencies": { - "@img/sharp-wasm32": "0.35.4" + "@img/sharp-wasm32": "0.35.5" }, "engines": { "node": ">=20.9.0" @@ -1388,9 +989,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", - "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz", + "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==", "cpu": [ "arm64" ], @@ -1404,9 +1005,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", - "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz", + "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==", "cpu": [ "x64" ], @@ -1420,9 +1021,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", - "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz", + "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==", "cpu": [ "arm" ], @@ -1439,9 +1040,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", - "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz", + "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==", "cpu": [ "arm64" ], @@ -1458,9 +1059,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", - "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz", + "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==", "cpu": [ "ppc64" ], @@ -1477,9 +1078,9 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", - "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz", + "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==", "cpu": [ "riscv64" ], @@ -1496,9 +1097,9 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", - "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz", + "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==", "cpu": [ "s390x" ], @@ -1515,9 +1116,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", - "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz", + "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==", "cpu": [ "x64" ], @@ -1534,9 +1135,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", - "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz", + "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==", "cpu": [ "arm64" ], @@ -1553,9 +1154,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", - "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz", + "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==", "cpu": [ "x64" ], @@ -1572,9 +1173,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", - "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz", + "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==", "cpu": [ "arm" ], @@ -1593,13 +1194,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.3.3" + "@img/sharp-libvips-linux-arm": "1.3.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", - "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz", + "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==", "cpu": [ "arm64" ], @@ -1618,13 +1219,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.3.3" + "@img/sharp-libvips-linux-arm64": "1.3.4" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", - "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz", + "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==", "cpu": [ "ppc64" ], @@ -1643,13 +1244,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.3.3" + "@img/sharp-libvips-linux-ppc64": "1.3.4" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", - "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz", + "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==", "cpu": [ "riscv64" ], @@ -1668,13 +1269,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.3.3" + "@img/sharp-libvips-linux-riscv64": "1.3.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", - "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz", + "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==", "cpu": [ "s390x" ], @@ -1693,13 +1294,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.3.3" + "@img/sharp-libvips-linux-s390x": "1.3.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", - "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz", + "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==", "cpu": [ "x64" ], @@ -1718,13 +1319,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.3.3" + "@img/sharp-libvips-linux-x64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", - "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz", + "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==", "cpu": [ "arm64" ], @@ -1743,13 +1344,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", - "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz", + "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==", "cpu": [ "x64" ], @@ -1768,13 +1369,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.3.3" + "@img/sharp-libvips-linuxmusl-x64": "1.3.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", - "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz", + "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==", "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -1788,16 +1389,16 @@ } }, "node_modules/@img/sharp-webcontainers-wasm32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", - "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz", + "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==", "cpu": [ "wasm32" ], "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/sharp-wasm32": "0.35.4" + "@img/sharp-wasm32": "0.35.5" }, "engines": { "node": ">=20.9.0" @@ -1807,9 +1408,9 @@ } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", - "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz", + "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==", "cpu": [ "arm64" ], @@ -1826,9 +1427,9 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", - "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz", + "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==", "cpu": [ "ia32" ], @@ -1845,9 +1446,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", - "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz", + "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==", "cpu": [ "x64" ], @@ -1907,9 +1508,9 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", - "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.6.tgz", + "integrity": "sha512-mRyDmEw9/fCDXCGfL1sbgIw/GUK0PVxRW4YwgPN61F3LQ+fSyoBFarJVzgGyhF6kRzEQZ0FejDqm4WLXSeqQmw==", "license": "MIT", "optional": true, "dependencies": { @@ -1923,8 +1524,8 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + "@emnapi/core": "^1.7.1 || 2.0.0-beta.2", + "@emnapi/runtime": "^1.7.1 || 2.0.0-beta.2" } }, "node_modules/@oslojs/encoding": { @@ -1934,12 +1535,12 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.147.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.147.0.tgz", - "integrity": "sha512-IJ3s6ltHLp45S0bh7phkX+gJO7A1Wuz2EaqpAhb8WjqDwbzMiWKHhyyT42tskaWjEYXtHtVCPpnBJVT9+dcRLg==", + "version": "0.156.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.156.0.tgz", + "integrity": "sha512-1Duyg48TdJNdyhEB8Xn1L36bT9Pv6GUtlKjHxOys8xkaF/rQq3XJE+bAurSK/AgIz5mGFsb77cn9Pb20+WCScw==", "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@pagefind/darwin-arm64": { @@ -2040,9 +1641,9 @@ ] }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.6.tgz", - "integrity": "sha512-b+jTcARdTiFLI6jB4a5XjTm0RWd6KcRfQj/I2356fxUZemiho9zQLxo0RtCuMDAyKcLo6cEltkgbQp6d1+sjjQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.16.tgz", + "integrity": "sha512-ia3DwAs0OsMGS7+IConptSiyk9pEXkOx/AbJ2n/lAGxH3QkWQus1t8d7gnAT38FCU2sQu8lUbeR6AiZFv4JxaA==", "cpu": [ "arm" ], @@ -2056,9 +1657,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.6.tgz", - "integrity": "sha512-lkWU8ZJaRk9q3CIEY1Tc7vIFALp3Xw5NfGJo2hQg5oIqNgxWi1zI+IiDEK3r70BF5Dzol1tcXsnzsRc8NLhG+Q==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.16.tgz", + "integrity": "sha512-kx5wBiMB6E7TEvpl2B9gjLU004BkvEm2Dr941BFjx/SontPwSzNuQUIoVKxHHoSjpFIfHMmcguyLOtyn0hObRg==", "cpu": [ "arm64" ], @@ -2072,9 +1673,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.6.tgz", - "integrity": "sha512-dgR56NYnvAszm7Ob1B2/Vn0e8bUQYZH2UjVaMMtMVOCKFSfjhfLmuA/9+O+F+ajUdG6B/bSssrKW6JJYASa8jA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.16.tgz", + "integrity": "sha512-qslZrXnKJU4cUpjoAmtAo/KQM9e2IRMlmpig6Zpwj+8KWxW8v+nkAf9216Bsek9lOC1jvg2yCjygCFo2f83msQ==", "cpu": [ "arm64" ], @@ -2088,9 +1689,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.6.tgz", - "integrity": "sha512-vpVxFvUCFioJqug7OTvqptkc4yb8UX0AwfDmJpaR/0sWz+BUmqSVAf7c8JkUgnN8YLspb4a/N6NhTyMAmdyQ7Q==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.16.tgz", + "integrity": "sha512-FdF+y48ND13eAyM2mQn+85kvAqNlvRWROy2rhgA463X/0Gv4vGtazZtfaF1mRBLscYvtOlh4QnLjOWiFzX69OQ==", "cpu": [ "x64" ], @@ -2104,9 +1705,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.6.tgz", - "integrity": "sha512-h1wG6Y6K3JlRswxsI64qQJqBAy4vrLuHgRbc8CZMGSWTOFRY6ghMApM1NKzB2I0n5xV1fjkE18SuVl2QpLeNpA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.16.tgz", + "integrity": "sha512-ddjqFM5e95AgLbUPtKIS7V1KTVlA0RUgCVr5mn+/IEhsdy3pr+Vuj/HZ7nlMN2FyxIwUktOH1LEPIQXO1v9y1Q==", "cpu": [ "x64" ], @@ -2120,9 +1721,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.6.tgz", - "integrity": "sha512-tbCiqub0q2MVWJKgF5PoAlNWCtQydiOYSLIkd8sByqK/6MMYLJRcSXSYodqYtd0O+Fw7QaVmKKlS4oL94YRZ0w==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.16.tgz", + "integrity": "sha512-tHdKWbFkFBI687iim3LIyIvyL7j66VvQYkDPss5Stn/qyE2tWkR1YD0dXmXPFKKqT/o5ZEJVsaRsWS2meQwGOA==", "cpu": [ "arm" ], @@ -2136,9 +1737,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.6.tgz", - "integrity": "sha512-oxK9+baEBPhZG5HB4URY+uU04zJWeZlH6Tb9rB5DK4DF9XR1uXNLXt5Q5ZsugTKayNCNLhkcwz/ye74hRI98dg==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.16.tgz", + "integrity": "sha512-FJiLGAblPBMlBEdbOqw6kW6QcXDWAf/oJu7gYs9ZJZwmg+K+/zjFLxPTIY9izJUzxzc24FHvmseyA0IvJSl17w==", "cpu": [ "arm64" ], @@ -2155,9 +1756,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.6.tgz", - "integrity": "sha512-muWCk27FVBEZtv0MsK8gnfSmgczA8KQ0uRVJbTABKhkRfQc38aUrcb7fhi3BNiyseFmgcRsoMfQsSNJ+DbZdSw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.16.tgz", + "integrity": "sha512-hrJpblMsrQ58U9veWpbXzkhV5zStunds6HWLprqq1qauvgBr1E6P+24kLj6lSLI9vjRn/RYpjprhkHQPKGWpNg==", "cpu": [ "arm64" ], @@ -2174,9 +1775,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.6.tgz", - "integrity": "sha512-eWDoSfU7Co2qj3vgB3Dt4lj1mG6CoWbcJQkRMP3XJplyCMtuaq3LHvPFjS9QIPvMGWVadJC04Xiy0IdcVPtnwQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.16.tgz", + "integrity": "sha512-qJd/dC6j6CwLG9/s/RP2nb1RZ0GIgj7Ioj7x/SYa3RzjVrlzrmH0fhIOpfvqQDeIsdP0loi+kHaMhJzY1PBIaA==", "cpu": [ "ppc64" ], @@ -2193,9 +1794,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.6.tgz", - "integrity": "sha512-2bWNjRSIayvupRKxXUY2tWG9fYdoUlTqWywHRvE8Eq3GvuQ+f2HeIkve697fIt+IQs/PV8yFsdWuhp1aJ1PdnA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.16.tgz", + "integrity": "sha512-Vx7Xg5uUJuNcujJjI70OICaH0EYj80BtOLZTSN7uOYg8QOLlyKnaG0IW7Fn/J0IpJsaKzmDKMhOQv1JBM9m9vg==", "cpu": [ "s390x" ], @@ -2212,9 +1813,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.6.tgz", - "integrity": "sha512-KekI0gS0wLxe1UBSQSjenBVwou/JkcQPDzBPICGZjxUv9k3RteHDPBQaiOicZUFKRIH2wKEimGwVpnJsbPzu7w==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.16.tgz", + "integrity": "sha512-TNKhgE3uJTsTzatUSSYt0Kgo+Oa2uSlSjz4r1aEIea7HX6ULBym4fAlYUhG1i6pjNf2njfCUAfKwr6C3E9Xg1w==", "cpu": [ "x64" ], @@ -2231,9 +1832,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.6.tgz", - "integrity": "sha512-TvtPnfVr+HtyGiDmPK4VWmlNm7QhNNAcK5Q9A7aOXsI8545yCyaoMaicXrFZ72JzeYjaUVk7yT243zT0jzjFKQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.16.tgz", + "integrity": "sha512-7chXdpjXZ8qG0+mIxECN3cT9kvhZ3/oZhMX6Pp876P7CDrIy8nJswva6Mq357JR7eYXfuskwZxMeV1SzoZdHrA==", "cpu": [ "x64" ], @@ -2250,9 +1851,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.6.tgz", - "integrity": "sha512-iOo0VEay2XFhaCcH0sps5XIimkSuOnNaZrf6+ZkoSOQBJPKNU48RkmJv0/lSpipexu5P+ouFgafe5IGr/DiQfg==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.16.tgz", + "integrity": "sha512-Kwjt+7uNTJK5/MDkGWGVO2KQPnj8yAV75dMpfwyHZrJSXWHrniOB0aUEWlVYf3H1hOqFLIStLdM5QXq6bnKmOQ==", "cpu": [ "arm64" ], @@ -2266,9 +1867,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.6.tgz", - "integrity": "sha512-y5NTmmasMS455JlOCO4ZM9krIchv3Mvm1crL1iUPGOPgEzSkves9n0SdC5Sjz6+qWDFhd8/JpfWMH8NSWNHe+A==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.16.tgz", + "integrity": "sha512-/LH6WfjDRXXJz/p5xl4TmU+jpcnwcxbKEQBW/GZE0JHfN0lGIyTtsUEGaQ/q/GikkGJ2yLKe6pwm7AnEWO8pdw==", "cpu": [ "arm64" ], @@ -2282,9 +1883,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.6.tgz", - "integrity": "sha512-np8iZSLfXlAD4kWhiyq/u0Yt8oZDtRQ8lGhQaCXo2rl37KNjeU0GjJuwr4P3oeZ++ROfofsKNBqR5LTO8aXyWQ==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.16.tgz", + "integrity": "sha512-1lv1KvX0Z871zfk7vw+dnXMMnHNyDwMzWG8Kv3HxDXMOhzCX4SHc7HK319fInP0i+0p9D8brkfzL7pJOaGl+tw==", "cpu": [ "x64" ], @@ -2304,13 +1905,13 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", - "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.5.0.tgz", + "integrity": "sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==", "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/primitive": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" @@ -2320,12 +1921,12 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", - "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.5.0.tgz", + "integrity": "sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -2334,12 +1935,12 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", - "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.5.0.tgz", + "integrity": "sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -2347,24 +1948,24 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", - "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.5.0.tgz", + "integrity": "sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", - "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.5.0.tgz", + "integrity": "sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -2373,21 +1974,21 @@ } }, "node_modules/@shikijs/themes": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", - "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.5.0.tgz", + "integrity": "sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", - "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.5.0.tgz", + "integrity": "sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -2398,9 +1999,9 @@ } }, "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.1.0.tgz", + "integrity": "sha512-cVBuhDQjBZaNMTwBquYfPydrUP+E3hE6oYGasx8h6ZrODIM7/r+gxLDXdd66oszbrggZHEntdE6j+5gYIVyMWQ==", "license": "MIT" }, "node_modules/@tybys/wasm-util": { @@ -2513,9 +2114,9 @@ "license": "ISC" }, "node_modules/acorn": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", - "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.19.0.tgz", + "integrity": "sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2534,9 +2135,9 @@ } }, "node_modules/am-i-vibing": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.4.0.tgz", - "integrity": "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/am-i-vibing/-/am-i-vibing-0.5.0.tgz", + "integrity": "sha512-KLcsDhqf1XRrJmJr+9I/C0EX2K+sGrAGZFgkmd84c8TJO9zJBu+/kFInjazu1KfJWFhWDKdRWkpBzEs7s35DVA==", "license": "MIT", "dependencies": { "process-ancestry": "^0.1.0" @@ -2611,70 +2212,69 @@ } }, "node_modules/astro": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/astro/-/astro-7.2.9.tgz", - "integrity": "sha512-o5nZFo/bieF6rp4x9sQSLhI7GO7Bahpld38Y4LvX27nFoxNiuttjI+Hea81w5ksORLHgdPUlQpU9obPz5QRa8g==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/astro/-/astro-7.4.4.tgz", + "integrity": "sha512-e+BzhGCaIY/H1tV/BQPTbOPZVZ8wuu6+bbpc+3oSMH2UgoB1l9peSGASk6nswtYra9PO9OoMREhldKtQkZ5TVw==", "license": "MIT", "dependencies": { - "@astrojs/compiler-rs": "^0.4.0", - "@astrojs/internal-helpers": "0.10.4", - "@astrojs/markdown-satteri": "0.3.8", - "@astrojs/telemetry": "3.3.3", - "@capsizecss/unpack": "^4.0.0", - "@clack/prompts": "^1.1.0", + "@astrojs/compiler-rs": "^0.5.1", + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/markdown-satteri": "0.4.6", + "@astrojs/telemetry": "3.4.2", + "@capsizecss/unpack": "^4.0.1", + "@clack/prompts": "^1.8.1", "@oslojs/encoding": "^1.1.0", - "am-i-vibing": "^0.4.0", + "am-i-vibing": "^0.5.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", - "devalue": "^5.8.1", + "devalue": "^6.0.2", "diff": "^9.0.0", "dset": "^3.1.4", - "es-module-lexer": "^2.0.0", - "esbuild": "^0.28.0", - "find-proc": "0.1.0", + "es-module-lexer": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.4.1", - "get-tsconfig": "5.0.0-beta.4", + "get-tsconfig": "5.0.0-beta.6", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", - "http-cache-semantics": "^4.2.0", - "js-yaml": "^4.3.0", + "http-cache-semantics": "^4.3.0", "jsonc-parser": "^3.3.1", - "magic-string": "^1.0.0", - "magicast": "^0.5.2", + "magic-string": "^1.4.3", + "magicast": "^0.5.5", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", - "obug": "^2.1.1", - "p-limit": "^7.3.0", - "p-queue": "^9.1.0", - "package-manager-detector": "^1.6.0", + "obug": "^3.0.0", + "p-limit": "^7.3.3", + "p-queue": "^9.3.5", + "package-manager-detector": "^1.9.0", "piccolore": "^0.1.3", - "picomatch": "^4.0.4", - "semver": "^7.7.4", - "shiki": "^4.0.2", - "smol-toml": "^1.6.0", - "svgo": "^4.0.1", - "tinyclip": "^0.1.12", - "tinyexec": "^1.0.4", - "tinyglobby": "^0.2.15", - "ultrahtml": "^1.6.0", - "unifont": "~0.7.5", + "picomatch": "^4.0.7", + "rolldown": "^1.2.14", + "shiki": "^4.5.0", + "smol-toml": "^1.9.1", + "svgo": "^4.1.0", + "tinyclip": "^1.0.3", + "tinyexec": "^1.3.1", + "tinyglobby": "^0.2.17", + "tinyps": "^0.5.0", + "ultrahtml": "^1.7.0", + "unifont": "^1.0.3", "unstorage": "^1.17.5", - "vite": "^8.0.13", - "vitefu": "^1.1.2", + "verkit": "^0.5.0", + "vite": "^8.3.5", + "vitefu": "^1.1.3", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", - "zod": "^4.3.6" + "zod": "^4.6.6" }, "bin": { "astro": "bin/astro.mjs" }, "engines": { - "node": ">=22.12.0", + "node": ">=22.23.4", "npm": ">=9.6.5", "pnpm": ">=7.1.0" }, @@ -2686,7 +2286,7 @@ "sharp": "^0.35.4" }, "peerDependencies": { - "@astrojs/markdown-remark": "7.2.4" + "@astrojs/markdown-remark": "^7.3.0" }, "peerDependenciesMeta": { "@astrojs/markdown-remark": { @@ -2707,13 +2307,247 @@ "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta || ^7.0.0" } }, + "node_modules/astro/node_modules/@astrojs/internal-helpers": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.13.0.tgz", + "integrity": "sha512-20jxQqnSmpskcGyad7N5l6Xf1gz0UCa6lNde44bEBdaXGpncEYfAZJ142r2ZgzBaG4dUyzGmhqZWv1INU2eiHQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.5", + "@types/mdast": "^4.0.4", + "picomatch": "^4.0.7", + "retext-smartypants": "^6.2.0", + "shiki": "^4.5.0", + "smol-toml": "^1.9.1", + "unified": "^11.0.5", + "yaml": "^2.9.1" + } + }, + "node_modules/astro/node_modules/@astrojs/markdown-satteri": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-satteri/-/markdown-satteri-0.4.6.tgz", + "integrity": "sha512-6biKp2lEAYycF3jhv91br+Otyf4EgDFkF1oRL9ks0u/m/YRGmI7XkGQ2MgaM35DslT03f7NtozKtlqfBNkp6bw==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.13.0", + "@astrojs/prism": "4.1.2", + "github-slugger": "^2.0.0", + "satteri": "^0.10.5" + } + }, + "node_modules/astro/node_modules/@astrojs/prism": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.1.2.tgz", + "integrity": "sha512-jMrUEpFDarDO1KWPvVc9eSa8DSfwBlwEOHwX+8zvZQpiqXRGDxFnOXHsYqV6DP7w+0qIgTr98gS1GdQlm8ypWg==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": ">=22.23.4" + } + }, + "node_modules/astro/node_modules/@bruits/satteri-darwin-arm64": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-arm64/-/satteri-darwin-arm64-0.10.5.tgz", + "integrity": "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-darwin-x64": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-darwin-x64/-/satteri-darwin-x64-0.10.5.tgz", + "integrity": "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-linux-arm64-gnu": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-gnu/-/satteri-linux-arm64-gnu-0.10.5.tgz", + "integrity": "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-linux-arm64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-arm64-musl/-/satteri-linux-arm64-musl-0.10.5.tgz", + "integrity": "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-linux-x64-gnu": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-gnu/-/satteri-linux-x64-gnu-0.10.5.tgz", + "integrity": "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-linux-x64-musl": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-linux-x64-musl/-/satteri-linux-x64-musl-0.10.5.tgz", + "integrity": "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-wasm32-wasi": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-wasm32-wasi/-/satteri-wasm32-wasi-0.10.5.tgz", + "integrity": "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.2.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/astro/node_modules/@bruits/satteri-win32-arm64-msvc": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-arm64-msvc/-/satteri-win32-arm64-msvc-0.10.5.tgz", + "integrity": "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/astro/node_modules/@bruits/satteri-win32-x64-msvc": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@bruits/satteri-win32-x64-msvc/-/satteri-win32-x64-msvc-0.10.5.tgz", + "integrity": "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/astro/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/astro/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/astro/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/astro/node_modules/es-module-lexer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-3.0.4.tgz", + "integrity": "sha512-BldNY5mwkVu+cQ5Ymn3e6hB9Sx8XHx4ZevWbiUyZbfKxJxYO27Hf0wfzkxIaD5CAJMaGl3YspKELj0ff/7nCMA==", + "license": "MIT" + }, "node_modules/astro/node_modules/magic-string": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz", - "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.5.tgz", + "integrity": "sha512-oLLC2+YvQUfAa+vxoufE/yc1icb87M9iXIRqAoR/2EhE/8cb3SF/+Gi0c2By1B+5Vz2e2vQtUvHiu1+63Znh+w==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@jridgewell/sourcemap-codec": "^1.6.0" + } + }, + "node_modules/astro/node_modules/satteri": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/satteri/-/satteri-0.10.5.tgz", + "integrity": "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.5", + "@types/hast": "^3.0.5", + "@types/mdast": "^4.0.4", + "@types/unist": "^3.0.3" + }, + "optionalDependencies": { + "@bruits/satteri-darwin-arm64": "0.10.5", + "@bruits/satteri-darwin-x64": "0.10.5", + "@bruits/satteri-linux-arm64-gnu": "0.10.5", + "@bruits/satteri-linux-arm64-musl": "0.10.5", + "@bruits/satteri-linux-x64-gnu": "0.10.5", + "@bruits/satteri-linux-x64-musl": "0.10.5", + "@bruits/satteri-wasm32-wasi": "0.10.5", + "@bruits/satteri-win32-arm64-msvc": "0.10.5", + "@bruits/satteri-win32-x64-msvc": "0.10.5" } }, "node_modules/axobject-query": { @@ -3084,10 +2918,13 @@ } }, "node_modules/devalue": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.2.tgz", - "integrity": "sha512-po4PAY5c53tw5XMocSnf8A/5OHhbbUftpr93aEN6BBoAdntUmK7vu7wOATqvt7cXO7m1Cl4gMVn6p7n6n4mj0w==", - "license": "MIT" + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-6.0.3.tgz", + "integrity": "sha512-3woMEITftG1wKeO/4d/QXH1DVKctTSZg3jNGPpjp9hNr5Hos8MCFF5McTML5ZtgKDObm2R591B0spRp2IVernA==", + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/devlop": { "version": "1.1.0", @@ -3250,47 +3087,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/esbuild": { - "version": "0.28.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", - "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.2", - "@esbuild/android-arm": "0.28.2", - "@esbuild/android-arm64": "0.28.2", - "@esbuild/android-x64": "0.28.2", - "@esbuild/darwin-arm64": "0.28.2", - "@esbuild/darwin-x64": "0.28.2", - "@esbuild/freebsd-arm64": "0.28.2", - "@esbuild/freebsd-x64": "0.28.2", - "@esbuild/linux-arm": "0.28.2", - "@esbuild/linux-arm64": "0.28.2", - "@esbuild/linux-ia32": "0.28.2", - "@esbuild/linux-loong64": "0.28.2", - "@esbuild/linux-mips64el": "0.28.2", - "@esbuild/linux-ppc64": "0.28.2", - "@esbuild/linux-riscv64": "0.28.2", - "@esbuild/linux-s390x": "0.28.2", - "@esbuild/linux-x64": "0.28.2", - "@esbuild/netbsd-arm64": "0.28.2", - "@esbuild/netbsd-x64": "0.28.2", - "@esbuild/openbsd-arm64": "0.28.2", - "@esbuild/openbsd-x64": "0.28.2", - "@esbuild/openharmony-arm64": "0.28.2", - "@esbuild/sunos-x64": "0.28.2", - "@esbuild/win32-arm64": "0.28.2", - "@esbuild/win32-ia32": "0.28.2", - "@esbuild/win32-x64": "0.28.2" - } - }, "node_modules/escape-string-regexp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", @@ -3459,15 +3255,6 @@ } } }, - "node_modules/find-proc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/find-proc/-/find-proc-0.1.0.tgz", - "integrity": "sha512-OaOpEYv2PiQ7SQ5LIrl+deA1XaWcxEjnpM6VuWXTUvn+teIXxeFTLDmu18/zDQpFmHN4o3oDBX+BT0AGwEhemg==", - "license": "MIT", - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/flattie": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", @@ -3477,6 +3264,12 @@ "node": ">=8" } }, + "node_modules/fnv1a-64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fnv1a-64/-/fnv1a-64-0.1.2.tgz", + "integrity": "sha512-mJbcILTPybAR1jdOwt/lVv8N2cffeJFFP+gVbSAwLEx1ujXH27RpPd8Rokec/KX9c76UYIB6Co+H4lQzxPnJfA==", + "license": "MIT" + }, "node_modules/fontace": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", @@ -3513,9 +3306,9 @@ } }, "node_modules/get-tsconfig": { - "version": "5.0.0-beta.4", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", - "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", + "version": "5.0.0-beta.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.6.tgz", + "integrity": "sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==", "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -3942,9 +3735,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz", + "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==", "license": "BSD-2-Clause" }, "node_modules/i18next": { @@ -4388,9 +4181,9 @@ } }, "node_modules/magicast": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz", - "integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.5.tgz", + "integrity": "sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.7", @@ -5501,9 +5294,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "funding": [ { "type": "github", @@ -5574,9 +5367,9 @@ } }, "node_modules/obug": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz", + "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==", "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" @@ -5597,12 +5390,6 @@ "ufo": "^1.6.1" } }, - "node_modules/ohash": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.12.tgz", - "integrity": "sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==", - "license": "MIT" - }, "node_modules/oniguruma-parser": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", @@ -5621,9 +5408,9 @@ } }, "node_modules/p-limit": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.1.tgz", - "integrity": "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.3.tgz", + "integrity": "sha512-SKgVvDU5TNIxQ4r30U75BNLC6a+6GOEjngrk/ysM5+Zu3oJuk1SC5ApzIzY/7PjCEjoVPMWJ0zho/4QUiEB7TQ==", "license": "MIT", "dependencies": { "yocto-queue": "^1.2.1" @@ -5636,9 +5423,9 @@ } }, "node_modules/p-queue": { - "version": "9.3.3", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.3.tgz", - "integrity": "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.5.tgz", + "integrity": "sha512-Lki/zhXFVmDhesBUn/yHRLW9Bte7mE7xoFHzTR8sIomV7a2z+LxYAPkGvdfidNiu4fKSfjtawixxSHcZci5QcQ==", "license": "MIT", "dependencies": { "eventemitter3": "^5.0.4", @@ -5652,9 +5439,9 @@ } }, "node_modules/p-timeout": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", - "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.2.tgz", + "integrity": "sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==", "license": "MIT", "engines": { "node": ">=20" @@ -5664,9 +5451,9 @@ } }, "node_modules/package-manager-detector": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.8.0.tgz", - "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz", + "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==", "license": "MIT" }, "node_modules/pagefind": { @@ -5767,9 +5554,9 @@ } }, "node_modules/postcss": { - "version": "8.5.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", - "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "version": "8.5.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.32.tgz", + "integrity": "sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g==", "funding": [ { "type": "opencollective", @@ -5786,9 +5573,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.17", + "nanoid": "^3.3.20", "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -5820,9 +5607,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", - "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.5.tgz", + "integrity": "sha512-TEHFzb5KRDKaOgJ4TYE+0jyJtFbjLvkdVOu0fZ2b6MTWzoqZd4Le+61aEppWkvTlYePgOX4ATL1wsAIPMLTw6Q==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -6251,12 +6038,12 @@ } }, "node_modules/rolldown": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.6.tgz", - "integrity": "sha512-vMM4q3aixf46GiF1Kok8jDPFsEpXgFWGjUHXNkNHNm+Y2adXAG2dbX91jkti3i0ZRsOlcmbuzAz1poObSHCmUA==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.16.tgz", + "integrity": "sha512-bWvlMpFKiTfDKfnK7FC2MPgPeWCf/Kpwsq49ApdW+FQaBZb6O6dZ4MAPbPUjp7hYQrw/RobqCzn64BRrQecGHw==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.147.0", + "@oxc-project/types": "=0.156.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -6266,21 +6053,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.6", - "@rolldown/binding-android-arm64": "1.2.6", - "@rolldown/binding-darwin-arm64": "1.2.6", - "@rolldown/binding-darwin-x64": "1.2.6", - "@rolldown/binding-freebsd-x64": "1.2.6", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.6", - "@rolldown/binding-linux-arm64-gnu": "1.2.6", - "@rolldown/binding-linux-arm64-musl": "1.2.6", - "@rolldown/binding-linux-ppc64-gnu": "1.2.6", - "@rolldown/binding-linux-s390x-gnu": "1.2.6", - "@rolldown/binding-linux-x64-gnu": "1.2.6", - "@rolldown/binding-linux-x64-musl": "1.2.6", - "@rolldown/binding-openharmony-arm64": "1.2.6", - "@rolldown/binding-win32-arm64-msvc": "1.2.6", - "@rolldown/binding-win32-x64-msvc": "1.2.6" + "@rolldown/binding-android-arm-eabi": "1.2.16", + "@rolldown/binding-android-arm64": "1.2.16", + "@rolldown/binding-darwin-arm64": "1.2.16", + "@rolldown/binding-darwin-x64": "1.2.16", + "@rolldown/binding-freebsd-x64": "1.2.16", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.16", + "@rolldown/binding-linux-arm64-gnu": "1.2.16", + "@rolldown/binding-linux-arm64-musl": "1.2.16", + "@rolldown/binding-linux-ppc64-gnu": "1.2.16", + "@rolldown/binding-linux-s390x-gnu": "1.2.16", + "@rolldown/binding-linux-x64-gnu": "1.2.16", + "@rolldown/binding-linux-x64-musl": "1.2.16", + "@rolldown/binding-openharmony-arm64": "1.2.16", + "@rolldown/binding-win32-arm64-msvc": "1.2.16", + "@rolldown/binding-win32-x64-msvc": "1.2.16" } }, "node_modules/satteri": { @@ -6328,9 +6115,9 @@ } }, "node_modules/sharp": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", - "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", + "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==", "license": "Apache-2.0", "dependencies": { "@img/colour": "^1.1.0", @@ -6344,31 +6131,31 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.35.4", - "@img/sharp-darwin-x64": "0.35.4", - "@img/sharp-freebsd-wasm32": "0.35.4", - "@img/sharp-libvips-darwin-arm64": "1.3.3", - "@img/sharp-libvips-darwin-x64": "1.3.3", - "@img/sharp-libvips-linux-arm": "1.3.3", - "@img/sharp-libvips-linux-arm64": "1.3.3", - "@img/sharp-libvips-linux-ppc64": "1.3.3", - "@img/sharp-libvips-linux-riscv64": "1.3.3", - "@img/sharp-libvips-linux-s390x": "1.3.3", - "@img/sharp-libvips-linux-x64": "1.3.3", - "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", - "@img/sharp-libvips-linuxmusl-x64": "1.3.3", - "@img/sharp-linux-arm": "0.35.4", - "@img/sharp-linux-arm64": "0.35.4", - "@img/sharp-linux-ppc64": "0.35.4", - "@img/sharp-linux-riscv64": "0.35.4", - "@img/sharp-linux-s390x": "0.35.4", - "@img/sharp-linux-x64": "0.35.4", - "@img/sharp-linuxmusl-arm64": "0.35.4", - "@img/sharp-linuxmusl-x64": "0.35.4", - "@img/sharp-webcontainers-wasm32": "0.35.4", - "@img/sharp-win32-arm64": "0.35.4", - "@img/sharp-win32-ia32": "0.35.4", - "@img/sharp-win32-x64": "0.35.4" + "@img/sharp-darwin-arm64": "0.35.5", + "@img/sharp-darwin-x64": "0.35.5", + "@img/sharp-freebsd-wasm32": "0.35.5", + "@img/sharp-libvips-darwin-arm64": "1.3.4", + "@img/sharp-libvips-darwin-x64": "1.3.4", + "@img/sharp-libvips-linux-arm": "1.3.4", + "@img/sharp-libvips-linux-arm64": "1.3.4", + "@img/sharp-libvips-linux-ppc64": "1.3.4", + "@img/sharp-libvips-linux-riscv64": "1.3.4", + "@img/sharp-libvips-linux-s390x": "1.3.4", + "@img/sharp-libvips-linux-x64": "1.3.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4", + "@img/sharp-libvips-linuxmusl-x64": "1.3.4", + "@img/sharp-linux-arm": "0.35.5", + "@img/sharp-linux-arm64": "0.35.5", + "@img/sharp-linux-ppc64": "0.35.5", + "@img/sharp-linux-riscv64": "0.35.5", + "@img/sharp-linux-s390x": "0.35.5", + "@img/sharp-linux-x64": "0.35.5", + "@img/sharp-linuxmusl-arm64": "0.35.5", + "@img/sharp-linuxmusl-x64": "0.35.5", + "@img/sharp-webcontainers-wasm32": "0.35.5", + "@img/sharp-win32-arm64": "0.35.5", + "@img/sharp-win32-ia32": "0.35.5", + "@img/sharp-win32-x64": "0.35.5" }, "peerDependenciesMeta": { "@types/node": { @@ -6377,17 +6164,17 @@ } }, "node_modules/shiki": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", - "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.5.0.tgz", + "integrity": "sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==", "license": "MIT", "dependencies": { - "@shikijs/core": "4.4.3", - "@shikijs/engine-javascript": "4.4.3", - "@shikijs/engine-oniguruma": "4.4.3", - "@shikijs/langs": "4.4.3", - "@shikijs/themes": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/core": "4.5.0", + "@shikijs/engine-javascript": "4.5.0", + "@shikijs/engine-oniguruma": "4.5.0", + "@shikijs/langs": "4.5.0", + "@shikijs/themes": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -6421,9 +6208,9 @@ } }, "node_modules/smol-toml": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", - "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.1.tgz", + "integrity": "sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -6442,9 +6229,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6475,6 +6262,12 @@ "@astrojs/starlight": ">=0.41" } }, + "node_modules/std-env": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", + "license": "MIT" + }, "node_modules/stream-replace-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", @@ -6545,18 +6338,18 @@ "license": "MIT" }, "node_modules/tinyclip": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.15.tgz", - "integrity": "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-1.0.3.tgz", + "integrity": "sha512-nTv2raKFMzGG6JJp0lpNDsRPdfFE6UHlu2rVEjXo8vkx1ZS3LW2CVXqIaLu8xZlu+6tbFs9V58Qc/Jmk/Ii7wA==", "license": "MIT", "engines": { "node": "^16.14.0 || >= 17.3.0" } }, "node_modules/tinyexec": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", - "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz", + "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==", "license": "MIT", "engines": { "node": ">=18" @@ -6578,6 +6371,12 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyps": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/tinyps/-/tinyps-0.5.1.tgz", + "integrity": "sha512-B6Ykif5HflC3AdDkS4Zst/2muYVfeXoVMy+KorqH80s/1x4vunIORpNySH681X7fjj+dFM9MDKD6/Hsccjb87Q==", + "license": "MIT" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -6624,9 +6423,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz", - "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==", + "version": "8.12.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.12.3.tgz", + "integrity": "sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==", "license": "MIT", "engines": { "node": ">=22.19.0" @@ -6658,13 +6457,14 @@ } }, "node_modules/unifont": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.5.tgz", - "integrity": "sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-1.0.3.tgz", + "integrity": "sha512-XGnEwj5sWdCbiBX01mWLSBncS0yMRjnLygau3IfdOlfjMacNIQvTGW4VH7pWBq+gGWArfSef/CensMLjMmIr/A==", "license": "MIT", "dependencies": { "css-tree": "^3.1.0", - "ohash": "^2.0.11", + "fnv1a-64": "^0.1.2", + "std-env": "^4.2.0", "undici": "^8.0.0" } }, @@ -6918,6 +6718,18 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/verkit": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.5.0.tgz", + "integrity": "sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==", + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -6961,15 +6773,15 @@ } }, "node_modules/vite": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", - "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz", + "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==", "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.26", - "rolldown": "~1.2.4", + "picomatch": "^4.0.7", + "postcss": "^8.5.30", + "rolldown": "~1.2.14", "tinyglobby": "^0.2.17" }, "bin": { @@ -6986,7 +6798,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.4.0 || ^0.5.0", + "@vitejs/devtools": "^0.7.1 || ^0.8.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -7072,6 +6884,21 @@ "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", "license": "MIT" }, + "node_modules/yaml": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yargs-parser": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", @@ -7094,9 +6921,9 @@ } }, "node_modules/zod": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz", - "integrity": "sha512-sC95tT5iHHH9gtpj6A81kh+NEaRAUFN+qlUPDUbRfOMvNf5QCBqsb3WgvnpVtK5Y+4UfA6KqufotuTvMGiTlsA==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/website/public/llms-full.txt b/website/public/llms-full.txt index 26931f5..569f2a7 100644 --- a/website/public/llms-full.txt +++ b/website/public/llms-full.txt @@ -451,6 +451,18 @@ tag while planning their migration. The runtime APIs are unchanged from 5.0.0. Version 5.0.1 corrects the packaged project template and adds startup regression coverage to the release gate. +### Upcoming 5.0.2 update + +The current branch prepares compatibility with **Orleans 10.4.2**, retaining the **10.1.0** +minimum and the existing public F# API. It aligns the transport copiers with Orleans' nullable +contract and updates build-time SourceLink tooling to remove a vulnerable Git task dependency. +Test hardening checks concrete state, retry outcomes, JSON bytes, and stream contents instead of +weaker count-only or paired round-trip assertions. This section is a candidate status, not a +claim that 5.0.2 has already been published. + +See [Orleans Compatibility](https://neftedollar.com/orleans-fsharp/compatibility/#what-changed-in-orleans-104) for runtime changes, +upgrade caveats, and new APIs considered separately from this patch. + The Legacy archive receives no new Legacy release line, features, compatibility work, or security fixes. New applications should use `grainContract`, `grainFor`, `journaledGrainFor`, typed API records, and `FunctionalGrain.ref`. @@ -476,8 +488,21 @@ initializes the grain definition and an end-to-end template process check in the Direct enumeration of a functional streaming reply is the supported path. With `FSharp.Control.TaskSeq` 1.1.1 on the repository's verified static resumable-code path, wrapping a runtime-returned `IAsyncEnumerable` with `TaskSeq.map` or -`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. TaskSeq -over ordinary producers such as lists, ranges, and database cursors is not affected. +`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. The +repository's ordinary list/range producers do not reproduce this wrapping problem; that is not +a guarantee about every third-party async source. + +As of **1 November 2026**, NuGet still publishes TaskSeq **1.1.1** and +[TaskSeq #452](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The merged reproduction-test PR is not a library fix. The F# compiler fix for Debug resumable-code +lowering was merged and [backported](https://github.com/dotnet/fsharp/pull/20692), but is not included +in stable SDK 10.0.403. The verified repository SDK remains 10.0.201; a closed compiler issue alone +is not sufficient evidence to lift that pin. + +The `UpstreamBoundary` integration cases compare actual item order and contents for empty, +single-item, and longer streams. Only the exact known final duplicate is tolerated for wrappers; +direct enumeration must match exactly. Green characterization tests therefore do **not** mean +the TaskSeq defect is fixed. Delivery, cancellation, and producer disposal have separate strict tests. When one grain relays another grain's streaming reply, return a direct delegating `IAsyncEnumerable`/enumerator instead of using those wrapping forms. The exact pattern and the SDK @@ -3723,10 +3748,17 @@ subscription. The corresponding new-subscription functions are `subscribeFromHan Build the argument to `resumeAllHandlers` with `StreamHandlers.withToken` when every resumed subscription must continue exposing provider cursors; a separate alias is unnecessary. -There is one deliberate Orleans distinction: `subscribeFrom*` creates a new subscription and the -tested memory provider includes the checkpoint event, while `resumeFrom` / `resumeBatchFrom` -reattach a handle which already acknowledged that event and continue after it. Keep that -new-subscription versus existing-handle distinction in migration tests for your chosen provider. +These helpers pass the checkpoint token to Orleans unchanged. **Do not assume that resuming an +existing handle is exclusive.** In our memory-provider tests, Orleans 10.1.0 skipped the already +acknowledged checkpoint event on `resumeFrom` / `resumeBatchFrom`; Orleans 10.4.2 replays it. +New `subscribeFrom*` subscriptions include that event on both versions. The integration tests +compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical +suffix, rather than imposing the older runtime's boundary on every version. + +Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests +for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in +[streaming replies](https://neftedollar.com/orleans-fsharp/streaming-replies/#authoring-a-producer); it does not justify dropping the +last item of an arbitrary stream. --- @@ -4928,7 +4960,7 @@ The handler returns the BCL `IAsyncEnumerable<'Item>` and nothing else, so any w works. `taskSeq { }` from `FSharp.Control.TaskSeq` is the natural F# tool and this library already depends on that package, so using it adds nothing to your closure. -> **One caveat, and it is not about this runtime.** In `FSharp.Control.TaskSeq` 1.1.1, the +> **Known TaskSeq/Orleans interoperability boundary.** In `FSharp.Control.TaskSeq` 1.1.1, the > *wrapping* forms — `TaskSeq.map`, and `taskSeq { for x in someStream do yield x }` — over an > `IAsyncEnumerable` returned by **this** runtime were measured yielding the last item twice under > an activation's task scheduler; direct enumeration is correct. So when one grain re-streams @@ -4942,12 +4974,18 @@ depends on that package, so using it adds nothing to your closure. > upstream.GetAsyncEnumerator ct }) > ``` > -> Producing from a `taskSeq { }` over ordinary data — a list, a range, a database cursor — is not -> affected and is what every example here does. This repository tests the Orleans-specific case +> The list/range producers used in these examples do not reproduce this wrapping problem; this +> is not a guarantee for every external async source. This repository tests the Orleans-specific case > against both its minimum and newest supported Orleans versions. The repository remains pinned > to SDK 10.0.201: TaskSeq's dynamic path under SDK 10.0.400 avoids this `taskSeq { for ... }` > duplication, but currently regresses stream delivery and producer-disposal propagation. +As of 1 November 2026, TaskSeq 1.1.1 is still the latest stable package and +[the upstream issue](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The compiler fix/backport has not reached stable SDK 10.0.403. The characterization tests allow +only the exact final-item duplicate, not arbitrary sequences with the same length; they are not +evidence that wrapping is production-safe. + This is tracked as an upstream production boundary, separate from the 4.1-versus-5.0 package split, in [Release and Production Status](https://neftedollar.com/orleans-fsharp/release-status/#taskseq-is-an-upstream-boundary-when-wrapping-streaming-replies). @@ -8598,8 +8636,9 @@ handler side is still an F# record. An observer facade is a possible future addi **Supported version policy, verified runtimes, and relevant changes in new Orleans releases.** -This page describes framework compatibility for Orleans.FSharp 5.0.1, the current published stable -release. See [Release and Production Status](https://neftedollar.com/orleans-fsharp/release-status/) for production boundaries. +This page describes the upcoming Orleans.FSharp 5.0.2 compatibility update. The current published +stable release is still 5.0.1; the 10.4.2 source-compatibility changes below belong to the update, +not retroactively to that release. See [Release and Production Status](https://neftedollar.com/orleans-fsharp/release-status/). ## Version policy @@ -8612,11 +8651,61 @@ current event-sourcing surface uses `JournaledGrain.ClearLogAsync`, which is abs |---|---|---| | 10.0.x | Not supported | Missing an API required by the current Orleans.FSharp assemblies | | 10.1.0 | Supported floor | The version used to compile packages and one end of the CI matrix | -| 10.3.1 | Latest stable Orleans release | The newest-version compatibility target | +| 10.3.1 | Previous compatibility target | Covered by the 5.0.1 release checks | +| 10.4.2 | Latest stable Orleans release as of 1 November 2026 | The newest-version compatibility target for 5.0.2 | The package floor should move only when Orleans.FSharp starts using a newer Orleans API. A new Orleans release alone is not a reason to force every consumer to upgrade. +## What changed in Orleans 10.4 + +Target **10.4.2**, including the servicing fixes after 10.4.0. The official notes for +[10.4.0](https://github.com/dotnet/orleans/releases/tag/v10.4.0), +[10.4.1](https://github.com/dotnet/orleans/releases/tag/v10.4.1), and +[10.4.2](https://github.com/dotnet/orleans/releases/tag/v10.4.2) describe several changes relevant +to functional grains: + +- Read-only request isolation, timer scheduling, and queued-request handling during activation + migration/retirement were corrected. Applications inherit these fixes from their Orleans runtime. +- Serializer type-authorization checks were hardened. ADO.NET streaming redelivery and Azure + membership interoperability also received fixes; the latter providers still need their own + application-level upgrade checks. +- `IDeepCopier` now describes nullable input explicitly. Seven hand-written Orleans.FSharp + transport/observer copiers are aligned with that contract in 5.0.2, including direct null-input + regression tests. This changes nullable annotations, not transport bytes or public F# APIs. +- Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint + event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; + consumers must not depend on exclusive resumption. See [checkpoint replay](https://neftedollar.com/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). +- The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build + dependency is updated without raising the Orleans package floor. +- RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a + serialized parameter ordinal. Audit application-owned C# grain interfaces before a rolling + upgrade, particularly tokens placed before other arguments. Our fixed transport places its + token last and writes the envelope with its existing explicit field ID; source inspection found + no corresponding ordinal change. This is not a blanket proof for arbitrary application interfaces. +- `SiloAddress.GetUniformHashCodes` changes its return type from an array to an immutable array. + Applications using that low-level API need a rebuild. Orleans.FSharp does not expose it as part + of its functional API. +- Request latency metrics move to `orleans-app-requests-latency`, a fractional-millisecond + histogram. Review dashboards/alerts, and apply the updated Orleans SQL scripts when using + existing SQLite storage databases. + +### Useful additions, separate from this compatibility update + +| Addition | How it fits Orleans.FSharp | +|---|---| +| Explicit stream subscription start: `Latest` / `EarliestAvailable` | A useful next F# helper, not added in 5.0.2. `EarliestAvailable` means the oldest retained **local queue-cache** item, not all provider history. Native 10.4 APIs are usable when the application targets that version; upgrade pulling-agent silos before enabling the feature. | +| Cancellation-aware framework operations | Evaluate helpers individually. Public stream subscribe/resume/unsubscribe still have no cancellation-token overload; cancelling only the wait can leak a subscription created later. Existing functional-call cancellation is separate. | +| Management `DeactivateGrain` | Usable through the native management grain on 10.4.1+; a dedicated F# convenience wrapper is optional. | +| New provider/cache configuration | Configure through native Orleans hosting APIs; no replacement F# configuration layer is required. | +| `Microsoft.Orleans.Journaling` / Durable Jobs | Still prerelease (`10.4.2-alpha.1`), deliberately deferred. They are not the log-consistency model wrapped by `journaledGrainFor`. | + +Adding first-class start-position helpers while retaining the 10.1 floor needs an explicit +unsupported-runtime error and tests for provider defaults, retained/empty caches, batch delivery, +and subscription cleanup. Falling back silently to ordinary live delivery would hide a semantic +change. The [upstream enum contract](https://github.com/dotnet/orleans/blob/v10.4.2/src/Orleans.Streaming/Core/StreamSubscriptionStartPosition.cs) +defines the cache boundary. + ## What changed in Orleans 10.3 Orleans 10.3.0 was released on 27 August 2026. Its @@ -8641,7 +8730,7 @@ version-contract analyzer metadata plus tests and documentation. See its [release notes](https://github.com/dotnet/orleans/releases/tag/v10.3.1) and [NuGet package](https://www.nuget.org/packages/Microsoft.Orleans.Server/10.3.1). -## Newly available Orleans surface +## Orleans 10.3 additions already assessed The release also highlights: @@ -8653,7 +8742,7 @@ The release also highlights: - incremental source generation and new Orleans application templates; - directory, membership, and rolling-upgrade reliability improvements. -These additions fall into three different categories: +Their compatibility boundaries are: | Category | Orleans.FSharp position | |---|---| @@ -8672,6 +8761,11 @@ The CI matrix keeps the package floor and newest stable Orleans separate. Its ne solution and runs unit tests, functional integration tests, separate-process rolling-update tests, stream tests, the functional sample, and the Dashboard smoke test against the selected release. +The N/N+1 rolling tests change **application** contracts and durable schemas with one Orleans +version per test run. They do not, by themselves, prove a cluster mixing Orleans 10.1 and 10.4 +binaries. Rebuilding against both versions is also different from running a floor-built NuGet +package on the newer runtime; package-consumer smoke checks cover that additional boundary. + This verifies the Orleans.FSharp surface exercised by those suites. It does **not** certify every third-party storage, clustering, or stream provider, nor does it prove that application-specific persisted data can be rolled back without an explicit schema migration strategy. For that, follow @@ -9632,7 +9726,10 @@ The returned value has the exact API-record type. ## Which Orleans versions are supported? -The current package range starts at Orleans 10.1.0 and is tested against both 10.1.0 and 10.3.1. A NuGet lower bound means older 10.0.x versions are not selected. See [Orleans Compatibility](https://neftedollar.com/orleans-fsharp/compatibility/) for release-specific notes. +The package range starts at Orleans 10.1.0. The published 5.0.1 release was tested through +10.3.1; the upcoming 5.0.2 update moves the newest compatibility target to 10.4.2 without raising +the minimum. A NuGet lower bound means older 10.0.x versions are not selected. See +[Orleans Compatibility](https://neftedollar.com/orleans-fsharp/compatibility/) for release-specific notes and verification boundaries. ## Does event sourcing support snapshots? diff --git a/website/src/content/docs/compatibility.md b/website/src/content/docs/compatibility.md index 1b0ec03..6bbb907 100644 --- a/website/src/content/docs/compatibility.md +++ b/website/src/content/docs/compatibility.md @@ -1,14 +1,15 @@ --- title: "Orleans Compatibility" -description: "Supported Orleans versions, the 10.3.1 compatibility target, and newly available framework surface." +description: "Supported Orleans versions, the 10.4.2 compatibility update, and newly available framework surface." --- # Orleans Compatibility **Supported version policy, verified runtimes, and relevant changes in new Orleans releases.** -This page describes framework compatibility for Orleans.FSharp 5.0.1, the current published stable -release. See [Release and Production Status](/orleans-fsharp/release-status/) for production boundaries. +This page describes the upcoming Orleans.FSharp 5.0.2 compatibility update. The current published +stable release is still 5.0.1; the 10.4.2 source-compatibility changes below belong to the update, +not retroactively to that release. See [Release and Production Status](/orleans-fsharp/release-status/). ## Version policy @@ -21,11 +22,61 @@ current event-sourcing surface uses `JournaledGrain.ClearLogAsync`, which is abs |---|---|---| | 10.0.x | Not supported | Missing an API required by the current Orleans.FSharp assemblies | | 10.1.0 | Supported floor | The version used to compile packages and one end of the CI matrix | -| 10.3.1 | Latest stable Orleans release | The newest-version compatibility target | +| 10.3.1 | Previous compatibility target | Covered by the 5.0.1 release checks | +| 10.4.2 | Latest stable Orleans release as of 1 November 2026 | The newest-version compatibility target for 5.0.2 | The package floor should move only when Orleans.FSharp starts using a newer Orleans API. A new Orleans release alone is not a reason to force every consumer to upgrade. +## What changed in Orleans 10.4 + +Target **10.4.2**, including the servicing fixes after 10.4.0. The official notes for +[10.4.0](https://github.com/dotnet/orleans/releases/tag/v10.4.0), +[10.4.1](https://github.com/dotnet/orleans/releases/tag/v10.4.1), and +[10.4.2](https://github.com/dotnet/orleans/releases/tag/v10.4.2) describe several changes relevant +to functional grains: + +- Read-only request isolation, timer scheduling, and queued-request handling during activation + migration/retirement were corrected. Applications inherit these fixes from their Orleans runtime. +- Serializer type-authorization checks were hardened. ADO.NET streaming redelivery and Azure + membership interoperability also received fixes; the latter providers still need their own + application-level upgrade checks. +- `IDeepCopier` now describes nullable input explicitly. Seven hand-written Orleans.FSharp + transport/observer copiers are aligned with that contract in 5.0.2, including direct null-input + regression tests. This changes nullable annotations, not transport bytes or public F# APIs. +- Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint + event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; + consumers must not depend on exclusive resumption. See [checkpoint replay](/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). +- The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build + dependency is updated without raising the Orleans package floor. +- RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a + serialized parameter ordinal. Audit application-owned C# grain interfaces before a rolling + upgrade, particularly tokens placed before other arguments. Our fixed transport places its + token last and writes the envelope with its existing explicit field ID; source inspection found + no corresponding ordinal change. This is not a blanket proof for arbitrary application interfaces. +- `SiloAddress.GetUniformHashCodes` changes its return type from an array to an immutable array. + Applications using that low-level API need a rebuild. Orleans.FSharp does not expose it as part + of its functional API. +- Request latency metrics move to `orleans-app-requests-latency`, a fractional-millisecond + histogram. Review dashboards/alerts, and apply the updated Orleans SQL scripts when using + existing SQLite storage databases. + +### Useful additions, separate from this compatibility update + +| Addition | How it fits Orleans.FSharp | +|---|---| +| Explicit stream subscription start: `Latest` / `EarliestAvailable` | A useful next F# helper, not added in 5.0.2. `EarliestAvailable` means the oldest retained **local queue-cache** item, not all provider history. Native 10.4 APIs are usable when the application targets that version; upgrade pulling-agent silos before enabling the feature. | +| Cancellation-aware framework operations | Evaluate helpers individually. Public stream subscribe/resume/unsubscribe still have no cancellation-token overload; cancelling only the wait can leak a subscription created later. Existing functional-call cancellation is separate. | +| Management `DeactivateGrain` | Usable through the native management grain on 10.4.1+; a dedicated F# convenience wrapper is optional. | +| New provider/cache configuration | Configure through native Orleans hosting APIs; no replacement F# configuration layer is required. | +| `Microsoft.Orleans.Journaling` / Durable Jobs | Still prerelease (`10.4.2-alpha.1`), deliberately deferred. They are not the log-consistency model wrapped by `journaledGrainFor`. | + +Adding first-class start-position helpers while retaining the 10.1 floor needs an explicit +unsupported-runtime error and tests for provider defaults, retained/empty caches, batch delivery, +and subscription cleanup. Falling back silently to ordinary live delivery would hide a semantic +change. The [upstream enum contract](https://github.com/dotnet/orleans/blob/v10.4.2/src/Orleans.Streaming/Core/StreamSubscriptionStartPosition.cs) +defines the cache boundary. + ## What changed in Orleans 10.3 Orleans 10.3.0 was released on 27 August 2026. Its @@ -50,7 +101,7 @@ version-contract analyzer metadata plus tests and documentation. See its [release notes](https://github.com/dotnet/orleans/releases/tag/v10.3.1) and [NuGet package](https://www.nuget.org/packages/Microsoft.Orleans.Server/10.3.1). -## Newly available Orleans surface +## Orleans 10.3 additions already assessed The release also highlights: @@ -62,7 +113,7 @@ The release also highlights: - incremental source generation and new Orleans application templates; - directory, membership, and rolling-upgrade reliability improvements. -These additions fall into three different categories: +Their compatibility boundaries are: | Category | Orleans.FSharp position | |---|---| @@ -81,6 +132,11 @@ The CI matrix keeps the package floor and newest stable Orleans separate. Its ne solution and runs unit tests, functional integration tests, separate-process rolling-update tests, stream tests, the functional sample, and the Dashboard smoke test against the selected release. +The N/N+1 rolling tests change **application** contracts and durable schemas with one Orleans +version per test run. They do not, by themselves, prove a cluster mixing Orleans 10.1 and 10.4 +binaries. Rebuilding against both versions is also different from running a floor-built NuGet +package on the newer runtime; package-consumer smoke checks cover that additional boundary. + This verifies the Orleans.FSharp surface exercised by those suites. It does **not** certify every third-party storage, clustering, or stream provider, nor does it prove that application-specific persisted data can be rolled back without an explicit schema migration strategy. For that, follow diff --git a/website/src/content/docs/faq.md b/website/src/content/docs/faq.md index 1606088..53a8cf4 100644 --- a/website/src/content/docs/faq.md +++ b/website/src/content/docs/faq.md @@ -42,7 +42,10 @@ The returned value has the exact API-record type. ## Which Orleans versions are supported? -The current package range starts at Orleans 10.1.0 and is tested against both 10.1.0 and 10.3.1. A NuGet lower bound means older 10.0.x versions are not selected. See [Orleans Compatibility](/orleans-fsharp/compatibility/) for release-specific notes. +The package range starts at Orleans 10.1.0. The published 5.0.1 release was tested through +10.3.1; the upcoming 5.0.2 update moves the newest compatibility target to 10.4.2 without raising +the minimum. A NuGet lower bound means older 10.0.x versions are not selected. See +[Orleans Compatibility](/orleans-fsharp/compatibility/) for release-specific notes and verification boundaries. ## Does event sourcing support snapshots? diff --git a/website/src/content/docs/release-status.md b/website/src/content/docs/release-status.md index b3cc08b..453e727 100644 --- a/website/src/content/docs/release-status.md +++ b/website/src/content/docs/release-status.md @@ -24,6 +24,18 @@ tag while planning their migration. The runtime APIs are unchanged from 5.0.0. Version 5.0.1 corrects the packaged project template and adds startup regression coverage to the release gate. +### Upcoming 5.0.2 update + +The current branch prepares compatibility with **Orleans 10.4.2**, retaining the **10.1.0** +minimum and the existing public F# API. It aligns the transport copiers with Orleans' nullable +contract and updates build-time SourceLink tooling to remove a vulnerable Git task dependency. +Test hardening checks concrete state, retry outcomes, JSON bytes, and stream contents instead of +weaker count-only or paired round-trip assertions. This section is a candidate status, not a +claim that 5.0.2 has already been published. + +See [Orleans Compatibility](/orleans-fsharp/compatibility/#what-changed-in-orleans-104) for runtime changes, +upgrade caveats, and new APIs considered separately from this patch. + The Legacy archive receives no new Legacy release line, features, compatibility work, or security fixes. New applications should use `grainContract`, `grainFor`, `journaledGrainFor`, typed API records, and `FunctionalGrain.ref`. @@ -49,8 +61,21 @@ initializes the grain definition and an end-to-end template process check in the Direct enumeration of a functional streaming reply is the supported path. With `FSharp.Control.TaskSeq` 1.1.1 on the repository's verified static resumable-code path, wrapping a runtime-returned `IAsyncEnumerable` with `TaskSeq.map` or -`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. TaskSeq -over ordinary producers such as lists, ranges, and database cursors is not affected. +`taskSeq { for item in upstream do yield item }` was measured duplicating the final item. The +repository's ordinary list/range producers do not reproduce this wrapping problem; that is not +a guarantee about every third-party async source. + +As of **1 November 2026**, NuGet still publishes TaskSeq **1.1.1** and +[TaskSeq #452](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The merged reproduction-test PR is not a library fix. The F# compiler fix for Debug resumable-code +lowering was merged and [backported](https://github.com/dotnet/fsharp/pull/20692), but is not included +in stable SDK 10.0.403. The verified repository SDK remains 10.0.201; a closed compiler issue alone +is not sufficient evidence to lift that pin. + +The `UpstreamBoundary` integration cases compare actual item order and contents for empty, +single-item, and longer streams. Only the exact known final duplicate is tolerated for wrappers; +direct enumeration must match exactly. Green characterization tests therefore do **not** mean +the TaskSeq defect is fixed. Delivery, cancellation, and producer disposal have separate strict tests. When one grain relays another grain's streaming reply, return a direct delegating `IAsyncEnumerable`/enumerator instead of using those wrapping forms. The exact pattern and the SDK diff --git a/website/src/content/docs/streaming-replies.md b/website/src/content/docs/streaming-replies.md index c2d3e31..ba9b9fd 100644 --- a/website/src/content/docs/streaming-replies.md +++ b/website/src/content/docs/streaming-replies.md @@ -275,7 +275,7 @@ The handler returns the BCL `IAsyncEnumerable<'Item>` and nothing else, so any w works. `taskSeq { }` from `FSharp.Control.TaskSeq` is the natural F# tool and this library already depends on that package, so using it adds nothing to your closure. -> **One caveat, and it is not about this runtime.** In `FSharp.Control.TaskSeq` 1.1.1, the +> **Known TaskSeq/Orleans interoperability boundary.** In `FSharp.Control.TaskSeq` 1.1.1, the > *wrapping* forms — `TaskSeq.map`, and `taskSeq { for x in someStream do yield x }` — over an > `IAsyncEnumerable` returned by **this** runtime were measured yielding the last item twice under > an activation's task scheduler; direct enumeration is correct. So when one grain re-streams @@ -289,12 +289,18 @@ depends on that package, so using it adds nothing to your closure. > upstream.GetAsyncEnumerator ct }) > ``` > -> Producing from a `taskSeq { }` over ordinary data — a list, a range, a database cursor — is not -> affected and is what every example here does. This repository tests the Orleans-specific case +> The list/range producers used in these examples do not reproduce this wrapping problem; this +> is not a guarantee for every external async source. This repository tests the Orleans-specific case > against both its minimum and newest supported Orleans versions. The repository remains pinned > to SDK 10.0.201: TaskSeq's dynamic path under SDK 10.0.400 avoids this `taskSeq { for ... }` > duplication, but currently regresses stream delivery and producer-disposal propagation. +As of 1 November 2026, TaskSeq 1.1.1 is still the latest stable package and +[the upstream issue](https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/452) remains open. +The compiler fix/backport has not reached stable SDK 10.0.403. The characterization tests allow +only the exact final-item duplicate, not arbitrary sequences with the same length; they are not +evidence that wrapping is production-safe. + This is tracked as an upstream production boundary, separate from the 4.1-versus-5.0 package split, in [Release and Production Status](/orleans-fsharp/release-status/#taskseq-is-an-upstream-boundary-when-wrapping-streaming-replies). diff --git a/website/src/content/docs/streaming.md b/website/src/content/docs/streaming.md index b7b6458..51f1ee2 100644 --- a/website/src/content/docs/streaming.md +++ b/website/src/content/docs/streaming.md @@ -258,10 +258,17 @@ subscription. The corresponding new-subscription functions are `subscribeFromHan Build the argument to `resumeAllHandlers` with `StreamHandlers.withToken` when every resumed subscription must continue exposing provider cursors; a separate alias is unnecessary. -There is one deliberate Orleans distinction: `subscribeFrom*` creates a new subscription and the -tested memory provider includes the checkpoint event, while `resumeFrom` / `resumeBatchFrom` -reattach a handle which already acknowledged that event and continue after it. Keep that -new-subscription versus existing-handle distinction in migration tests for your chosen provider. +These helpers pass the checkpoint token to Orleans unchanged. **Do not assume that resuming an +existing handle is exclusive.** In our memory-provider tests, Orleans 10.1.0 skipped the already +acknowledged checkpoint event on `resumeFrom` / `resumeBatchFrom`; Orleans 10.4.2 replays it. +New `subscribeFrom*` subscriptions include that event on both versions. The integration tests +compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical +suffix, rather than imposing the older runtime's boundary on every version. + +Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests +for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in +[streaming replies](/orleans-fsharp/streaming-replies/#authoring-a-producer); it does not justify dropping the +last item of an arbitrary stream. --- From 5489ea898c72af24686da8715d3b57756e59e3b1 Mon Sep 17 00:00:00 2001 From: Roman Melnikov Date: Sun, 1 Nov 2026 01:23:08 +0300 Subject: [PATCH 2/2] Explain upstream checkpoint replay correction --- docs/compatibility.md | 4 +++- docs/streaming.md | 6 ++++++ website/public/llms-full.txt | 10 +++++++++- website/src/content/docs/compatibility.md | 4 +++- website/src/content/docs/streaming.md | 6 ++++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/compatibility.md b/docs/compatibility.md index 13a5128..61c4b16 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -41,7 +41,9 @@ to functional grains: regression tests. This changes nullable annotations, not transport bytes or public F# APIs. - Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; - consumers must not depend on exclusive resumption. See [checkpoint replay](streaming.md#resuming-subscriptions-after-reactivation). + consumers must not depend on exclusive resumption. This corrects start-token handling in + Orleans 10.4.0's [PR #10936](https://github.com/dotnet/orleans/pull/10936), not a new F# delivery + defect. See [checkpoint replay](streaming.md#resuming-subscriptions-after-reactivation). - The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build dependency is updated without raising the Orleans package floor. - RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a diff --git a/docs/streaming.md b/docs/streaming.md index 1a243ec..4ec269a 100644 --- a/docs/streaming.md +++ b/docs/streaming.md @@ -260,6 +260,12 @@ New `subscribeFrom*` subscriptions include that event on both versions. The inte compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical suffix, rather than imposing the older runtime's boundary on every version. +This is an upstream correction in Orleans 10.4.0's +[PR #10936](https://github.com/dotnet/orleans/pull/10936): an explicit start token stays inclusive +during delivery-handshake renegotiation, whereas an acknowledged delivery token advances past the +already delivered event. It applies to explicit-token resumption even without selecting the new +`EarliestAvailable` option. Tokenless resumption is a different operation. + Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in [streaming replies](streaming-replies.md#authoring-a-producer); it does not justify dropping the diff --git a/website/public/llms-full.txt b/website/public/llms-full.txt index 569f2a7..b276d5b 100644 --- a/website/public/llms-full.txt +++ b/website/public/llms-full.txt @@ -3755,6 +3755,12 @@ New `subscribeFrom*` subscriptions include that event on both versions. The inte compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical suffix, rather than imposing the older runtime's boundary on every version. +This is an upstream correction in Orleans 10.4.0's +[PR #10936](https://github.com/dotnet/orleans/pull/10936): an explicit start token stays inclusive +during delivery-handshake renegotiation, whereas an acknowledged delivery token advances past the +already delivered event. It applies to explicit-token resumption even without selecting the new +`EarliestAvailable` option. Tokenless resumption is a different operation. + Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in [streaming replies](https://neftedollar.com/orleans-fsharp/streaming-replies/#authoring-a-producer); it does not justify dropping the @@ -8675,7 +8681,9 @@ to functional grains: regression tests. This changes nullable annotations, not transport bytes or public F# APIs. - Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; - consumers must not depend on exclusive resumption. See [checkpoint replay](https://neftedollar.com/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). + consumers must not depend on exclusive resumption. This corrects start-token handling in + Orleans 10.4.0's [PR #10936](https://github.com/dotnet/orleans/pull/10936), not a new F# delivery + defect. See [checkpoint replay](https://neftedollar.com/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). - The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build dependency is updated without raising the Orleans package floor. - RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a diff --git a/website/src/content/docs/compatibility.md b/website/src/content/docs/compatibility.md index 6bbb907..68349c6 100644 --- a/website/src/content/docs/compatibility.md +++ b/website/src/content/docs/compatibility.md @@ -46,7 +46,9 @@ to functional grains: regression tests. This changes nullable annotations, not transport bytes or public F# APIs. - Explicit-token resumption of an existing memory-stream subscription now replays the checkpoint event in our 10.4.2 tests, where 10.1.0 skipped it. The F# helpers preserve native Orleans behavior; - consumers must not depend on exclusive resumption. See [checkpoint replay](/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). + consumers must not depend on exclusive resumption. This corrects start-token handling in + Orleans 10.4.0's [PR #10936](https://github.com/dotnet/orleans/pull/10936), not a new F# delivery + defect. See [checkpoint replay](/orleans-fsharp/streaming/#resuming-subscriptions-after-reactivation). - The Dashboard example needs OpenTelemetry.Api 1.18.0 with Dashboard 10.4.2. The central build dependency is updated without raising the Orleans package floor. - RPC parameter `[Id]` values are now honored and `CancellationToken` no longer consumes a diff --git a/website/src/content/docs/streaming.md b/website/src/content/docs/streaming.md index 51f1ee2..3294fd9 100644 --- a/website/src/content/docs/streaming.md +++ b/website/src/content/docs/streaming.md @@ -265,6 +265,12 @@ New `subscribeFrom*` subscriptions include that event on both versions. The inte compare the wrapper with direct native `ResumeAsync` and require the exact ordered historical suffix, rather than imposing the older runtime's boundary on every version. +This is an upstream correction in Orleans 10.4.0's +[PR #10936](https://github.com/dotnet/orleans/pull/10936): an explicit start token stays inclusive +during delivery-handshake renegotiation, whereas an acknowledged delivery token advances past the +already delivered event. It applies to explicit-token resumption even without selecting the new +`EarliestAvailable` option. Tokenless resumption is a different operation. + Make checkpoint consumers idempotent or de-duplicate by event identity, and retain migration tests for your own provider. This checkpoint replay is separate from the TaskSeq wrapping defect in [streaming replies](/orleans-fsharp/streaming-replies/#authoring-a-producer); it does not justify dropping the