From 2e9f5b6033ac35c24d0d12316c7caf8461bd2310 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 14 Oct 2025 13:34:57 +0000 Subject: [PATCH 01/15] v39.0.0-rc.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d64294f15..1ec26eb01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-js-sdk", - "version": "38.4.0", + "version": "39.0.0-rc.0", "description": "Matrix Client-Server SDK for Javascript", "engines": { "node": ">=22.0.0" From ddd6e77cdefd1703415ea171398a2a6c6e9f4efa Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 14 Oct 2025 15:49:31 +0200 Subject: [PATCH 02/15] Handle redactions for sticky events (MSC4354) (#5037) * Handle redactions. * Add unit tests * Refactor to support unstable insertion orders. * lint * tidy tidy * Fix doc * lint * Assert userId * Catch one occurance of sticky event errors not being caught --- spec/unit/models/room-sticky-events.spec.ts | 160 ++++++++++++++ src/models/room-sticky-events.ts | 224 ++++++++++++++++---- src/models/room.ts | 8 + 3 files changed, 351 insertions(+), 41 deletions(-) diff --git a/spec/unit/models/room-sticky-events.spec.ts b/spec/unit/models/room-sticky-events.spec.ts index a51fe461c..e7ea91b60 100644 --- a/spec/unit/models/room-sticky-events.spec.ts +++ b/spec/unit/models/room-sticky-events.spec.ts @@ -259,4 +259,164 @@ describe("RoomStickyEvents", () => { expect(emitSpy).toHaveBeenCalledWith([], [], [ev]); }); }); + + describe("handleRedaction", () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + afterAll(() => { + jest.useRealTimers(); + }); + it("should not emit if the event does not exist in the map", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + content: {}, + origin_server_ts: Date.now(), + }); + stickyEvents.addStickyEvents([ev]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + stickyEvents.handleRedaction("$123456"); + expect(emitSpy).not.toHaveBeenCalled(); + }); + it("should emit a remove when the event exists in the map without a predecessor", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + stickyEvents.addStickyEvents([ev]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + stickyEvents.handleRedaction(stickyEvent.event_id); + expect(emitSpy).toHaveBeenCalledWith([], [], [ev]); + }); + it("should emit a remove when the event has no sticky key", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + content: {}, + origin_server_ts: Date.now(), + }); + stickyEvents.addStickyEvents([ev]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + stickyEvents.handleRedaction(stickyEvent.event_id); + expect(emitSpy).toHaveBeenCalledWith([], [], [ev]); + }); + it("should emit an update when the event exists in the map with a predecessor", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + jest.advanceTimersByTime(1000); // Advance time so we can insert a newer event. + const newerEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newer-ev", + origin_server_ts: Date.now() + 1000, + }); + stickyEvents.addStickyEvents([ev, newerEv]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + stickyEvents.handleRedaction(newerEv.getId()!); + expect(emitSpy).toHaveBeenCalledWith([], [{ current: ev, previous: newerEv }], []); + }); + it("should emit a remove if the previous event has expired", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + jest.advanceTimersByTime(1000); // Advance time so we can insert a newer event. + const newerEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newer-ev", + origin_server_ts: Date.now() + 1000, + }); + stickyEvents.addStickyEvents([ev, newerEv]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + // Expire the older event. + jest.advanceTimersByTime(stickyEvent.msc4354_sticky.duration_ms); + // Redact the newer event + stickyEvents.handleRedaction(newerEv.getId()!); + expect(emitSpy).toHaveBeenCalledWith([], [], [newerEv]); + }); + it("should recurse the chain of events if the previous event has been redacted", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + jest.advanceTimersByTime(1000); // Advance time so we can insert a newer event. + const middleEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newer-ev", + origin_server_ts: Date.now() + 1000, + }); + jest.advanceTimersByTime(1000); + const newestEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newest-ev", + origin_server_ts: Date.now() + 2000, + }); + stickyEvents.addStickyEvents([ev, middleEv, newestEv]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + // Mark the middle event as redacted. + middleEv.setUnsigned({ + redacted_because: { + event_id: "$foo", + } as any, + }); + // Redact the newer event + stickyEvents.handleRedaction(newestEv.getId()!); + // expect immediate transition from newestEv -> ev and skipping middleEv + expect(emitSpy).toHaveBeenCalledWith([], [{ current: ev, previous: newestEv }], []); + }); + it("should revert to the most recent valid event regardless of insertion order", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + jest.advanceTimersByTime(1000); // Advance time so we can insert a newer event. + const middleEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newer-ev", + origin_server_ts: Date.now() + 1000, + }); + jest.advanceTimersByTime(1000); + const newestEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newest-ev", + origin_server_ts: Date.now() + 2000, + }); + // Invert in reverse order, to make sure we retain the older events. + stickyEvents.addStickyEvents([newestEv, middleEv, ev]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + // Mark the middle event as redacted. + middleEv.setUnsigned({ + redacted_because: { + event_id: "$foo", + } as any, + }); + // Redact the newer event + stickyEvents.handleRedaction(newestEv.getId()!); + expect(emitSpy).toHaveBeenCalledWith([], [{ current: ev, previous: newestEv }], []); + }); + it("should handle redaction when using `handleRedaction` with a `MatrixEvent` parameter", () => { + const emitSpy = jest.fn(); + const ev = new MatrixEvent({ + ...stickyEvent, + origin_server_ts: Date.now(), + }); + jest.advanceTimersByTime(1000); // Advance time so we can insert a newer event. + const newerEv = new MatrixEvent({ + ...stickyEvent, + event_id: "$newer-ev", + origin_server_ts: Date.now() + 1000, + }); + stickyEvents.addStickyEvents([ev, newerEv]); + stickyEvents.on(RoomStickyEventsEvent.Update, emitSpy); + stickyEvents.handleRedaction(newerEv); + expect(emitSpy).toHaveBeenCalledWith([], [{ current: ev, previous: newerEv }], []); + }); + }); }); diff --git a/src/models/room-sticky-events.ts b/src/models/room-sticky-events.ts index 3e9e26a2b..85cee9f41 100644 --- a/src/models/room-sticky-events.ts +++ b/src/models/room-sticky-events.ts @@ -24,17 +24,64 @@ export type RoomStickyEventsMap = { ) => void; }; +type UserId = `@${string}`; + +function assertIsUserId(value: unknown): asserts value is UserId { + if (typeof value !== "string") throw new Error("Not a string"); + if (!value.startsWith("@")) throw new Error("Not a userId"); +} + /** * Tracks sticky events on behalf of one room, and fires an event * whenever a sticky event is updated or replaced. */ export class RoomStickyEventsStore extends TypedEventEmitter { - private readonly stickyEventsMap = new Map>(); // (type -> stickyKey+userId) -> event + /** + * Sticky event map is a nested map of: + * eventType -> `content.sticky_key sender` -> StickyMatrixEvent[] + * + * The events are ordered in latest to earliest expiry, so that the first event + * in the array will always be the "current" one. + */ + private readonly stickyEventsMap = new Map>(); + /** + * These are sticky events that have no sticky key and therefore exist outside the tuple + * system above. They are just held in this Set until they expire. + */ private readonly unkeyedStickyEvents = new Set(); private stickyEventTimer?: ReturnType; private nextStickyEventExpiryTs: number = Number.MAX_SAFE_INTEGER; + /** + * Sort two sticky events by order of expiry. This assumes the sticky events have the same + * `type`, `sticky_key` and `sender`. + * @returns A positive value if event A will expire sooner, or a negative value if event B will expire sooner. + */ + private static sortStickyEvent(eventA: StickyMatrixEvent, eventB: StickyMatrixEvent): number { + // Sticky events with the same key have to use the same expiration duration. + // Hence, comparing via `origin_server_ts` yields the exact same result as comparing their expiration time. + if (eventB.getTs() !== eventA.getTs()) { + return eventB.getTs() - eventA.getTs(); + } + + if ((eventB.getId() ?? "") > (eventA.getId() ?? "")) { + return 1; + } + + // This should fail as we've got corruption in our sticky array. + throw Error("Comparing two sticky events with the same event ID is not allowed."); + } + + /** + * Generate the correct key for an event to be found in the inner maps of `stickyEventsMap`. + * @param stickyKey The sticky key of an event. + * @param sender The sender of the event. + */ + private static stickyMapKey(stickyKey: string, sender: UserId): string { + return `${stickyKey}${sender}`; + } + /** * Get all sticky events that are currently active. * @returns An iterable set of events. @@ -42,7 +89,11 @@ export class RoomStickyEventsStore extends TypedEventEmitter { yield* this.unkeyedStickyEvents; for (const innerMap of this.stickyEventsMap.values()) { - yield* innerMap.values(); + // Inner map contains a map of sender+stickykeys => all sticky events + for (const events of innerMap.values()) { + // The first sticky event is the "current" one in the sticky map. + yield events[0]; + } } } @@ -54,7 +105,8 @@ export class RoomStickyEventsStore extends TypedEventEmitter - // E.g. Where a malicous event type might be "rtc.member.event@foo:bar" the key becomes: - // "rtc.member.event.@foo:bar@bar:baz" - const innerMapKey = `${stickyKey}${sender}`; - prevEvent = this.stickyEventsMap.get(type)?.get(innerMapKey); + const stickyEvent = event as StickyMatrixEvent; - // sticky events are not allowed to expire sooner than their predecessor. - if (prevEvent && event.unstableStickyExpiresAt < prevEvent.unstableStickyExpiresAt) { - logger.info("ignored sticky event with older expiry time", stickyKey); - return { added: false }; - } else if ( - prevEvent && - event.getTs() === prevEvent.getTs() && - (event.getId() ?? "") < (prevEvent.getId() ?? "") - ) { - // This path is unlikely, as it requires both events to have the same TS. - logger.info("ignored sticky event due to 'id tie break rule' on sticky_key", stickyKey); - return { added: false }; - } - if (!this.stickyEventsMap.has(type)) { - this.stickyEventsMap.set(type, new Map()); - } - this.stickyEventsMap.get(type)!.set(innerMapKey, event as StickyMatrixEvent); - } else { - this.unkeyedStickyEvents.add(event as StickyMatrixEvent); + if (stickyKey === undefined) { + this.unkeyedStickyEvents.add(stickyEvent); + // Recalculate the next expiry time. + this.nextStickyEventExpiryTs = Math.min(event.unstableStickyExpiresAt, this.nextStickyEventExpiryTs); + + this.scheduleStickyTimer(); + return { added: true }; } + // Why this is safe: + // A type may contain anything but the *sender* is tightly + // constrained so that a key will always end with a @ + // E.g. Where a malicious event type might be "rtc.member.event@foo:bar" the key becomes: + // "rtc.member.event.@foo:bar@bar:baz" + const innerMapKey = RoomStickyEventsStore.stickyMapKey(stickyKey, sender); + const currentEventSet = [stickyEvent, ...(this.stickyEventsMap.get(type)?.get(innerMapKey) ?? [])].sort( + RoomStickyEventsStore.sortStickyEvent, + ); + if (!this.stickyEventsMap.has(type)) { + this.stickyEventsMap.set(type, new Map()); + } + this.stickyEventsMap.get(type)?.set(innerMapKey, currentEventSet); + // Recalculate the next expiry time. - this.nextStickyEventExpiryTs = Math.min(event.unstableStickyExpiresAt, this.nextStickyEventExpiryTs); + this.nextStickyEventExpiryTs = Math.min(stickyEvent.unstableStickyExpiresAt, this.nextStickyEventExpiryTs); this.scheduleStickyTimer(); - return { added: true, prevEvent }; + return { + added: currentEventSet[0] === stickyEvent, + prevEvent: currentEventSet?.[1], + }; } /** @@ -193,17 +241,24 @@ export class RoomStickyEventsStore extends TypedEventEmitter= event.unstableStickyExpiresAt) { - logger.debug("Expiring sticky event", event.getId()); - removedEvents.push(event); + if (now >= currentEvent.unstableStickyExpiresAt) { + logger.debug("Expiring sticky event", currentEvent.getId()); + removedEvents.push(currentEvent); this.stickyEventsMap.get(eventType)!.delete(innerMapKey); } else { + // Ensure we remove any previous events which have now expired, to avoid unbounded memory consumption. + this.stickyEventsMap + .get(eventType)! + .set(innerMapKey, [ + currentEvent, + ...previousEvents.filter((e) => e.unstableStickyExpiresAt <= now), + ]); // If not removing the event, check to see if it's the next lowest expiry. this.nextStickyEventExpiryTs = Math.min( this.nextStickyEventExpiryTs, - event.unstableStickyExpiresAt, + currentEvent.unstableStickyExpiresAt, ); } } @@ -229,6 +284,93 @@ export class RoomStickyEventsStore extends TypedEventEmitter !e.isRedacted()).sort(RoomStickyEventsStore.sortStickyEvent); + this.stickyEventsMap.get(eventType)?.set(mapKey, newEvents); + if (newEvents.length) { + this.emit( + RoomStickyEventsEvent.Update, + [], + [ + { + // This looks confusing. This emits that the newer event + // has been redacted and the previous event has taken it's place. + previous: currentEvent, + current: newEvents[0], + }, + ], + [], + ); + } else { + // We did not find a previous event, so just expire. + innerMap.delete(mapKey); + if (innerMap.size === 0) { + this.stickyEventsMap.delete(eventType); + } + this.emit(RoomStickyEventsEvent.Update, [], [], [currentEvent]); + } + return; + } + + // We only know the event ID of the redacted event, so we need to + // traverse the map to find our event. + for (const innerMap of this.stickyEventsMap.values()) { + for (const [currentEvent] of innerMap.values()) { + if (currentEvent.getId() !== redactEventId) { + continue; + } + // Found the event. + return this.handleRedaction(currentEvent); + } + } + } + /** * Clear all events and stop the timer from firing. */ diff --git a/src/models/room.ts b/src/models/room.ts index ffd35c2a7..6c657c49f 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -2633,6 +2633,14 @@ export class Room extends ReadReceipt { // if we know about this event, redact its contents now. const redactedEvent = redactId ? this.findEventById(redactId) : undefined; + if (redactId) { + try { + this.stickyEvents.handleRedaction(redactedEvent || redactId); + } catch (ex) { + // Non-critical failure, but we should warn. + logger.error("Failed to handle redaction for sticky event", ex); + } + } if (redactedEvent) { this.applyEventAsRedaction(event, redactedEvent); } From a67fb1fb8d2d50010005f69f70a249e0cc590ec0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 16:13:48 +0100 Subject: [PATCH 03/15] Update all non-major dependencies (#5044) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 262 +++++++++++++++++++++++++++--------------------------- 1 file changed, 130 insertions(+), 132 deletions(-) diff --git a/yarn.lock b/yarn.lock index 591162d9d..a99dce80b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1798,9 +1798,9 @@ "@tybys/wasm-util" "^0.10.0" "@napi-rs/wasm-runtime@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.5.tgz#1fc8952d993d476c9e57999a3b886239119ce476" - integrity sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg== + version "1.0.7" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz#dcfea99a75f06209a235f3d941e3460a51e9b14c" + integrity sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw== dependencies: "@emnapi/core" "^1.5.0" "@emnapi/runtime" "^1.5.0" @@ -1839,102 +1839,102 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@oxc-resolver/binding-android-arm-eabi@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.8.4.tgz#6db60f4996c1f4947731352dbcd7b900d4ac1ec3" - integrity sha512-6BjMji0TcvQfJ4EoSunOSyu/SiyHKficBD0V3Y0NxF0beaNnnZ7GYEi2lHmRNnRCuIPK8IuVqQ6XizYau+CkKw== +"@oxc-resolver/binding-android-arm-eabi@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.9.0.tgz#19b0b17080023f3daa3ba06335d98158a0543aca" + integrity sha512-4AxaG6TkSBQ2FiC5oGZEJQ35DjsSfAbW6/AJauebq4EzIPVOIgDJCF4de+PvX/Xi9BkNw6VtJuMXJdWW97iEAA== -"@oxc-resolver/binding-android-arm64@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.8.4.tgz#51e06144d0c272cdcb691c103265aa956b0d3ea0" - integrity sha512-SxF4X6rzCBS9XNPXKZGoIHIABjfGmtQpEgRBDzpDHx5VTuLAUmwLTHXnVBAZoX5bmnhF79RiMElavzFdJ2cA1A== +"@oxc-resolver/binding-android-arm64@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.9.0.tgz#7bde3f216ab61eded4a5245e1cc301b1f760d2ca" + integrity sha512-oOEg7rUd2M6YlmRkvPcszJ6KO6TaLGN21oDdcs27gbTVYbQQtCWYbZz5jRW5zEBJu6dopoWVx+shJNGtG1qDFw== -"@oxc-resolver/binding-darwin-arm64@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.8.4.tgz#dc83eb372519ab6a9975d89ed4d6200b6fd0d70f" - integrity sha512-8zWeERrzgscAniE6kh1TQ4E7GJyglYsvdoKrHYLBCbHWD+0/soffiwAYxZuckKEQSc2RXMSPjcu+JTCALaY0Dw== +"@oxc-resolver/binding-darwin-arm64@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.9.0.tgz#f3969a4d689f6f51c3b0c57d123f12e4ae396042" + integrity sha512-fM6zE/j6o3C1UIkcZPV7C1f186R7w97guY2N4lyNLlhlgwwhd46acnOezLARvRNU5oyKNev4PvOJhGCCDnFMGg== -"@oxc-resolver/binding-darwin-x64@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.8.4.tgz#0e54eb8198073fde5b765e6ba9a49073153c8783" - integrity sha512-BUwggKz8Hi5uEQ0AeVTSun1+sp4lzNcItn+L7fDsHu5Cx0Zueuo10BtVm+dIwmYVVPL5oGYOeD0fS7MKAazKiw== +"@oxc-resolver/binding-darwin-x64@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.9.0.tgz#f0da13a7256dd3b7e61827e1fde6b8946af7ee92" + integrity sha512-Bg3Orw7gAxbUqQlt64YPWvHDVo3bo2JfI26Qmzv6nKo7mIMTDhQKl7YmywtLNMYbX0IgUM4qu1V90euu+WCDOw== -"@oxc-resolver/binding-freebsd-x64@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.8.4.tgz#d385b26b21993796d7d575bc906d648b32956248" - integrity sha512-fPO5TQhnn8gA6yP4o49lc4Gn8KeDwAp9uYd4PlE3Q00JVqU6cY9WecDhYHrWtiFcyoZ8UVBlIxuhRqT/DP4Z4A== +"@oxc-resolver/binding-freebsd-x64@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.9.0.tgz#f8fec7382a51f8bd8380025d33e1791f6b6e65af" + integrity sha512-eBqVZqTETH6miBfIZXvpzUe98WATz2+Sh+LEFwuRpGsTsKkIpTyb4p1kwylCLkxrd3Yx7wkxQku+L0AMEGBiAA== -"@oxc-resolver/binding-linux-arm-gnueabihf@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.8.4.tgz#84b0661cdd706342fb7638bcaba46c6eecd49e11" - integrity sha512-QuNbdUaVGiP0W0GrXsvCDZjqeL4lZGU7aXlx/S2tCvyTk3wh6skoiLJgqUf/eeqXfUPnzTfntYqyfolzCAyBYA== +"@oxc-resolver/binding-linux-arm-gnueabihf@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.9.0.tgz#90f277428b9bc422e33e2d5b298c2b780bb067d4" + integrity sha512-QgCk/IJnGBvpbc8rYTVgO+A3m3edJjH1zfv8Nvx7fmsxpbXwWH2l4b4tY3/SLMzasxsp7x7k87+HWt095bI5Lg== -"@oxc-resolver/binding-linux-arm-musleabihf@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.8.4.tgz#417f9c7818e55aad195785482a707e83b94d335b" - integrity sha512-p/zLMfza8OsC4BDKxqeZ9Qel+4eA/oiMSyKLRkMrTgt6OWQq1d5nHntjfG35Abcw4ev6Q9lRU3NOW5hj0xlUbw== +"@oxc-resolver/binding-linux-arm-musleabihf@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.9.0.tgz#271e1a2538af19cd2ef70b6b85407a36d87b57fb" + integrity sha512-xkJH0jldIXD2GwoHpCDEF0ucJ7fvRETCL+iFLctM679o7qeDXvtzsO/E401EgFFXcWBJNKXWvH+ZfdYMKyowfA== -"@oxc-resolver/binding-linux-arm64-gnu@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.8.4.tgz#eb3c7b23a10dd20ab307f7a116df3de5172a39ef" - integrity sha512-bvJF9wWxF1+a5YZATlS5JojpOMC7OsnTatA6sXVHoOb7MIigjledYB5ZMAeRrnWWexRMiEX3YSaA46oSfOzmOg== +"@oxc-resolver/binding-linux-arm64-gnu@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.9.0.tgz#fe909cd141ad48911db22af156e3df0e08e0ee30" + integrity sha512-TWq+y2psMzbMtZB9USAq2bSA7NV1TMmh9lhAFbMGQ8Yp2YV4BRC/HilD6qF++efQl6shueGBFOv0LVe9BUXaIA== -"@oxc-resolver/binding-linux-arm64-musl@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.8.4.tgz#6125023a9c24b6c37a8ea166762831323a921ce9" - integrity sha512-gf4nwGBfu+EFwOn5p7/T7VF4jmIdfodwJS9MRkOBHvuAm3LQgCX7O6d3Y80mm0TV7ZMRD/trfW628rHfd5++vQ== +"@oxc-resolver/binding-linux-arm64-musl@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.9.0.tgz#7b02c1d5591cdeb891e393eb05fdb72dccc8e8a1" + integrity sha512-8WwGLfXk7yttc6rD6g53+RnYfX5B8xOot1ffthLn8oCXzVRO4cdChlmeHStxwLD/MWx8z8BGeyfyINNrsh9N2w== -"@oxc-resolver/binding-linux-ppc64-gnu@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.8.4.tgz#8475face8fd588614b82860a22eebf8995bebc26" - integrity sha512-T120R5GIzRd41rYWWKCI6cSYrZjmRQzf3X4xeE1WX396Uabz5DX8KU7RnVHihSK+KDxccCVOFBxcH3ITd+IEpw== +"@oxc-resolver/binding-linux-ppc64-gnu@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.9.0.tgz#fc68a2272e5f8979aadf56fac8a2697a009a694d" + integrity sha512-ZWiAXfan6actlSzayaFS/kYO2zD6k1k0fmLb1opbujXYMKepEnjjVOvKdzCIYR/zKzudqI39dGc+ywqVdsPIpQ== -"@oxc-resolver/binding-linux-riscv64-gnu@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.8.4.tgz#4cb7f523d2e8c1f80df219adda3ca25635c3bbfa" - integrity sha512-PVG7SxBFFjAaQ76p9O/0Xt5mTBlziRwpck+6cRNhy/hbWY/hSt8BFfPqw0EDSfnl40Uuh+NPsHFMnaWWyxbQEg== +"@oxc-resolver/binding-linux-riscv64-gnu@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.9.0.tgz#c54cf2fb9e4e11d90db344c40eb50d8b6141004b" + integrity sha512-p9mCSb+Bym+eycNo9k+81wQ5SAE31E+/rtfbDmF4/7krPotkEjPsEBSc3rqunRwO+FtsUn7H68JLY7hlai49eQ== -"@oxc-resolver/binding-linux-riscv64-musl@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.8.4.tgz#2d1ea0d74450ce257820de82b6a2240619ee902c" - integrity sha512-L0OklUhM2qLGaKvPSyKmwWpoijfc++VJtPyVgz031ShOXyo0WjD0ZGzusyJMsA1a/gdulAmN6CQ/0Sf4LGXEcw== +"@oxc-resolver/binding-linux-riscv64-musl@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.9.0.tgz#b61886c50a1fb4a449c6546326829d0b24fdd675" + integrity sha512-/SePuVxgFhLPciRwsJ8kLVltr+rxh0b6riGFuoPnFXBbHFclKnjNIt3TfqzUj0/vOnslXw3cVGPpmtkm2TgCgg== -"@oxc-resolver/binding-linux-s390x-gnu@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.8.4.tgz#44ec8e96cff6b63ce5c1743607be0c8e5363e326" - integrity sha512-18Ajz5hqO4cRGuoHzLFUsIPod9GIaIRDiXFg2m6CS3NgVdHx7iCZscplYH7KtjdE42M8nGWYMyyq5BOk7QVgPw== +"@oxc-resolver/binding-linux-s390x-gnu@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.9.0.tgz#1f50d2154c6ae5108571d39b991e58fdfbd6d462" + integrity sha512-zLuEjlYIzfnr1Ei2UZYQBbCTa/9deh+BEjO9rh1ai8BfEq4uj6RupTtNpgHfgAsEYdqOBVExw9EU1S6SW3RCAw== -"@oxc-resolver/binding-linux-x64-gnu@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.8.4.tgz#7cebe95af63f781a8b35315635caad0186baa399" - integrity sha512-uHvH4RyYBdQ/lFGV9H+R1ScHg6EBnAhE3mnX+u+mO/btnalvg7j80okuHf8Qw0tLQiP5P1sEBoVeE6zviXY9IA== +"@oxc-resolver/binding-linux-x64-gnu@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.9.0.tgz#88471c8091845338198126dc95ac672715f5d8d2" + integrity sha512-cxdg73WG+aVlPu/k4lEQPRVOhWunYOUglW6OSzclZLJJAXZU0tSZ5ymKaqPRkfTsyNSAafj1cA1XYd+P9UxBgw== -"@oxc-resolver/binding-linux-x64-musl@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.8.4.tgz#e655d381bc22be3ccff538016a6ef008490ad043" - integrity sha512-X5z44qh5DdJfVhcqXAQFTDFUpcxdpf6DT/lHL5CFcdQGIZxatjc7gFUy05IXPI9xwfq39RValjJBvFovUk9XBw== +"@oxc-resolver/binding-linux-x64-musl@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.9.0.tgz#ded9224c29ad902e513d450b95dc7ec7b1e2f680" + integrity sha512-sy5nkVdMvNgqcx9sIY7G6U9TYZUZC4cmMGw/wKhJNuuD2/HFGtbje62ttXSwBAbVbmJ2GgZ4ZUo/S1OMyU+/OA== -"@oxc-resolver/binding-wasm32-wasi@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.8.4.tgz#e03e1930de885684fde2869883b4f554b762f2b5" - integrity sha512-z3906y+cd8RRhBGNwHRrRAFxnKjXsBeL3+rdQjZpBrUyrhhsaV5iKD/ROx64FNJ9GjL/9mfon8A5xx/McYIqHA== +"@oxc-resolver/binding-wasm32-wasi@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.9.0.tgz#0adab7fc397a1889934ee826cf72987785da1ff4" + integrity sha512-dfi/a0Xh6o6nOLbJdaYuy7txncEcwkRHp9DGGZaAP7zxDiepkBZ6ewSJODQrWwhjVmMteXo+XFzEOMjsC7WUtQ== dependencies: "@napi-rs/wasm-runtime" "^1.0.5" -"@oxc-resolver/binding-win32-arm64-msvc@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.8.4.tgz#fb0332c8a541a2c0d9d1efd326bde0b1df5b4404" - integrity sha512-70vXFs74uA3X5iYOkpclbkWlQEF+MI325uAQ+Or2n8HJip2T0SEmuBlyw/sRL2E8zLC4oocb+1g25fmzlDVkmg== +"@oxc-resolver/binding-win32-arm64-msvc@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.9.0.tgz#b74f16ec19e53fd24fbfef1edfe76670d5832e6f" + integrity sha512-b1yKr+eFwyi8pZMjAQwW352rXpaHAmz7FLK03vFIxdyWzWiiL6S3UrfMu+nKQud38963zu4wNNLm7rdXQazgRA== -"@oxc-resolver/binding-win32-ia32-msvc@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.8.4.tgz#fde4b74d5caf06c9bd2c6f9473dd179be22cb3f5" - integrity sha512-SEOUAzTvr+nyMia3nx1dMtD7YUxZwuhQ3QAPnxy21261Lj0yT3JY4EIfwWH54lAWWfMdRSRRMFuGeF/dq7XjEw== +"@oxc-resolver/binding-win32-ia32-msvc@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.9.0.tgz#a51810b4abaabc20ea9737e79a32c0e6eebe9cce" + integrity sha512-DxRT+1HjCpRH8qYCmGHzgsRCYiK+X14PUM9Fb+aD4TljplA7MdDQXqMISTb4zBZ70AuclvlXKTbW+K1GZop3xA== -"@oxc-resolver/binding-win32-x64-msvc@11.8.4": - version "11.8.4" - resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.8.4.tgz#b7478e2124034a8168128d29f3f201b455cf73e5" - integrity sha512-1gARIQsOPOU7LJ7jvMyPmZEVMapL/PymeG3J7naOdLZDrIZKX6CTvgawJmETYKt+8icP8M6KbBinrVkKVqFd+A== +"@oxc-resolver/binding-win32-x64-msvc@11.9.0": + version "11.9.0" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.9.0.tgz#3e8127b5c225cb2d99b991f251768188efbda25f" + integrity sha512-gE3QJvhh0Yj9cSAkkHjRLKPmC7BTJeiaB5YyhVKVUwbnWQgTszV92lZ9pvZtNPEghP7jPbhEs4c6983A0ojQwA== "@peculiar/asn1-schema@^2.3.8": version "2.3.8" @@ -3357,9 +3357,9 @@ emittery@^0.13.1: integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^10.3.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.5.0.tgz#be23498b9e39db476226d8e81e467f39aca26b78" - integrity sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg== + version "10.6.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.6.0.tgz#bf3d6e8f7f8fd22a65d9703475bc0147357a6b0d" + integrity sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A== emoji-regex@^8.0.0: version "8.0.0" @@ -4551,9 +4551,9 @@ is-negative-zero@^2.0.3: integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-network-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.1.0.tgz#d26a760e3770226d11c169052f266a4803d9c997" - integrity sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g== + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.3.0.tgz#2ce62cbca444abd506f8a900f39d20b898d37512" + integrity sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw== is-number-object@^1.0.4: version "1.0.7" @@ -5132,9 +5132,9 @@ jest@^29.0.0: jest-cli "^29.7.0" jiti@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.0.tgz#b831fdc4440c0a4944c34456643c555afe09d36d" - integrity sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ== + version "2.6.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" + integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== jju@~1.4.0: version "1.4.0" @@ -5273,9 +5273,9 @@ kleur@^3.0.3: integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== knip@^5.0.0: - version "5.64.1" - resolved "https://registry.yarnpkg.com/knip/-/knip-5.64.1.tgz#313e5de65e89ba747e8acea999df8be0e46b5d33" - integrity sha512-80XnLsyeXuyxj1F4+NBtQFHxaRH0xWRw8EKwfQ6EkVZZ0bSz/kqqan08k/Qg8ajWsFPhFq+0S2RbLCBGIQtuOg== + version "5.65.0" + resolved "https://registry.yarnpkg.com/knip/-/knip-5.65.0.tgz#487016f8f25f8bf599c8f0b34aff0d74d1bd9f77" + integrity sha512-wMSca3O1JGs/JgEQx7uZUZYMnZvGqhNjL4b2w8LJGxFzEckNWcvyHopsCwkC7M6aeWgIASCT9vCFDXklvvey3g== dependencies: "@nodelib/fs.walk" "^1.2.3" fast-glob "^3.3.3" @@ -5316,14 +5316,14 @@ linkify-it@^5.0.0: uc.micro "^2.0.0" lint-staged@^16.0.0: - version "16.2.3" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.2.3.tgz#790866221d75602510507b5be40b2c7963715960" - integrity sha512-1OnJEESB9zZqsp61XHH2fvpS1es3hRCxMplF/AJUDa8Ho8VrscYDIuxGrj3m8KPXbcWZ8fT9XTMUhEQmOVKpKw== + version "16.2.4" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.2.4.tgz#1f166370e32d9b7eb10583e86d86e1117f7ab489" + integrity sha512-Pkyr/wd90oAyXk98i/2KwfkIhoYQUMtss769FIT9hFM5ogYZwrk+GRE46yKXSg2ZGhcJ1p38Gf5gmI5Ohjg2yg== dependencies: commander "^14.0.1" listr2 "^9.0.4" micromatch "^4.0.8" - nano-spawn "^1.0.3" + nano-spawn "^2.0.0" pidtree "^0.6.0" string-argv "^0.3.2" yaml "^2.8.1" @@ -5562,15 +5562,15 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nano-spawn@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/nano-spawn/-/nano-spawn-1.0.3.tgz#ef8d89a275eebc8657e67b95fc312a6527a05b8d" - integrity sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA== +nano-spawn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/nano-spawn/-/nano-spawn-2.0.0.tgz#f1250434c09ae18870d4f729fc54b406cf85a3e1" + integrity sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw== napi-postinstall@^0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.3.tgz#93d045c6b576803ead126711d3093995198c6eb9" - integrity sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow== + version "0.3.4" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== natural-compare@^1.4.0: version "1.4.0" @@ -5710,31 +5710,29 @@ optionator@^0.9.3: word-wrap "^1.2.5" oxc-resolver@^11.8.3: - version "11.8.4" - resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-11.8.4.tgz#84d1c5352893bf13a3817f8fe7ba6f8eb9b15f8a" - integrity sha512-qpimS3tHHEf+kgESMAme+q+rj7aCzMya00u9YdKOKyX2o7q4lozjPo6d7ZTTi979KHEcVOPWdNTueAKdeNq72w== - dependencies: - napi-postinstall "^0.3.0" + version "11.9.0" + resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-11.9.0.tgz#fbe5d6a67d8090e43c518c74cedce3cfb6a3aa0c" + integrity sha512-u714L0DBBXpD0ERErCQlun2XwinuBfIGo2T8bA7xE8WLQ4uaJudO/VOEQCWslOmcDY2nEkS+UVir5PpyvSG23w== optionalDependencies: - "@oxc-resolver/binding-android-arm-eabi" "11.8.4" - "@oxc-resolver/binding-android-arm64" "11.8.4" - "@oxc-resolver/binding-darwin-arm64" "11.8.4" - "@oxc-resolver/binding-darwin-x64" "11.8.4" - "@oxc-resolver/binding-freebsd-x64" "11.8.4" - "@oxc-resolver/binding-linux-arm-gnueabihf" "11.8.4" - "@oxc-resolver/binding-linux-arm-musleabihf" "11.8.4" - "@oxc-resolver/binding-linux-arm64-gnu" "11.8.4" - "@oxc-resolver/binding-linux-arm64-musl" "11.8.4" - "@oxc-resolver/binding-linux-ppc64-gnu" "11.8.4" - "@oxc-resolver/binding-linux-riscv64-gnu" "11.8.4" - "@oxc-resolver/binding-linux-riscv64-musl" "11.8.4" - "@oxc-resolver/binding-linux-s390x-gnu" "11.8.4" - "@oxc-resolver/binding-linux-x64-gnu" "11.8.4" - "@oxc-resolver/binding-linux-x64-musl" "11.8.4" - "@oxc-resolver/binding-wasm32-wasi" "11.8.4" - "@oxc-resolver/binding-win32-arm64-msvc" "11.8.4" - "@oxc-resolver/binding-win32-ia32-msvc" "11.8.4" - "@oxc-resolver/binding-win32-x64-msvc" "11.8.4" + "@oxc-resolver/binding-android-arm-eabi" "11.9.0" + "@oxc-resolver/binding-android-arm64" "11.9.0" + "@oxc-resolver/binding-darwin-arm64" "11.9.0" + "@oxc-resolver/binding-darwin-x64" "11.9.0" + "@oxc-resolver/binding-freebsd-x64" "11.9.0" + "@oxc-resolver/binding-linux-arm-gnueabihf" "11.9.0" + "@oxc-resolver/binding-linux-arm-musleabihf" "11.9.0" + "@oxc-resolver/binding-linux-arm64-gnu" "11.9.0" + "@oxc-resolver/binding-linux-arm64-musl" "11.9.0" + "@oxc-resolver/binding-linux-ppc64-gnu" "11.9.0" + "@oxc-resolver/binding-linux-riscv64-gnu" "11.9.0" + "@oxc-resolver/binding-linux-riscv64-musl" "11.9.0" + "@oxc-resolver/binding-linux-s390x-gnu" "11.9.0" + "@oxc-resolver/binding-linux-x64-gnu" "11.9.0" + "@oxc-resolver/binding-linux-x64-musl" "11.9.0" + "@oxc-resolver/binding-wasm32-wasi" "11.9.0" + "@oxc-resolver/binding-win32-arm64-msvc" "11.9.0" + "@oxc-resolver/binding-win32-ia32-msvc" "11.9.0" + "@oxc-resolver/binding-win32-x64-msvc" "11.9.0" p-limit@^2.2.0: version "2.3.0" @@ -5765,9 +5763,9 @@ p-locate@^5.0.0: p-limit "^3.0.2" p-retry@7: - version "7.0.0" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-7.0.0.tgz#38dbee20149d94680fe0a022405839d995f95e7b" - integrity sha512-3BgO9rjULJYyr0Y0pcsG7FZ+7JB/hfOODO8kx9ppumiO5jprUF92WK/Y7Q0xppZtq4VhTcPiVq7qWLQfIV5aKQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-7.1.0.tgz#bddc957f94e8483f3c046a4318e1513fd0e784b4" + integrity sha512-xL4PiFRQa/f9L9ZvR4/gUCRNus4N8YX80ku8kv9Jqz+ZokkiZLM0bcvX0gm1F3PDi9SPRsww1BDsTWgE6Y1GLQ== dependencies: is-network-error "^1.1.0" @@ -7161,6 +7159,6 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zod@^4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" - integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== + version "4.1.12" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0" + integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ== From d8b70ef83bcf68f2cc28661949f65a687bf4db1f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:16:55 +0000 Subject: [PATCH 04/15] Update actions/stale digest to 5f858e3 (#5043) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/triage-stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/triage-stale.yml b/.github/workflows/triage-stale.yml index 31da38096..055b841eb 100644 --- a/.github/workflows/triage-stale.yml +++ b/.github/workflows/triage-stale.yml @@ -12,7 +12,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10 with: operations-per-run: 250 days-before-issue-stale: -1 From b2d3ab8bc121dd357a9a9d17a3b1180d9be9e8a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:17:11 +0000 Subject: [PATCH 05/15] Update typescript-eslint monorepo to v8.46.0 (#5046) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 134 +++++++++++++++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 62 deletions(-) diff --git a/yarn.lock b/yarn.lock index a99dce80b..6eb7c972c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2243,38 +2243,38 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^8.0.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz#9f251d4e85ec5089e7cccb09257ce93dbf0d7744" - integrity sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg== + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz#20876354024140aabc8b400bc95735fdcade17d5" + integrity sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.45.0" - "@typescript-eslint/type-utils" "8.45.0" - "@typescript-eslint/utils" "8.45.0" - "@typescript-eslint/visitor-keys" "8.45.0" + "@typescript-eslint/scope-manager" "8.46.1" + "@typescript-eslint/type-utils" "8.46.1" + "@typescript-eslint/utils" "8.46.1" + "@typescript-eslint/visitor-keys" "8.46.1" graphemer "^1.4.0" ignore "^7.0.0" natural-compare "^1.4.0" ts-api-utils "^2.1.0" "@typescript-eslint/parser@^8.0.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.45.0.tgz#571660c98824aefb4a6ec3b3766655d1348520a4" - integrity sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ== + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.1.tgz#81751f46800fc6b01ce1a72760cd17f06e7f395b" + integrity sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA== dependencies: - "@typescript-eslint/scope-manager" "8.45.0" - "@typescript-eslint/types" "8.45.0" - "@typescript-eslint/typescript-estree" "8.45.0" - "@typescript-eslint/visitor-keys" "8.45.0" + "@typescript-eslint/scope-manager" "8.46.1" + "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/typescript-estree" "8.46.1" + "@typescript-eslint/visitor-keys" "8.46.1" debug "^4.3.4" -"@typescript-eslint/project-service@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.45.0.tgz#f83dda1bca31dae2fd6821f9131daf1edebfd46c" - integrity sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg== +"@typescript-eslint/project-service@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.1.tgz#07be0e6f27fa90a17d8e5f6996ee02329c9a8c2e" + integrity sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg== dependencies: - "@typescript-eslint/tsconfig-utils" "^8.45.0" - "@typescript-eslint/types" "^8.45.0" + "@typescript-eslint/tsconfig-utils" "^8.46.1" + "@typescript-eslint/types" "^8.46.1" debug "^4.3.4" "@typescript-eslint/scope-manager@8.21.0": @@ -2285,27 +2285,27 @@ "@typescript-eslint/types" "8.21.0" "@typescript-eslint/visitor-keys" "8.21.0" -"@typescript-eslint/scope-manager@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz#59615ba506a9e3479d1efb0d09d6ab52f2a19142" - integrity sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA== +"@typescript-eslint/scope-manager@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz#590dd2e65e95af646bdaf50adeae9af39e25e8c1" + integrity sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A== dependencies: - "@typescript-eslint/types" "8.45.0" - "@typescript-eslint/visitor-keys" "8.45.0" + "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/visitor-keys" "8.46.1" -"@typescript-eslint/tsconfig-utils@8.45.0", "@typescript-eslint/tsconfig-utils@^8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz#63d38282790a2566c571bad423e7c1cad1f3d64c" - integrity sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w== +"@typescript-eslint/tsconfig-utils@8.46.1", "@typescript-eslint/tsconfig-utils@^8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz#24405888560175c6c209c39df11ac06a2efef9d7" + integrity sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g== -"@typescript-eslint/type-utils@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz#04004bdf2598844faa29fb936fb6b0ee10d6d3f3" - integrity sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A== +"@typescript-eslint/type-utils@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz#14d4307dd6045f6b48a888cde1513d6ec305537f" + integrity sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw== dependencies: - "@typescript-eslint/types" "8.45.0" - "@typescript-eslint/typescript-estree" "8.45.0" - "@typescript-eslint/utils" "8.45.0" + "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/typescript-estree" "8.46.1" + "@typescript-eslint/utils" "8.46.1" debug "^4.3.4" ts-api-utils "^2.1.0" @@ -2314,7 +2314,12 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.21.0.tgz#58f30aec8db8212fd886835dc5969cdf47cb29f5" integrity sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A== -"@typescript-eslint/types@8.45.0", "@typescript-eslint/types@^8.44.0", "@typescript-eslint/types@^8.45.0": +"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.1.tgz#4c5479538ec10b5508b8e982e172911c987446d8" + integrity sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ== + +"@typescript-eslint/types@^8.44.0": version "8.45.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.45.0.tgz#fc01cd2a4690b9713b02f895e82fb43f7d960684" integrity sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA== @@ -2333,15 +2338,15 @@ semver "^7.6.0" ts-api-utils "^2.0.0" -"@typescript-eslint/typescript-estree@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz#3498500f109a89b104d2770497c707e56dfe062d" - integrity sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA== +"@typescript-eslint/typescript-estree@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz#1c146573b942ebe609c156c217ceafdc7a88e6ed" + integrity sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg== dependencies: - "@typescript-eslint/project-service" "8.45.0" - "@typescript-eslint/tsconfig-utils" "8.45.0" - "@typescript-eslint/types" "8.45.0" - "@typescript-eslint/visitor-keys" "8.45.0" + "@typescript-eslint/project-service" "8.46.1" + "@typescript-eslint/tsconfig-utils" "8.46.1" + "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/visitor-keys" "8.46.1" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -2349,15 +2354,15 @@ semver "^7.6.0" ts-api-utils "^2.1.0" -"@typescript-eslint/utils@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.45.0.tgz#6e68e92d99019fdf56018d0e6664c76a70470c95" - integrity sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg== +"@typescript-eslint/utils@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.1.tgz#c572184d9227d66b10a954b90249a20c48b22452" + integrity sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ== dependencies: "@eslint-community/eslint-utils" "^4.7.0" - "@typescript-eslint/scope-manager" "8.45.0" - "@typescript-eslint/types" "8.45.0" - "@typescript-eslint/typescript-estree" "8.45.0" + "@typescript-eslint/scope-manager" "8.46.1" + "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/typescript-estree" "8.46.1" "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": version "8.21.0" @@ -2377,12 +2382,12 @@ "@typescript-eslint/types" "8.21.0" eslint-visitor-keys "^4.2.0" -"@typescript-eslint/visitor-keys@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz#4e3bcc55da64ac61069ebfe62ca240567ac7d784" - integrity sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag== +"@typescript-eslint/visitor-keys@8.46.1": + version "8.46.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz#da35f1d58ec407419d68847cfd358b32746ac315" + integrity sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA== dependencies: - "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/types" "8.46.1" eslint-visitor-keys "^4.2.1" "@ungap/structured-clone@^1.2.0": @@ -6239,16 +6244,21 @@ semver@^7.5.3, semver@^7.5.4: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== -semver@^7.6.0, semver@^7.7.1: - version "7.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== +semver@^7.6.0: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== semver@^7.6.3: version "7.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== +semver@^7.7.1: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" From cd9794471f961c8ddb46c23b84bbdc18e705cd0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:17:41 +0000 Subject: [PATCH 06/15] Update dependency @types/node to v18.19.130 (#5045) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6eb7c972c..6ce8744fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2199,9 +2199,9 @@ undici-types "~5.26.4" "@types/node@18": - version "18.19.128" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.128.tgz#e55ec96fe0b8ae57c374c22238e7844908b2aadc" - integrity sha512-m7wxXGpPpqxp2QDi/rpih5O772APRuBIa/6XiGqLNoM1txkjI8Sz1V4oSXJxQLTz/yP5mgy9z6UXEO6/lP70Gg== + version "18.19.130" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.130.tgz#da4c6324793a79defb7a62cba3947ec5add00d59" + integrity sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg== dependencies: undici-types "~5.26.4" From 2d90ad95f1ee3fefc0fe39d08ca6f7db2b3c1f84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:19:11 +0000 Subject: [PATCH 07/15] Update peter-evans/repository-dispatch action to v4 (#5048) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/notify-downstream.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/notify-downstream.yaml b/.github/workflows/notify-downstream.yaml index 7139b90e6..2e9bbe895 100644 --- a/.github/workflows/notify-downstream.yaml +++ b/.github/workflows/notify-downstream.yaml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Notify matrix-react-sdk repo that a new SDK build is on develop so it can CI against it - uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3 + uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} repository: ${{ matrix.repo }} From 7c1e25e713a82c4ee70ec20be7fefffab93e86c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:28:15 +0100 Subject: [PATCH 08/15] Update actions/setup-node action to v6 (#5047) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release-drafter-workflow.yml | 2 +- .github/workflows/release-gitflow.yml | 2 +- .github/workflows/release-make.yml | 2 +- .github/workflows/release-npm.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/static_analysis.yml | 16 ++++++++-------- .github/workflows/tests.yml | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release-drafter-workflow.yml b/.github/workflows/release-drafter-workflow.yml index 3b6d16aa5..682621123 100644 --- a/.github/workflows/release-drafter-workflow.yml +++ b/.github/workflows/release-drafter-workflow.yml @@ -21,7 +21,7 @@ jobs: ref: staging fetch-depth: 0 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: node-version-file: package.json cache: "yarn" diff --git a/.github/workflows/release-gitflow.yml b/.github/workflows/release-gitflow.yml index de9e806c6..3a6abce0f 100644 --- a/.github/workflows/release-gitflow.yml +++ b/.github/workflows/release-gitflow.yml @@ -33,7 +33,7 @@ jobs: sparse-checkout: | scripts/release - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json diff --git a/.github/workflows/release-make.yml b/.github/workflows/release-make.yml index 6e65fe2ef..8b505ae4c 100644 --- a/.github/workflows/release-make.yml +++ b/.github/workflows/release-make.yml @@ -125,7 +125,7 @@ jobs: git config --global user.email "releases@riot.im" git config --global user.name "RiotRobot" - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 1a9ec554d..9c46fc44d 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -25,7 +25,7 @@ jobs: ref: staging - name: 🔧 Yarn cache - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" registry-url: "https://registry.npmjs.org" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6a4904c3..0a6348ee2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: ref: staging token: ${{ secrets.ELEMENT_BOT_TOKEN }} - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version: "lts/*" @@ -76,7 +76,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - name: 🔧 Yarn cache - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 99543269d..da03e52d9 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -50,7 +50,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -61,7 +61,7 @@ jobs: - name: Build Types run: "yarn build:types" - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "npm" node-version-file: "examples/node/package.json" @@ -85,7 +85,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -102,7 +102,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -127,7 +127,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version-file: package.json @@ -147,7 +147,7 @@ jobs: with: repository: element-hq/element-web - - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version: "lts/*" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c3495cc56..b0c41fc94 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: - name: Setup Node id: setupNode - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: "yarn" node-version: ${{ matrix.node }} From 3ac47e71cdc333466c6dcf6ebf19703f95322aa3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 10:49:42 +0100 Subject: [PATCH 09/15] Update eslint-plugins (#5049) * Update eslint-plugins * Bump matrix-org Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- yarn.lock | 1106 +++++++++++++++++++++++++++----------------------- 2 files changed, 608 insertions(+), 500 deletions(-) diff --git a/package.json b/package.json index d64294f15..b4fcd060d 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-jest": "^28.0.0", "eslint-plugin-jsdoc": "^50.0.0", - "eslint-plugin-matrix-org": "2.1.0", + "eslint-plugin-matrix-org": "^3.0.0", "eslint-plugin-n": "^14.0.0", "eslint-plugin-tsdoc": "^0.4.0", "eslint-plugin-unicorn": "^56.0.0", diff --git a/yarn.lock b/yarn.lock index 6ce8744fe..42299235a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1364,11 +1364,13 @@ dependencies: tslib "^2.4.0" -"@es-joy/jsdoccomment@~0.49.0": - version "0.49.0" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz#e5ec1eda837c802eca67d3b29e577197f14ba1db" - integrity sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q== +"@es-joy/jsdoccomment@~0.50.2": + version "0.50.2" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz#707768f0cb62abe0703d51aa9086986d230a5d5c" + integrity sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA== dependencies: + "@types/estree" "^1.0.6" + "@typescript-eslint/types" "^8.11.0" comment-parser "1.4.1" esquery "^1.6.0" jsdoc-type-pratt-parser "~4.1.0" @@ -1380,14 +1382,7 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/eslint-utils@^4.4.0": - version "4.6.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz#e4c58fdcf0696e7a5f19c30201ed43123ab15abc" - integrity sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw== - dependencies: - eslint-visitor-keys "^3.4.3" - -"@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.9.0": +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.9.0": version "4.9.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== @@ -2121,6 +2116,11 @@ dependencies: "@types/ms" "*" +"@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/events@^3.0.0": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.3.tgz#a8ef894305af28d1fc6d2dfdfc98e899591ea529" @@ -2277,14 +2277,6 @@ "@typescript-eslint/types" "^8.46.1" debug "^4.3.4" -"@typescript-eslint/scope-manager@8.21.0": - version "8.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz#d08d94e2a34b4ccdcc975543c25bb62917437500" - integrity sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA== - dependencies: - "@typescript-eslint/types" "8.21.0" - "@typescript-eslint/visitor-keys" "8.21.0" - "@typescript-eslint/scope-manager@8.46.1": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz#590dd2e65e95af646bdaf50adeae9af39e25e8c1" @@ -2309,12 +2301,7 @@ debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.21.0": - version "8.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.21.0.tgz#58f30aec8db8212fd886835dc5969cdf47cb29f5" - integrity sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A== - -"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.46.1": +"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.11.0", "@typescript-eslint/types@^8.46.1": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.1.tgz#4c5479538ec10b5508b8e982e172911c987446d8" integrity sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ== @@ -2324,20 +2311,6 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.45.0.tgz#fc01cd2a4690b9713b02f895e82fb43f7d960684" integrity sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA== -"@typescript-eslint/typescript-estree@8.21.0": - version "8.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz#5ce71acdbed3b97b959f6168afba5a03c88f69a9" - integrity sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg== - dependencies: - "@typescript-eslint/types" "8.21.0" - "@typescript-eslint/visitor-keys" "8.21.0" - debug "^4.3.4" - fast-glob "^3.3.2" - is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^2.0.0" - "@typescript-eslint/typescript-estree@8.46.1": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz#1c146573b942ebe609c156c217ceafdc7a88e6ed" @@ -2354,7 +2327,7 @@ semver "^7.6.0" ts-api-utils "^2.1.0" -"@typescript-eslint/utils@8.46.1": +"@typescript-eslint/utils@8.46.1", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.1.tgz#c572184d9227d66b10a954b90249a20c48b22452" integrity sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ== @@ -2364,24 +2337,6 @@ "@typescript-eslint/types" "8.46.1" "@typescript-eslint/typescript-estree" "8.46.1" -"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": - version "8.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.21.0.tgz#bc4874fbc30feb3298b926e3b03d94570b3999c5" - integrity sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.21.0" - "@typescript-eslint/types" "8.21.0" - "@typescript-eslint/typescript-estree" "8.21.0" - -"@typescript-eslint/visitor-keys@8.21.0": - version "8.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz#a89744c4cdc83b5c761eb5878befe6c33d1481b2" - integrity sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w== - dependencies: - "@typescript-eslint/types" "8.21.0" - eslint-visitor-keys "^4.2.0" - "@typescript-eslint/visitor-keys@8.46.1": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz#da35f1d58ec407419d68847cfd358b32746ac315" @@ -2522,7 +2477,7 @@ acorn@^8.1.0, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== -acorn@^8.14.0, acorn@^8.15.0: +acorn@^8.15.0: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== @@ -2642,71 +2597,73 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" + call-bound "^1.0.3" + is-array-buffer "^3.0.5" -array-includes@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" - integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== +array-includes@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.9.tgz#1f0ccaa08e90cdbc3eb433210f903ad0f17c3f3a" + integrity sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" define-properties "^1.2.1" - es-abstract "^1.23.2" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - is-string "^1.0.7" + es-abstract "^1.24.0" + es-object-atoms "^1.1.1" + get-intrinsic "^1.3.0" + is-string "^1.1.1" + math-intrinsics "^1.1.0" -array.prototype.findlastindex@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" - integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== +array.prototype.findlastindex@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz#cfa1065c81dcb64e34557c9b81d012f6a421c564" + integrity sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" define-properties "^1.2.1" - es-abstract "^1.23.2" + es-abstract "^1.23.9" es-errors "^1.3.0" - es-object-atoms "^1.0.0" + es-object-atoms "^1.1.1" + es-shim-unscopables "^1.1.0" + +array.prototype.flat@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" es-shim-unscopables "^1.0.2" -array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== +array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" -array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" asn1js@^3.0.1, asn1js@^3.0.5: version "3.0.5" @@ -2717,6 +2674,11 @@ asn1js@^3.0.1, asn1js@^3.0.5: pvutils "^1.1.3" tslib "^2.4.0" +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2915,7 +2877,7 @@ builtin-modules@^3.3.0: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== -call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== @@ -2923,16 +2885,23 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: es-errors "^1.3.0" function-bind "^1.1.2" -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== dependencies: + call-bind-apply-helpers "^1.0.0" es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" get-intrinsic "^1.2.4" - set-function-length "^1.2.1" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" callsites@^3.0.0: version "3.1.0" @@ -3195,30 +3164,30 @@ data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.2" es-errors "^1.3.0" is-data-view "^1.0.1" @@ -3236,7 +3205,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.3.6, debug@^4.4.1: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -3272,7 +3241,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -3332,7 +3301,7 @@ domexception@^4.0.0: dependencies: webidl-conversions "^7.0.0" -dunder-proto@^1.0.1: +dunder-proto@^1.0.0, dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== @@ -3393,98 +3362,83 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== +es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" + integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" + call-bind "^1.0.8" + call-bound "^1.0.4" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" + es-object-atoms "^1.1.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.3.0" + get-proto "^1.0.1" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" + has-proto "^1.2.0" + has-symbols "^1.1.0" hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" is-callable "^1.2.7" - is-data-view "^1.0.1" + is-data-view "^1.0.2" is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" + is-regex "^1.2.1" + is-set "^2.0.3" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.1" + math-intrinsics "^1.1.0" + object-inspect "^1.13.4" object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.4" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.19" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-define-property@^1.0.1: +es-define-property@^1.0.0, es-define-property@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== -es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-object-atoms@^1.1.1: +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - es-set-tostringtag@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" @@ -3495,21 +3449,21 @@ es-set-tostringtag@^2.1.0: has-tostringtag "^1.0.2" hasown "^2.0.2" -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== +es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" escalade@^3.1.1: version "3.1.2" @@ -3587,10 +3541,10 @@ eslint-import-resolver-typescript@^4.0.0: tinyglobby "^0.2.14" unrs-resolver "^1.7.11" -eslint-module-utils@^2.12.0: - version "2.12.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" - integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== +eslint-module-utils@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz#f76d3220bfb83c057651359295ab5854eaad75ff" + integrity sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw== dependencies: debug "^3.2.7" @@ -3603,57 +3557,57 @@ eslint-plugin-es@^4.1.0: regexpp "^3.0.0" eslint-plugin-import@^2.26.0: - version "2.31.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" - integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== + version "2.32.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz#602b55faa6e4caeaa5e970c198b5c00a37708980" + integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA== dependencies: "@rtsao/scc" "^1.1.0" - array-includes "^3.1.8" - array.prototype.findlastindex "^1.2.5" - array.prototype.flat "^1.3.2" - array.prototype.flatmap "^1.3.2" + array-includes "^3.1.9" + array.prototype.findlastindex "^1.2.6" + array.prototype.flat "^1.3.3" + array.prototype.flatmap "^1.3.3" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.12.0" + eslint-module-utils "^2.12.1" hasown "^2.0.2" - is-core-module "^2.15.1" + is-core-module "^2.16.1" is-glob "^4.0.3" minimatch "^3.1.2" object.fromentries "^2.0.8" object.groupby "^1.0.3" - object.values "^1.2.0" + object.values "^1.2.1" semver "^6.3.1" - string.prototype.trimend "^1.0.8" + string.prototype.trimend "^1.0.9" tsconfig-paths "^3.15.0" eslint-plugin-jest@^28.0.0: - version "28.11.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.11.0.tgz#2641ecb4411941bbddb3d7cf8a8ff1163fbb510e" - integrity sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig== + version "28.14.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.14.0.tgz#02da77dc27d7b4c5480df3552ea26de056857b36" + integrity sha512-P9s/qXSMTpRTerE2FQ0qJet2gKbcGyFTPAJipoKxmWqR6uuFqIqk8FuEfg5yBieOezVrEfAMZrEwJ6yEp+1MFQ== dependencies: "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" eslint-plugin-jsdoc@^50.0.0: - version "50.6.11" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.11.tgz#36733620dafe03e8666df4cff449c7e9a8e1b1da" - integrity sha512-k4+MnBCGR8cuIB5MZ++FGd4gbXxjob2rX1Nq0q3nWFF4xSGZENTgTLZSjb+u9B8SAnP6lpGV2FJrBjllV3pVSg== + version "50.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.8.0.tgz#a8d192ccca26df368a2fbaff17c9dddefacd773f" + integrity sha512-UyGb5755LMFWPrZTEqqvTJ3urLz1iqj+bYOHFNag+sw3NvaMWP9K2z+uIn37XfNALmQLQyrBlJ5mkiVPL7ADEg== dependencies: - "@es-joy/jsdoccomment" "~0.49.0" + "@es-joy/jsdoccomment" "~0.50.2" are-docs-informative "^0.0.2" comment-parser "1.4.1" - debug "^4.3.6" + debug "^4.4.1" escape-string-regexp "^4.0.0" - espree "^10.1.0" + espree "^10.3.0" esquery "^1.6.0" parse-imports-exports "^0.2.4" - semver "^7.6.3" + semver "^7.7.2" spdx-expression-parse "^4.0.0" -eslint-plugin-matrix-org@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-2.1.0.tgz#9053726119f107154f5210665c2f84219425c190" - integrity sha512-YjVQ0qunzVV34tpUchLWhOrOalGfRLm0tclS4dPYnXS8Ui+p12o/YtRHt+26Mg5tJ0QH76HsGC0LJKLVLNoqfg== +eslint-plugin-matrix-org@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-3.0.0.tgz#0e5eaa556b6780dcd616b1381baec252df78b56d" + integrity sha512-xOPMeyLxOgoB2SsPhJmIc+drorZmXozSBo3X9whk/62DvbVpJcnththOCGx8ljYScADLb+baNOeN+wKZqwkldw== eslint-plugin-n@^14.0.0: version "14.0.0" @@ -3748,7 +3702,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: +eslint-visitor-keys@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== @@ -3797,16 +3751,7 @@ eslint@8.57.1: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^10.1.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" - integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== - dependencies: - acorn "^8.14.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.2.0" - -espree@^10.4.0: +espree@^10.3.0, espree@^10.4.0: version "10.4.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== @@ -4045,12 +3990,12 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== dependencies: - is-callable "^1.1.3" + is-callable "^1.2.7" foreground-child@^3.1.0: version "3.2.1" @@ -4098,21 +4043,28 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -4128,18 +4080,7 @@ get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.0, get-east-asian-width@^ resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz#9bc4caa131702b4b61729cb7e42735bc550c9ee6" integrity sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-intrinsic@^1.2.6: +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== @@ -4173,14 +4114,14 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== dependencies: - call-bind "^1.0.5" + call-bound "^1.0.3" es-errors "^1.3.0" - get-intrinsic "^1.2.4" + get-intrinsic "^1.2.6" get-tsconfig@^4.10.1: version "4.10.1" @@ -4249,7 +4190,7 @@ globals@^15.9.0: resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== -globalthis@^1.0.3: +globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -4257,14 +4198,7 @@ globalthis@^1.0.3: define-properties "^1.2.1" gopd "^1.0.1" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -gopd@^1.2.0: +gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== @@ -4279,10 +4213,10 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== has-flag@^3.0.0: version "3.0.0" @@ -4301,29 +4235,26 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-symbols@^1.1.0: +has-symbols@^1.0.3, has-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: +has-tostringtag@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: +hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== @@ -4430,34 +4361,46 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== dependencies: es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" + hasown "^2.0.2" + side-channel "^1.1.0" -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== +is-async-function@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== dependencies: - has-bigints "^1.0.1" + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" @@ -4466,13 +4409,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-builtin-module@^3.2.1: version "3.2.1" @@ -4488,44 +4431,54 @@ is-bun-module@^2.0.0: dependencies: semver "^7.7.1" -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.16.0: +is-core-module@^2.13.0, is-core-module@^2.16.0, is-core-module@^2.16.1: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: hasown "^2.0.2" -is-core-module@^2.15.1, is-core-module@^2.3.0: +is-core-module@^2.3.0: version "2.15.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: hasown "^2.0.2" -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" is-typed-array "^1.1.13" -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -4543,6 +4496,17 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.10: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -4550,6 +4514,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + is-negative-zero@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" @@ -4560,12 +4529,13 @@ is-network-error@^1.1.0: resolved "https://registry.yarnpkg.com/is-network-error/-/is-network-error-1.3.0.tgz#2ce62cbca444abd506f8a900f39d20b898d37512" integrity sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw== -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-number@^7.0.0: version "7.0.0" @@ -4582,58 +4552,81 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== +is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" integrity sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw== -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: - has-symbols "^1.0.2" + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - which-typed-array "^1.1.14" + which-typed-array "^1.1.16" -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" isarray@^2.0.5: version "2.0.5" @@ -5626,24 +5619,26 @@ nwsapi@^2.2.2: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== +object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - call-bind "^1.0.5" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - has-symbols "^1.0.3" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" object-keys "^1.1.1" object.fromentries@^2.0.8: @@ -5665,12 +5660,13 @@ object.groupby@^1.0.3: define-properties "^1.2.1" es-abstract "^1.23.2" -object.values@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== +object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -5714,6 +5710,15 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + oxc-resolver@^11.8.3: version "11.9.0" resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-11.9.0.tgz#fbe5d6a67d8090e43c518c74cedce3cfb6a3aa0c" @@ -5901,9 +5906,9 @@ pluralize@^8.0.0: integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== prelude-ls@^1.2.1: version "1.2.1" @@ -6020,6 +6025,20 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" + regenerate-unicode-properties@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" @@ -6042,14 +6061,16 @@ regexp-tree@^0.1.27: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== -regexp.prototype.flags@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" - integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== +regexp.prototype.flags@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" define-properties "^1.2.1" es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" set-function-name "^2.0.2" regexparam@^3.0.0: @@ -6135,7 +6156,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.10.0, resolve@^1.22.10: +resolve@^1.10.0, resolve@^1.22.10, resolve@^1.22.4: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -6144,7 +6165,7 @@ resolve@^1.10.0, resolve@^1.22.10: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.4, resolve@~1.22.2: +resolve@^1.10.1, resolve@^1.20.0, resolve@~1.22.2: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -6193,24 +6214,33 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" isarray "^2.0.5" -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== dependencies: - call-bind "^1.0.6" es-errors "^1.3.0" - is-regex "^1.1.4" + isarray "^2.0.5" + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" @@ -6244,7 +6274,7 @@ semver@^7.5.3, semver@^7.5.4: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== -semver@^7.6.0: +semver@^7.6.0, semver@^7.7.2: version "7.7.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== @@ -6259,7 +6289,7 @@ semver@^7.7.1: resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== -set-function-length@^1.2.1: +set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -6281,6 +6311,15 @@ set-function-name@^2.0.2: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6293,15 +6332,45 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: - call-bind "^1.0.7" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -6384,9 +6453,9 @@ spdx-expression-parse@^4.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.21" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz#6d6e980c9df2b6fc905343a3b2d702a6239536c3" - integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg== + version "3.0.22" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" + integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== sprintf-js@~1.0.2: version "1.0.3" @@ -6405,6 +6474,14 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== + dependencies: + es-errors "^1.3.0" + internal-slot "^1.1.0" + string-argv@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" @@ -6462,22 +6539,26 @@ string-width@^8.0.0: get-east-asian-width "^1.3.0" strip-ansi "^7.1.0" -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" define-properties "^1.2.1" - es-abstract "^1.23.0" + es-abstract "^1.23.5" es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -6649,11 +6730,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -ts-api-utils@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" - integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== - ts-api-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" @@ -6730,49 +6806,50 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-typed-array "^1.1.13" + is-typed-array "^1.1.14" -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-proto "^1.0.3" is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" typedoc-plugin-coverage@^4.0.0: version "4.0.1" @@ -6810,15 +6887,15 @@ uc.micro@^2.0.0, uc.micro@^2.1.0: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" undici-types@~5.26.4: version "5.26.5" @@ -7022,26 +7099,57 @@ whatwg-url@^6.5.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" -which-typed-array@^1.1.14, which-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.16, which-typed-array@^1.1.19: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" has-tostringtag "^1.0.2" which@^2.0.1: From 502a513b5b3f1f388dac5c66d1a6ce58c4e9a1c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 11:28:30 +0100 Subject: [PATCH 10/15] Update eslint-plugins (#5050) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 4 +-- yarn.lock | 98 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index b4fcd060d..14c35cb1e 100644 --- a/package.json +++ b/package.json @@ -97,8 +97,8 @@ "eslint-config-prettier": "^10.0.0", "eslint-import-resolver-typescript": "^4.0.0", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^28.0.0", - "eslint-plugin-jsdoc": "^50.0.0", + "eslint-plugin-jest": "^29.0.0", + "eslint-plugin-jsdoc": "^61.0.0", "eslint-plugin-matrix-org": "^3.0.0", "eslint-plugin-n": "^14.0.0", "eslint-plugin-tsdoc": "^0.4.0", diff --git a/yarn.lock b/yarn.lock index 42299235a..afbfa67bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1364,16 +1364,16 @@ dependencies: tslib "^2.4.0" -"@es-joy/jsdoccomment@~0.50.2": - version "0.50.2" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.50.2.tgz#707768f0cb62abe0703d51aa9086986d230a5d5c" - integrity sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA== +"@es-joy/jsdoccomment@~0.76.0": + version "0.76.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz#7785b915035f6010a0f59535202a1ff916faaa72" + integrity sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w== dependencies: - "@types/estree" "^1.0.6" - "@typescript-eslint/types" "^8.11.0" + "@types/estree" "^1.0.8" + "@typescript-eslint/types" "^8.46.0" comment-parser "1.4.1" esquery "^1.6.0" - jsdoc-type-pratt-parser "~4.1.0" + jsdoc-type-pratt-parser "~6.10.0" "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -2013,6 +2013,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sindresorhus/base62@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/base62/-/base62-0.1.0.tgz#2ef36425f0210998adf504e495f6c1e85c7d2718" + integrity sha512-BNjiImatCV+CUdvzSbFWzZIZqOddg6qn0Ag6/8Ty5G09oOtvxidZ5tkPQW2XHpzGVkB3eHfdYGwrWNy2nUFOwQ== + "@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" @@ -2116,7 +2121,7 @@ dependencies: "@types/ms" "*" -"@types/estree@^1.0.6": +"@types/estree@^1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== @@ -2301,7 +2306,7 @@ debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.11.0", "@typescript-eslint/types@^8.46.1": +"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.46.0", "@typescript-eslint/types@^8.46.1": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.1.tgz#4c5479538ec10b5508b8e982e172911c987446d8" integrity sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ== @@ -2327,7 +2332,7 @@ semver "^7.6.0" ts-api-utils "^2.1.0" -"@typescript-eslint/utils@8.46.1", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": +"@typescript-eslint/utils@8.46.1", "@typescript-eslint/utils@^8.0.0": version "8.46.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.1.tgz#c572184d9227d66b10a954b90249a20c48b22452" integrity sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ== @@ -3205,7 +3210,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1, debug@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -3581,28 +3586,31 @@ eslint-plugin-import@^2.26.0: string.prototype.trimend "^1.0.9" tsconfig-paths "^3.15.0" -eslint-plugin-jest@^28.0.0: - version "28.14.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.14.0.tgz#02da77dc27d7b4c5480df3552ea26de056857b36" - integrity sha512-P9s/qXSMTpRTerE2FQ0qJet2gKbcGyFTPAJipoKxmWqR6uuFqIqk8FuEfg5yBieOezVrEfAMZrEwJ6yEp+1MFQ== +eslint-plugin-jest@^29.0.0: + version "29.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz#0f72a81349409d20742208260c9a6cb9efed4df5" + integrity sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw== dependencies: - "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/utils" "^8.0.0" -eslint-plugin-jsdoc@^50.0.0: - version "50.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.8.0.tgz#a8d192ccca26df368a2fbaff17c9dddefacd773f" - integrity sha512-UyGb5755LMFWPrZTEqqvTJ3urLz1iqj+bYOHFNag+sw3NvaMWP9K2z+uIn37XfNALmQLQyrBlJ5mkiVPL7ADEg== +eslint-plugin-jsdoc@^61.0.0: + version "61.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.1.4.tgz#477002a98a4b79269bee1dfde046dac58f8cdee6" + integrity sha512-DmpKw8kHgNQlMS8m+XYtlGcsw4IzrHtupEObPZAww0OrXb7IekbKR7vjYu8jv5aOiFRhGdnIfEZRuoAf4ELe5w== dependencies: - "@es-joy/jsdoccomment" "~0.50.2" + "@es-joy/jsdoccomment" "~0.76.0" are-docs-informative "^0.0.2" comment-parser "1.4.1" - debug "^4.4.1" + debug "^4.4.3" escape-string-regexp "^4.0.0" - espree "^10.3.0" + espree "^10.4.0" esquery "^1.6.0" + html-entities "^2.6.0" + object-deep-merge "^1.0.5" parse-imports-exports "^0.2.4" - semver "^7.7.2" + semver "^7.7.3" spdx-expression-parse "^4.0.0" + to-valid-identifier "^0.1.1" eslint-plugin-matrix-org@^3.0.0: version "3.0.0" @@ -3751,7 +3759,7 @@ eslint@8.57.1: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^10.3.0, espree@^10.4.0: +espree@^10.4.0: version "10.4.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== @@ -4273,6 +4281,11 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" +html-entities@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.6.0.tgz#7c64f1ea3b36818ccae3d3fb48b6974208e984f8" + integrity sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -5159,10 +5172,10 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsdoc-type-pratt-parser@~4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz#ff6b4a3f339c34a6c188cbf50a16087858d22113" - integrity sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg== +jsdoc-type-pratt-parser@~6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz#0846ab682d937eb7272b0e42f49d7f22039059a2" + integrity sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ== jsdom@^20.0.0: version "20.0.3" @@ -5619,6 +5632,13 @@ nwsapi@^2.2.2: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== +object-deep-merge@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/object-deep-merge/-/object-deep-merge-1.0.5.tgz#a5aed81ba02563f6632ea3496451f2b987619538" + integrity sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg== + dependencies: + type-fest "4.2.0" + object-inspect@^1.13.3, object-inspect@^1.13.4: version "1.13.4" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" @@ -6129,6 +6149,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +reserved-identifiers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/reserved-identifiers/-/reserved-identifiers-1.0.0.tgz#a4878ea2b5130ec2bf5aba40074edcb9704d2623" + integrity sha512-h0bP2Katmvf3hv4Z3WtDl4+6xt/OglQ2Xa6TnhZ/Rm9/7IH1crXQqMwD4J2ngKBonVv+fB55zfGgNDAmsevLVQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -6274,7 +6299,7 @@ semver@^7.5.3, semver@^7.5.4: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== -semver@^7.6.0, semver@^7.7.2: +semver@^7.6.0, semver@^7.7.3: version "7.7.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== @@ -6701,6 +6726,14 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-valid-identifier@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/to-valid-identifier/-/to-valid-identifier-0.1.1.tgz#bfd09b8c63ab0c0235e23c8243f7630f45b3e7a9" + integrity sha512-/m+BsP+oLrdYptSVuWdRanXBD0N1qiyx2GtAunpPz+TRPENw7IpEndqyPTwxe67wLiu16ZinauXESdOL1eDYBQ== + dependencies: + "@sindresorhus/base62" "^0.1.0" + reserved-identifiers "^1.0.0" + tough-cookie@^4.1.2: version "4.1.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" @@ -6786,6 +6819,11 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.2.0.tgz#e259430307710e77721ecf6f545840acad72195f" + integrity sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" From 2731e20893bb6c26e8959ee10316ffa9d5a8f078 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Mon, 20 Oct 2025 10:59:29 -0400 Subject: [PATCH 11/15] MSC4140: support filters on delayed event lookup (#5038) * MSC4140: support filters on delayed event lookup Support looking up scheduled/finalised delayed events, and looking up a single delayed event. * Add test coverage for delayed event lookup filters * Prettier * Use it.each for test loop * Support multiple delayIds * Support single or multiple delayIds As it may be more common to look up a single delayed event than to look up many of them, support passing a single delayID in the lookup function instead of needing to pass a single-element array. --- spec/unit/matrix-client.spec.ts | 31 +++++++++++++++++++++---------- src/@types/requests.ts | 21 ++++++++++++++++----- src/client.ts | 14 +++++++++++--- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index 90199bde3..026142f8f 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -1053,17 +1053,28 @@ describe("MatrixClient", function () { ); }); - it("can look up delayed events", async () => { - httpLookups = [ - { - method: "GET", - prefix: unstableMSC4140Prefix, - path: "/delayed_events", - data: [], - }, - ]; + describe("lookups", () => { + const statuses = [undefined, "scheduled" as const, "finalised" as const]; + const delayIds = [undefined, "dxyz", ["d123"], ["d456", "d789"]]; + const inputs = statuses.flatMap((status) => + delayIds.map((delayId) => [status, delayId] as [(typeof statuses)[0], (typeof delayIds)[0]]), + ); + it.each(inputs)("can look up delayed events (status = %s, delayId = %s)", async (status, delayId) => { + httpLookups = [ + { + method: "GET", + prefix: unstableMSC4140Prefix, + path: "/delayed_events", + expectQueryParams: { + status, + delay_id: delayId, + }, + data: [], + }, + ]; - await client._unstable_getDelayedEvents(); + await client._unstable_getDelayedEvents(status, delayId); + }); }); it("can update delayed events", async () => { diff --git a/src/@types/requests.ts b/src/@types/requests.ts index 713a6b7f2..4797d2acb 100644 --- a/src/@types/requests.ts +++ b/src/@types/requests.ts @@ -20,6 +20,7 @@ import { type IEventWithRoomId, type SearchKey } from "./search.ts"; import { type IRoomEventFilter } from "../filter.ts"; import { type Direction } from "../models/event-timeline.ts"; import { type PushRuleAction } from "./PushRules.ts"; +import { type MatrixError } from "../matrix.ts"; import { type IRoomEvent } from "../sync-accumulator.ts"; import { type EventType, type RelationType, type RoomType } from "./event.ts"; @@ -136,12 +137,22 @@ type DelayedPartialStateEvent = DelayedPartialTimelineEvent & { type DelayedPartialEvent = DelayedPartialTimelineEvent | DelayedPartialStateEvent; +export type DelayedEventInfoItem = DelayedPartialEvent & + SendDelayedEventResponse & + SendDelayedEventRequestOpts & { + running_since: number; + }; + export type DelayedEventInfo = { - delayed_events: (DelayedPartialEvent & - SendDelayedEventResponse & - SendDelayedEventRequestOpts & { - running_since: number; - })[]; + scheduled?: DelayedEventInfoItem[]; + finalised?: { + delayed_event: DelayedEventInfoItem; + outcome: "send" | "cancel"; + reason: "error" | "action" | "delay"; + error?: MatrixError["data"]; + event_id?: string; + origin_server_ts?: number; + }[]; next_batch?: string; }; diff --git a/src/client.ts b/src/client.ts index bd1f83626..106380699 100644 --- a/src/client.ts +++ b/src/client.ts @@ -3537,13 +3537,17 @@ export class MatrixClient extends TypedEventEmitter { + public async _unstable_getDelayedEvents( + status?: "scheduled" | "finalised", + delayId?: string | string[], + fromToken?: string, + ): Promise { if (!(await this.doesServerSupportUnstableFeature(UNSTABLE_MSC4140_DELAYED_EVENTS))) { throw new UnsupportedDelayedEventsEndpointError( "Server does not support the delayed events API", @@ -3551,7 +3555,11 @@ export class MatrixClient extends TypedEventEmitter Date: Tue, 21 Oct 2025 11:18:29 +0000 Subject: [PATCH 12/15] v39.0.0 --- CHANGELOG.md | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d9da58c2..f69624798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +Changes in [39.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v39.0.0) (2025-10-21) +================================================================================================== +## 🚨 BREAKING CHANGES + +* [MatrixRTC] Multi SFU support + m.rtc.member event type support ([#5022](https://github.com/matrix-org/matrix-js-sdk/pull/5022)). Contributed by @toger5. + +## ✨ Features + +* [MatrixRTC] Multi SFU support + m.rtc.member event type support ([#5022](https://github.com/matrix-org/matrix-js-sdk/pull/5022)). Contributed by @toger5. +* Implement Sticky Events MSC4354 ([#5028](https://github.com/matrix-org/matrix-js-sdk/pull/5028)). Contributed by @Half-Shot. +* feat(client): allow disabling VoIP support ([#5021](https://github.com/matrix-org/matrix-js-sdk/pull/5021)). Contributed by @pkuzco. + +## 🐛 Bug Fixes + +* Only use the first 3 viaServers specified ([#5034](https://github.com/matrix-org/matrix-js-sdk/pull/5034)). Contributed by @t3chguy. +* Fetch the user's device info before processing a verification request ([#5030](https://github.com/matrix-org/matrix-js-sdk/pull/5030)). Contributed by @andybalaam. + + Changes in [38.4.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v38.4.0) (2025-10-07) ================================================================================================== ## ✨ Features diff --git a/package.json b/package.json index 1ec26eb01..24907c7d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-js-sdk", - "version": "39.0.0-rc.0", + "version": "39.0.0", "description": "Matrix Client-Server SDK for Javascript", "engines": { "node": ">=22.0.0" From 977d0322dafa55b4f69295117e29d3b415515613 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:02:14 +0200 Subject: [PATCH 13/15] Add parseCallNotificationContent (#5015) * add parseCallNotificationContent Signed-off-by: Timo K * add tests Signed-off-by: Timo K * remove decline reason and better m.mentions check Signed-off-by: Timo K * cap ring duration to EX value (90s) Signed-off-by: Timo K --------- Signed-off-by: Timo K --- spec/unit/matrixrtc/types.spec.ts | 135 ++++++++++++++++++++++++++++++ src/matrixrtc/types.ts | 42 +++++++++- 2 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 spec/unit/matrixrtc/types.spec.ts diff --git a/spec/unit/matrixrtc/types.spec.ts b/spec/unit/matrixrtc/types.spec.ts new file mode 100644 index 000000000..7e45acb67 --- /dev/null +++ b/spec/unit/matrixrtc/types.spec.ts @@ -0,0 +1,135 @@ +/* +Copyright 2025 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { type CallMembership } from "../../../src/matrixrtc"; +import { isMyMembership, parseCallNotificationContent } from "../../../src/matrixrtc/types"; + +describe("types", () => { + describe("isMyMembership", () => { + it("returns false if userId is different", () => { + expect( + isMyMembership( + { sender: "@alice:example.org", deviceId: "DEVICE" } as CallMembership, + "@bob:example.org", + "DEVICE", + ), + ).toBe(false); + }); + it("returns true if userId and device is the same", () => { + expect( + isMyMembership( + { sender: "@alice:example.org", deviceId: "DEVICE" } as CallMembership, + "@alice:example.org", + "DEVICE", + ), + ).toBe(true); + }); + }); +}); + +describe("IRTCNotificationContent", () => { + const validBase = Object.freeze({ + "m.mentions": { user_ids: [], room: true }, + "notification_type": "notification", + "sender_ts": 123, + "lifetime": 1000, + }); + + it("parses valid content", () => { + const res = parseCallNotificationContent({ ...validBase }); + expect(res).toMatchObject(validBase); + }); + + it("caps lifetime to 90000ms", () => { + const res = parseCallNotificationContent({ ...validBase, lifetime: 130000 }); + expect(res.lifetime).toBe(90000); + }); + + it("throws on malformed m.mentions", () => { + expect(() => + parseCallNotificationContent({ + ...validBase, + "m.mentions": "not an object", + } as any), + ).toThrow("malformed m.mentions"); + }); + + it("throws on missing or invalid notification_type", () => { + expect(() => + parseCallNotificationContent({ + ...validBase, + notification_type: undefined, + } as any), + ).toThrow("Missing or invalid notification_type"); + + expect(() => + parseCallNotificationContent({ + ...validBase, + notification_type: 123 as any, + } as any), + ).toThrow("Missing or invalid notification_type"); + }); + + it("throws on missing or invalid sender_ts", () => { + expect(() => + parseCallNotificationContent({ + ...validBase, + sender_ts: undefined, + } as any), + ).toThrow("Missing or invalid sender_ts"); + + expect(() => + parseCallNotificationContent({ + ...validBase, + sender_ts: "123" as any, + } as any), + ).toThrow("Missing or invalid sender_ts"); + }); + + it("throws on missing or invalid lifetime", () => { + expect(() => + parseCallNotificationContent({ + ...validBase, + lifetime: undefined, + } as any), + ).toThrow("Missing or invalid lifetime"); + + expect(() => + parseCallNotificationContent({ + ...validBase, + lifetime: "1000" as any, + } as any), + ).toThrow("Missing or invalid lifetime"); + }); + + it("accepts valid relation (m.reference)", () => { + // Note: parseCallNotificationContent currently checks `relation.rel_type` rather than `m.relates_to`. + const res = parseCallNotificationContent({ + ...validBase, + relation: { rel_type: "m.reference", event_id: "$ev" }, + } as any); + expect(res).toBeTruthy(); + }); + + it("throws on invalid relation rel_type", () => { + expect(() => + parseCallNotificationContent({ + ...validBase, + relation: { rel_type: "m.annotation", event_id: "$ev" }, + } as any), + ).toThrow("Invalid relation"); + }); +}); diff --git a/src/matrixrtc/types.ts b/src/matrixrtc/types.ts index 08c32a206..fe4b47b10 100644 --- a/src/matrixrtc/types.ts +++ b/src/matrixrtc/types.ts @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import type { IMentions } from "../matrix.ts"; +import type { IContent, IMentions } from "../matrix.ts"; import type { RelationEvent } from "../types.ts"; import type { CallMembership } from "./CallMembership.ts"; @@ -102,9 +102,45 @@ export type RTCNotificationType = "ring" | "notification"; * May be any string, although `"audio"` and `"video"` are commonly accepted values. */ export type RTCCallIntent = "audio" | "video" | string; + +/** + * This will check if the content has all the expected fields to be a valid IRTCNotificationContent. + * It will also cap the lifetime to 90000ms (1.5 min) if a higher value is provided. + * @param content + * @throws if the content is invalid + * @returns a parsed IRTCNotificationContent + */ +export function parseCallNotificationContent(content: IContent): IRTCNotificationContent { + if (content["m.mentions"] && typeof content["m.mentions"] !== "object") { + throw new Error("malformed m.mentions"); + } + if (typeof content["notification_type"] !== "string") { + throw new Error("Missing or invalid notification_type"); + } + if (typeof content["sender_ts"] !== "number") { + throw new Error("Missing or invalid sender_ts"); + } + if (typeof content["lifetime"] !== "number") { + throw new Error("Missing or invalid lifetime"); + } + + if (content["relation"] && content["relation"]["rel_type"] !== "m.reference") { + throw new Error("Invalid relation"); + } + if (content["m.call.intent"] && typeof content["m.call.intent"] !== "string") { + throw new Error("Invalid m.call.intent"); + } + + const cappedLifetime = content["lifetime"] >= 90000 ? 90000 : content["lifetime"]; + return { ...content, lifetime: cappedLifetime } as IRTCNotificationContent; +} + +/** + * Interface for `org.matrix.msc4075.rtc.notification` events. + * Don't cast event content to this directly. Use `parseCallNotificationContent` instead to validate the content first. + */ export interface IRTCNotificationContent extends RelationEvent { - "m.mentions": IMentions; - "decline_reason"?: string; + "m.mentions"?: IMentions; "notification_type": RTCNotificationType; /** * The initial intent of the calling user. From b0cbe22f644943e28645dc00b24a29589cc39505 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Thu, 23 Oct 2025 13:04:28 +0200 Subject: [PATCH 14/15] Add `CryptoApi.getSecretStorageStatus` (#5054) * Add `CryptoApi.getSecretStorageStatus` `isSecretStorageReady` is a bit of a blunt instrument: it's hard to see from logs *why* the secret storage isn't ready. Add a new method which returns a bit more data. * Update src/rust-crypto/rust-crypto.ts Co-authored-by: Andy Balaam --------- Co-authored-by: Andy Balaam --- spec/unit/rust-crypto/rust-crypto.spec.ts | 18 +++++++++++++ src/crypto-api/index.ts | 31 ++++++++++++++++++++- src/rust-crypto/rust-crypto.ts | 33 ++++++++++++++++++++--- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/spec/unit/rust-crypto/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts index e9c77ef4e..3c83cb1d7 100644 --- a/spec/unit/rust-crypto/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -854,9 +854,27 @@ describe("RustCrypto", () => { }); }); + it("getSecretStorageStatus", async () => { + const mockSecretStorage = { + getDefaultKeyId: jest.fn().mockResolvedValue("blah"), + isStored: jest.fn().mockResolvedValue({ blah: {} }), + } as unknown as Mocked; + const rustCrypto = await makeTestRustCrypto(undefined, undefined, undefined, mockSecretStorage); + await expect(rustCrypto.getSecretStorageStatus()).resolves.toEqual({ + defaultKeyId: "blah", + ready: true, + secretStorageKeyValidityMap: { + "m.cross_signing.master": true, + "m.cross_signing.self_signing": true, + "m.cross_signing.user_signing": true, + }, + }); + }); + it("isSecretStorageReady", async () => { const mockSecretStorage = { getDefaultKeyId: jest.fn().mockResolvedValue(null), + isStored: jest.fn().mockResolvedValue(null), } as unknown as Mocked; const rustCrypto = await makeTestRustCrypto(undefined, undefined, undefined, mockSecretStorage); await expect(rustCrypto.isSecretStorageReady()).resolves.toBe(false); diff --git a/src/crypto-api/index.ts b/src/crypto-api/index.ts index ff55c4396..976e6e46e 100644 --- a/src/crypto-api/index.ts +++ b/src/crypto-api/index.ts @@ -20,7 +20,7 @@ import type { ToDeviceBatch, ToDevicePayload } from "../models/ToDeviceMessage.t import { type Room } from "../models/room.ts"; import { type DeviceMap } from "../models/device.ts"; import { type UIAuthCallback } from "../interactive-auth.ts"; -import { type PassphraseInfo, type SecretStorageKeyDescription } from "../secret-storage.ts"; +import { type PassphraseInfo, type SecretStorageKey, type SecretStorageKeyDescription } from "../secret-storage.ts"; import { type VerificationRequest } from "./verification.ts"; import { type BackupTrustInfo, @@ -369,6 +369,11 @@ export interface CryptoApi { */ isSecretStorageReady(): Promise; + /** + * Inspect the status of secret storage, in more detail than {@link isSecretStorageReady}. + */ + getSecretStorageStatus(): Promise; + /** * Bootstrap [secret storage](https://spec.matrix.org/v1.12/client-server-api/#storage). * @@ -1148,6 +1153,30 @@ export interface CryptoCallbacks { cacheSecretStorageKey?: (keyId: string, keyInfo: SecretStorageKeyDescription, key: Uint8Array) => void; } +/** + * The result of a call to {@link CryptoApi.getSecretStorageStatus}. + */ +export interface SecretStorageStatus { + /** Whether secret storage is fully populated. The same as {@link CryptoApi.isSecretStorageReady}. */ + ready: boolean; + + /** The ID of the current default secret storage key. */ + defaultKeyId: string | null; + + /** + * For each secret that we checked whether it is correctly stored in secret storage with the default secret storage key. + * + * Note that we will only check that the key backup key is stored if key backup is currently enabled (i.e. that + * {@link CryptoApi.getActiveSessionBackupVersion} returns non-null). `m.megolm_backup.v1` will only be present in that case. + * + * (This is an object rather than a `Map` so that it JSON.stringify()s nicely, since its main purpose is to end up + * in logs.) + */ + secretStorageKeyValidityMap: { + [P in SecretStorageKey]?: boolean; + }; +} + /** * Parameter of {@link CryptoApi#bootstrapSecretStorage} */ diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index 638bf37d1..dbb0abf7c 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -65,6 +65,7 @@ import { type KeyBackupRestoreOpts, type KeyBackupRestoreResult, type OwnDeviceKeys, + type SecretStorageStatus, type StartDehydrationOpts, UserVerificationStatus, type VerificationRequest, @@ -78,7 +79,7 @@ import { type ServerSideSecretStorage, } from "../secret-storage.ts"; import { CrossSigningIdentity } from "./CrossSigningIdentity.ts"; -import { secretStorageCanAccessSecrets, secretStorageContainsCrossSigningKeys } from "./secret-storage.ts"; +import { secretStorageContainsCrossSigningKeys } from "./secret-storage.ts"; import { isVerificationEvent, RustVerificationRequest, verificationMethodIdentifierToMethod } from "./verification.ts"; import { EventType, MsgType } from "../@types/event.ts"; import { TypedEventEmitter } from "../models/typed-event-emitter.ts"; @@ -827,6 +828,13 @@ export class RustCrypto extends TypedEventEmitter { + return (await this.getSecretStorageStatus()).ready; + } + + /** + * Implementation of {@link CryptoApi#getSecretStorageStatus} + */ + public async getSecretStorageStatus(): Promise { // make sure that the cross-signing keys are stored const secretsToCheck: SecretStorageKey[] = [ "m.cross_signing.master", @@ -834,13 +842,32 @@ export class RustCrypto extends TypedEventEmitter Date: Thu, 23 Oct 2025 16:56:54 +0200 Subject: [PATCH 15/15] [MatrixRTC] Sticky Events support (MSC4354) (#5017) * Implement Sticky Events MSC * Renames * lint * some review work * Update for support for 4-ples * fix lint * pull through method * Fix the mistake * More tests to appease SC * Cleaner code * Review cleanup * Refactors based on review. * lint * Add sticky event support to the js-sdk Signed-off-by: Timo K * use sticky events for matrixRTC Signed-off-by: Timo K * make sticky events a non breaking change (default to state events. use joinConfig to use sticky events) Signed-off-by: Timo K * review - fix types (`msc4354_sticky:number` -> `msc4354_sticky?: { duration_ms: number };`) - add `MultiKeyMap` Signed-off-by: Timo K * Refactor all of this away to it's own accumulator and class. * Add tests * tidyup * more test cleaning * lint * Updates and tests * fix filter * fix filter with lint * Add timer tests * Add tests for MatrixRTCSessionManager * Listen for sticky events on MatrixRTCSessionManager * fix logic on filtering out state events * lint * more lint * tweaks * Add logging in areas * more debugging * much more logging * remove more logging * Finish supporting new MSC * a line * reconnect the bits to RTC * fixup more bits * fixup testrs * Ensure consistent order * lint * fix log line * remove extra bit of code * revert changes to room-sticky-events.ts * fixup mocks again * lint * fix * cleanup * fix paths * tweak test * fixup * Add more tests for coverage * Small improvements Signed-off-by: Timo K * review Signed-off-by: Timo K * Document better * fix sticky event type Signed-off-by: Timo K * fix demo Signed-off-by: Timo K * fix tests Signed-off-by: Timo K * Update src/matrixrtc/CallMembership.ts Co-authored-by: Robin * cleanup * lint * fix ci Signed-off-by: Timo K --------- Signed-off-by: Timo K Co-authored-by: Half-Shot Co-authored-by: Robin --- spec/unit/matrixrtc/MatrixRTCSession.spec.ts | 509 +++++++++++++----- .../matrixrtc/MatrixRTCSessionManager.spec.ts | 229 ++++---- spec/unit/matrixrtc/MembershipManager.spec.ts | 101 ++-- spec/unit/matrixrtc/mocks.ts | 41 +- src/@types/event.ts | 1 + src/matrixrtc/CallMembership.ts | 4 + src/matrixrtc/MatrixRTCSession.ts | 151 ++++-- src/matrixrtc/MatrixRTCSessionManager.ts | 24 +- src/matrixrtc/MembershipManager.ts | 260 +++++---- src/models/room-sticky-events.ts | 2 +- 10 files changed, 880 insertions(+), 442 deletions(-) diff --git a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts index 3e394119a..8eb11ecdd 100644 --- a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts @@ -14,13 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { encodeBase64, EventType, MatrixClient, type MatrixError, type MatrixEvent, type Room } from "../../../src"; +import { + encodeBase64, + type EventTimeline, + EventType, + MatrixClient, + type MatrixError, + type MatrixEvent, + type Room, +} from "../../../src"; import { KnownMembership } from "../../../src/@types/membership"; import { MatrixRTCSession, MatrixRTCSessionEvent } from "../../../src/matrixrtc/MatrixRTCSession"; import { Status, type EncryptionKeysEventContent } from "../../../src/matrixrtc/types"; -import { secureRandomString } from "../../../src/randomstring"; -import { makeMockEvent, makeMockRoom, membershipTemplate, makeKey, type MembershipData, mockRoomState } from "./mocks"; +import { + makeMockEvent, + makeMockRoom, + membershipTemplate, + makeKey, + type MembershipData, + mockRoomState, + mockRTCEvent, +} from "./mocks"; import { RTCEncryptionManager } from "../../../src/matrixrtc/RTCEncryptionManager.ts"; +import { RoomStickyEventsEvent, type StickyMatrixEvent } from "../../../src/models/room-sticky-events.ts"; +import { StickyEventMembershipManager } from "../../../src/matrixrtc/MembershipManager.ts"; const mockFocus = { type: "mock" }; @@ -47,11 +64,293 @@ describe("MatrixRTCSession", () => { sess = undefined; }); - describe("roomSessionForRoom", () => { - it("creates a room-scoped session from room state", () => { - const mockRoom = makeMockRoom([membershipTemplate]); + describe.each([ + { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + testCreateSticky: false, + createWithDefaults: true, // Create MatrixRTCSession with defaults + }, + { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + testCreateSticky: false, + }, + { + listenForStickyEvents: false, + listenForMemberStateEvents: true, + testCreateSticky: false, + }, + { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + testCreateSticky: true, + }, + { + listenForStickyEvents: true, + listenForMemberStateEvents: false, + testCreateSticky: true, + }, + ])( + "roomSessionForRoom listenForSticky=$listenForStickyEvents listenForMemberStateEvents=$listenForMemberStateEvents testCreateSticky=$testCreateSticky", + (testConfig) => { + it(`will ${testConfig.listenForMemberStateEvents ? "" : "NOT"} throw if the room does not have any state stored`, () => { + const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); + mockRoom.getLiveTimeline.mockReturnValue({ + getState: jest.fn().mockReturnValue(undefined), + } as unknown as EventTimeline); + if (testConfig.listenForMemberStateEvents) { + // eslint-disable-next-line jest/no-conditional-expect + expect(() => { + MatrixRTCSession.sessionForSlot(client, mockRoom, callSession, testConfig); + }).toThrow(); + } else { + // eslint-disable-next-line jest/no-conditional-expect + expect(() => { + MatrixRTCSession.sessionForSlot(client, mockRoom, callSession, testConfig); + }).not.toThrow(); + } + }); - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); + it("creates a room-scoped session from room state", () => { + const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); + + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships.length).toEqual(1); + expect(sess?.memberships[0].slotDescription.id).toEqual(""); + expect(sess?.memberships[0].scope).toEqual("m.room"); + expect(sess?.memberships[0].application).toEqual("m.call"); + expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA"); + expect(sess?.memberships[0].isExpired()).toEqual(false); + expect(sess?.slotDescription.id).toEqual(""); + }); + + it("ignores memberships where application is not m.call", () => { + const testMembership = Object.assign({}, membershipTemplate, { + application: "not-m.call", + }); + const mockRoom = makeMockRoom([testMembership], testConfig.testCreateSticky); + const sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships).toHaveLength(0); + }); + + it("ignores memberships where callId is not empty", () => { + const testMembership = Object.assign({}, membershipTemplate, { + call_id: "not-empty", + scope: "m.room", + }); + const mockRoom = makeMockRoom([testMembership], testConfig.testCreateSticky); + const sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships).toHaveLength(0); + }); + + it("ignores expired memberships events", () => { + jest.useFakeTimers(); + const expiredMembership = Object.assign({}, membershipTemplate); + expiredMembership.expires = 1000; + expiredMembership.device_id = "EXPIRED"; + const mockRoom = makeMockRoom([membershipTemplate, expiredMembership], testConfig.testCreateSticky); + + jest.advanceTimersByTime(2000); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships.length).toEqual(1); + expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA"); + jest.useRealTimers(); + }); + + it("ignores memberships events of members not in the room", () => { + const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); + mockRoom.hasMembershipState.mockImplementation((state) => state === KnownMembership.Join); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships.length).toEqual(0); + }); + + it("ignores memberships events with no sender", () => { + // Force the sender to be undefined. + const mockRoom = makeMockRoom([{ ...membershipTemplate, user_id: "" }], testConfig.testCreateSticky); + mockRoom.hasMembershipState.mockImplementation((state) => state === KnownMembership.Join); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships.length).toEqual(0); + }); + + it("honours created_ts", () => { + jest.useFakeTimers(); + jest.setSystemTime(500); + const expiredMembership = Object.assign({}, membershipTemplate); + expiredMembership.created_ts = 500; + expiredMembership.expires = 1000; + const mockRoom = makeMockRoom([expiredMembership], testConfig.testCreateSticky); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships[0].getAbsoluteExpiry()).toEqual(1500); + jest.useRealTimers(); + }); + + it("returns empty session if no membership events are present", () => { + const mockRoom = makeMockRoom([], testConfig.testCreateSticky); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess?.memberships).toHaveLength(0); + }); + + it("safely ignores events with no memberships section", () => { + const event = { + getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix), + getContent: jest.fn().mockReturnValue({}), + getSender: jest.fn().mockReturnValue("@mock:user.example"), + getTs: jest.fn().mockReturnValue(1000), + getLocalAge: jest.fn().mockReturnValue(0), + }; + const mockRoom = makeMockRoom([]); + mockRoom.getLiveTimeline.mockReturnValue({ + getState: jest.fn().mockReturnValue({ + on: jest.fn(), + off: jest.fn(), + getStateEvents: (_type: string, _stateKey: string) => [event], + events: new Map([ + [ + EventType.GroupCallMemberPrefix, + { + size: () => true, + has: (_stateKey: string) => true, + get: (_stateKey: string) => event, + values: () => [event], + }, + ], + ]), + }), + } as unknown as EventTimeline); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess.memberships).toHaveLength(0); + }); + + it("safely ignores events with junk memberships section", () => { + const event = { + getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix), + getContent: jest.fn().mockReturnValue({ memberships: ["i am a fish"] }), + getSender: jest.fn().mockReturnValue("@mock:user.example"), + getTs: jest.fn().mockReturnValue(1000), + getLocalAge: jest.fn().mockReturnValue(0), + }; + const mockRoom = makeMockRoom([]); + mockRoom.getLiveTimeline.mockReturnValue({ + getState: jest.fn().mockReturnValue({ + on: jest.fn(), + off: jest.fn(), + getStateEvents: (_type: string, _stateKey: string) => [event], + events: new Map([ + [ + EventType.GroupCallMemberPrefix, + { + size: () => true, + has: (_stateKey: string) => true, + get: (_stateKey: string) => event, + values: () => [event], + }, + ], + ]), + }), + } as unknown as EventTimeline); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess.memberships).toHaveLength(0); + }); + + it("ignores memberships with no device_id", () => { + const testMembership = Object.assign({}, membershipTemplate); + (testMembership.device_id as string | undefined) = undefined; + const mockRoom = makeMockRoom([testMembership]); + const sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess.memberships).toHaveLength(0); + }); + + it("ignores memberships with no call_id", () => { + const testMembership = Object.assign({}, membershipTemplate); + (testMembership.call_id as string | undefined) = undefined; + const mockRoom = makeMockRoom([testMembership]); + sess = MatrixRTCSession.sessionForSlot( + client, + mockRoom, + callSession, + testConfig.createWithDefaults ? undefined : testConfig, + ); + expect(sess.memberships).toHaveLength(0); + }); + }, + ); + + describe("roomSessionForRoom combined state", () => { + it("perfers sticky events when both membership and sticky events appear for the same user", () => { + // Create a room with identical member state and sticky state for the same user. + const mockRoom = makeMockRoom([membershipTemplate]); + mockRoom._unstable_getStickyEvents.mockImplementation(() => { + const ev = mockRTCEvent( + { + ...membershipTemplate, + msc4354_sticky_key: `_${membershipTemplate.user_id}_${membershipTemplate.device_id}`, + }, + mockRoom.roomId, + ); + return [ev as StickyMatrixEvent]; + }); + + // Expect for there to be one membership as the state has been merged down. + sess = MatrixRTCSession.sessionForSlot(client, mockRoom, callSession, { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + }); expect(sess?.memberships.length).toEqual(1); expect(sess?.memberships[0].slotDescription.id).toEqual(""); expect(sess?.memberships[0].scope).toEqual("m.room"); @@ -60,149 +359,67 @@ describe("MatrixRTCSession", () => { expect(sess?.memberships[0].isExpired()).toEqual(false); expect(sess?.slotDescription.id).toEqual(""); }); - - it("ignores memberships where application is not m.call", () => { - const testMembership = Object.assign({}, membershipTemplate, { - application: "not-m.call", - }); - const mockRoom = makeMockRoom([testMembership]); - const sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships).toHaveLength(0); - }); - - it("ignores memberships where callId is not empty", () => { - const testMembership = Object.assign({}, membershipTemplate, { - call_id: "not-empty", - scope: "m.room", - }); - const mockRoom = makeMockRoom([testMembership]); - const sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships).toHaveLength(0); - }); - - it("ignores expired memberships events", () => { - jest.useFakeTimers(); - const expiredMembership = Object.assign({}, membershipTemplate); - expiredMembership.expires = 1000; - expiredMembership.device_id = "EXPIRED"; - const mockRoom = makeMockRoom([membershipTemplate, expiredMembership]); - - jest.advanceTimersByTime(2000); - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships.length).toEqual(1); - expect(sess?.memberships[0].deviceId).toEqual("AAAAAAA"); - jest.useRealTimers(); - }); - - it("ignores memberships events of members not in the room", () => { + it("combines sticky and membership events when both exist", () => { + // Create a room with identical member state and sticky state for the same user. const mockRoom = makeMockRoom([membershipTemplate]); - mockRoom.hasMembershipState = (state) => state === KnownMembership.Join; - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships.length).toEqual(0); - }); + const stickyUserId = "@stickyev:user.example"; + mockRoom._unstable_getStickyEvents.mockImplementation(() => { + const ev = mockRTCEvent( + { + ...membershipTemplate, + user_id: stickyUserId, + msc4354_sticky_key: `_${stickyUserId}_${membershipTemplate.device_id}`, + }, + mockRoom.roomId, + 15000, + Date.now() - 1000, // Sticky event comes first. + ); + return [ev as StickyMatrixEvent]; + }); - it("honours created_ts", () => { - jest.useFakeTimers(); - jest.setSystemTime(500); - const expiredMembership = Object.assign({}, membershipTemplate); - expiredMembership.created_ts = 500; - expiredMembership.expires = 1000; - const mockRoom = makeMockRoom([expiredMembership]); - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships[0].getAbsoluteExpiry()).toEqual(1500); - jest.useRealTimers(); - }); + sess = MatrixRTCSession.sessionForSlot(client, mockRoom, callSession, { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + }); - it("returns empty session if no membership events are present", () => { - const mockRoom = makeMockRoom([]); - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess?.memberships).toHaveLength(0); - }); + const memberships = sess.memberships; + expect(memberships.length).toEqual(2); + expect(memberships[0].sender).toEqual(stickyUserId); + expect(memberships[0].slotDescription.id).toEqual(""); + expect(memberships[0].scope).toEqual("m.room"); + expect(memberships[0].application).toEqual("m.call"); + expect(memberships[0].deviceId).toEqual("AAAAAAA"); + expect(memberships[0].isExpired()).toEqual(false); - it("safely ignores events with no memberships section", () => { - const roomId = secureRandomString(8); - const event = { - getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix), - getContent: jest.fn().mockReturnValue({}), - getSender: jest.fn().mockReturnValue("@mock:user.example"), - getTs: jest.fn().mockReturnValue(1000), - getLocalAge: jest.fn().mockReturnValue(0), - }; - const mockRoom = { - ...makeMockRoom([]), - roomId, - getLiveTimeline: jest.fn().mockReturnValue({ - getState: jest.fn().mockReturnValue({ - on: jest.fn(), - off: jest.fn(), - getStateEvents: (_type: string, _stateKey: string) => [event], - events: new Map([ - [ - EventType.GroupCallMemberPrefix, - { - size: () => true, - has: (_stateKey: string) => true, - get: (_stateKey: string) => event, - values: () => [event], - }, - ], - ]), - }), - }), - }; - sess = MatrixRTCSession.sessionForRoom(client, mockRoom as unknown as Room, callSession); - expect(sess.memberships).toHaveLength(0); - }); + // Then state + expect(memberships[1].sender).toEqual(membershipTemplate.user_id); - it("safely ignores events with junk memberships section", () => { - const roomId = secureRandomString(8); - const event = { - getType: jest.fn().mockReturnValue(EventType.GroupCallMemberPrefix), - getContent: jest.fn().mockReturnValue({ memberships: ["i am a fish"] }), - getSender: jest.fn().mockReturnValue("@mock:user.example"), - getTs: jest.fn().mockReturnValue(1000), - getLocalAge: jest.fn().mockReturnValue(0), - }; - const mockRoom = { - ...makeMockRoom([]), - roomId, - getLiveTimeline: jest.fn().mockReturnValue({ - getState: jest.fn().mockReturnValue({ - on: jest.fn(), - off: jest.fn(), - getStateEvents: (_type: string, _stateKey: string) => [event], - events: new Map([ - [ - EventType.GroupCallMemberPrefix, - { - size: () => true, - has: (_stateKey: string) => true, - get: (_stateKey: string) => event, - values: () => [event], - }, - ], - ]), - }), - }), - }; - sess = MatrixRTCSession.sessionForRoom(client, mockRoom as unknown as Room, callSession); - expect(sess.memberships).toHaveLength(0); + expect(sess?.slotDescription.id).toEqual(""); }); + it("handles an incoming sticky event to an existing session", () => { + const mockRoom = makeMockRoom([membershipTemplate]); + const stickyUserId = "@stickyev:user.example"; - it("ignores memberships with no device_id", () => { - const testMembership = Object.assign({}, membershipTemplate); - (testMembership.device_id as string | undefined) = undefined; - const mockRoom = makeMockRoom([testMembership]); - const sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess.memberships).toHaveLength(0); - }); - - it("ignores memberships with no call_id", () => { - const testMembership = Object.assign({}, membershipTemplate); - (testMembership.call_id as string | undefined) = undefined; - const mockRoom = makeMockRoom([testMembership]); - sess = MatrixRTCSession.sessionForRoom(client, mockRoom, callSession); - expect(sess.memberships).toHaveLength(0); + sess = MatrixRTCSession.sessionForSlot(client, mockRoom, callSession, { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + }); + expect(sess.memberships.length).toEqual(1); + const stickyEv = mockRTCEvent( + { + ...membershipTemplate, + user_id: stickyUserId, + msc4354_sticky_key: `_${stickyUserId}_${membershipTemplate.device_id}`, + }, + mockRoom.roomId, + 15000, + Date.now() - 1000, // Sticky event comes first. + ) as StickyMatrixEvent; + mockRoom._unstable_getStickyEvents.mockImplementation(() => { + return [stickyEv]; + }); + mockRoom.emit(RoomStickyEventsEvent.Update, [stickyEv], [], []); + expect(sess.memberships.length).toEqual(2); }); }); @@ -329,6 +546,12 @@ describe("MatrixRTCSession", () => { expect(sess!.isJoined()).toEqual(true); }); + it("uses the sticky events membership manager implementation", () => { + sess!.joinRoomSession([mockFocus], mockFocus, { unstableSendStickyEvents: true }); + expect(sess!.isJoined()).toEqual(true); + expect(sess!["membershipManager"] instanceof StickyEventMembershipManager).toEqual(true); + }); + it("sends a notification when starting a call and emit DidSendCallNotification", async () => { // Simulate a join, including the update to the room state // Ensure sendEvent returns event IDs so the DidSendCallNotification payload includes them diff --git a/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts b/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts index 9472dc16e..a6d862cb0 100644 --- a/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts @@ -14,136 +14,145 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { ClientEvent, EventTimeline, MatrixClient } from "../../../src"; +import { ClientEvent, EventTimeline, MatrixClient, type Room } from "../../../src"; import { RoomStateEvent } from "../../../src/models/room-state"; import { MatrixRTCSessionManager, MatrixRTCSessionManagerEvents } from "../../../src/matrixrtc/MatrixRTCSessionManager"; -import { makeMockRoom, membershipTemplate, mockRoomState } from "./mocks"; +import { makeMockRoom, type MembershipData, membershipTemplate, mockRoomState, mockRTCEvent } from "./mocks"; import { logger } from "../../../src/logger"; -describe("MatrixRTCSessionManager", () => { - let client: MatrixClient; +describe.each([{ eventKind: "sticky" }, { eventKind: "memberState" }])( + "MatrixRTCSessionManager ($eventKind)", + ({ eventKind }) => { + let client: MatrixClient; - beforeEach(() => { - client = new MatrixClient({ baseUrl: "base_url" }); - client.matrixRTC.start(); - }); - - afterEach(() => { - client.stopClient(); - client.matrixRTC.stop(); - }); - - it("Fires event when session starts", () => { - const onStarted = jest.fn(); - client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); - - try { - const room1 = makeMockRoom([membershipTemplate]); - jest.spyOn(client, "getRooms").mockReturnValue([room1]); - - client.emit(ClientEvent.Room, room1); - expect(onStarted).toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); - } finally { - client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + function sendLeaveMembership(room: Room, membershipData: MembershipData[]): void { + if (eventKind === "memberState") { + mockRoomState(room, [{ user_id: membershipTemplate.user_id }]); + const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS)!; + const membEvent = roomState.getStateEvents("org.matrix.msc3401.call.member")[0]; + client.emit(RoomStateEvent.Events, membEvent, roomState, null); + } else { + membershipData.splice(0, 1, { user_id: membershipTemplate.user_id }); + client.emit(ClientEvent.Event, mockRTCEvent(membershipData[0], room.roomId, 10000)); + } } - }); - it("Doesn't fire event if unrelated sessions starts", () => { - const onStarted = jest.fn(); - client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + beforeEach(() => { + client = new MatrixClient({ baseUrl: "base_url" }); + client.matrixRTC.start(); + }); - try { - const room1 = makeMockRoom([{ ...membershipTemplate, application: "m.other" }]); + afterEach(() => { + client.stopClient(); + client.matrixRTC.stop(); + }); + + it("Fires event when session starts", () => { + const onStarted = jest.fn(); + client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + + try { + const room1 = makeMockRoom([membershipTemplate], eventKind === "sticky"); + jest.spyOn(client, "getRooms").mockReturnValue([room1]); + + client.emit(ClientEvent.Room, room1); + expect(onStarted).toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); + } finally { + client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + } + }); + + it("Doesn't fire event if unrelated sessions starts", () => { + const onStarted = jest.fn(); + client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + + try { + const room1 = makeMockRoom([{ ...membershipTemplate, application: "m.other" }], eventKind === "sticky"); + jest.spyOn(client, "getRooms").mockReturnValue([room1]); + + client.emit(ClientEvent.Room, room1); + expect(onStarted).not.toHaveBeenCalled(); + } finally { + client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + } + }); + + it("Fires event when session ends", () => { + const onEnded = jest.fn(); + client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); + const membershipData: MembershipData[] = [membershipTemplate]; + const room1 = makeMockRoom(membershipData, eventKind === "sticky"); jest.spyOn(client, "getRooms").mockReturnValue([room1]); - + jest.spyOn(client, "getRoom").mockReturnValue(room1); client.emit(ClientEvent.Room, room1); - expect(onStarted).not.toHaveBeenCalled(); - } finally { - client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); - } - }); - it("Fires event when session ends", () => { - const onEnded = jest.fn(); - client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); - const room1 = makeMockRoom([membershipTemplate]); - jest.spyOn(client, "getRooms").mockReturnValue([room1]); - jest.spyOn(client, "getRoom").mockReturnValue(room1); + sendLeaveMembership(room1, membershipData); - client.emit(ClientEvent.Room, room1); + expect(onEnded).toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); + }); - mockRoomState(room1, [{ user_id: membershipTemplate.user_id }]); + it("Fires correctly with custom sessionDescription", () => { + const onStarted = jest.fn(); + const onEnded = jest.fn(); + // create a session manager with a custom session description + const sessionManager = new MatrixRTCSessionManager(logger, client, { + id: "test", + application: "m.notCall", + }); - const roomState = room1.getLiveTimeline().getState(EventTimeline.FORWARDS)!; - const membEvent = roomState.getStateEvents("org.matrix.msc3401.call.member")[0]; - client.emit(RoomStateEvent.Events, membEvent, roomState, null); + // manually start the session manager (its not the default one started by the client) + sessionManager.start(); + sessionManager.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); + sessionManager.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); - expect(onEnded).toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); - }); + try { + // Create a session for applicaation m.other, we ignore this session ecause it lacks a call_id + const room1MembershipData: MembershipData[] = [{ ...membershipTemplate, application: "m.other" }]; + const room1 = makeMockRoom(room1MembershipData, eventKind === "sticky"); + jest.spyOn(client, "getRooms").mockReturnValue([room1]); + client.emit(ClientEvent.Room, room1); + expect(onStarted).not.toHaveBeenCalled(); + onStarted.mockClear(); - it("Fires correctly with for with custom sessionDescription", () => { - const onStarted = jest.fn(); - const onEnded = jest.fn(); - // create a session manager with a custom session description - const sessionManager = new MatrixRTCSessionManager(logger, client, { id: "test", application: "m.notCall" }); + // Create a session for applicaation m.notCall. We expect this call to be tracked because it has a call_id + const room2MembershipData: MembershipData[] = [ + { ...membershipTemplate, application: "m.notCall", call_id: "test" }, + ]; + const room2 = makeMockRoom(room2MembershipData, eventKind === "sticky"); + jest.spyOn(client, "getRooms").mockReturnValue([room1, room2]); + client.emit(ClientEvent.Room, room2); + expect(onStarted).toHaveBeenCalled(); + onStarted.mockClear(); - // manually start the session manager (its not the default one started by the client) - sessionManager.start(); - sessionManager.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); - sessionManager.on(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + // Stop room1's RTC session. Tracked. + jest.spyOn(client, "getRoom").mockReturnValue(room2); + sendLeaveMembership(room2, room2MembershipData); + expect(onEnded).toHaveBeenCalled(); + onEnded.mockClear(); - try { - const room1 = makeMockRoom([{ ...membershipTemplate, application: "m.other" }]); + // Stop room1's RTC session. Not tracked. + jest.spyOn(client, "getRoom").mockReturnValue(room1); + sendLeaveMembership(room1, room1MembershipData); + expect(onEnded).not.toHaveBeenCalled(); + } finally { + client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); + client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); + } + }); + + it("Doesn't fire event if unrelated sessions ends", () => { + const onEnded = jest.fn(); + client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); + const membership: MembershipData[] = [{ ...membershipTemplate, application: "m.other_app" }]; + const room1 = makeMockRoom(membership, eventKind === "sticky"); jest.spyOn(client, "getRooms").mockReturnValue([room1]); - - client.emit(ClientEvent.Room, room1); - expect(onStarted).not.toHaveBeenCalled(); - onStarted.mockClear(); - - const room2 = makeMockRoom([{ ...membershipTemplate, application: "m.notCall", call_id: "test" }]); - jest.spyOn(client, "getRooms").mockReturnValue([room1, room2]); - - client.emit(ClientEvent.Room, room2); - expect(onStarted).toHaveBeenCalled(); - onStarted.mockClear(); - - mockRoomState(room2, [{ user_id: membershipTemplate.user_id }]); - jest.spyOn(client, "getRoom").mockReturnValue(room2); - - const roomState = room2.getLiveTimeline().getState(EventTimeline.FORWARDS)!; - const membEvent = roomState.getStateEvents("org.matrix.msc3401.call.member")[0]; - client.emit(RoomStateEvent.Events, membEvent, roomState, null); - expect(onEnded).toHaveBeenCalled(); - onEnded.mockClear(); - - mockRoomState(room1, [{ user_id: membershipTemplate.user_id }]); jest.spyOn(client, "getRoom").mockReturnValue(room1); - const roomStateOther = room1.getLiveTimeline().getState(EventTimeline.FORWARDS)!; - const membEventOther = roomStateOther.getStateEvents("org.matrix.msc3401.call.member")[0]; - client.emit(RoomStateEvent.Events, membEventOther, roomStateOther, null); - expect(onEnded).not.toHaveBeenCalled(); - } finally { - client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionStarted, onStarted); - client.matrixRTC.off(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); - } - }); + client.emit(ClientEvent.Room, room1); - it("Doesn't fire event if unrelated sessions ends", () => { - const onEnded = jest.fn(); - client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); - const room1 = makeMockRoom([{ ...membershipTemplate, application: "m.other_app" }]); - jest.spyOn(client, "getRooms").mockReturnValue([room1]); - jest.spyOn(client, "getRoom").mockReturnValue(room1); + sendLeaveMembership(room1, membership); - client.emit(ClientEvent.Room, room1); - - mockRoomState(room1, [{ user_id: membershipTemplate.user_id }]); - - const roomState = room1.getLiveTimeline().getState(EventTimeline.FORWARDS)!; - const membEvent = roomState.getStateEvents("org.matrix.msc3401.call.member")[0]; - client.emit(RoomStateEvent.Events, membEvent, roomState, null); - - expect(onEnded).not.toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); - }); -}); + expect(onEnded).not.toHaveBeenCalledWith(room1.roomId, client.matrixRTC.getActiveRoomSession(room1)); + }); + }, +); diff --git a/spec/unit/matrixrtc/MembershipManager.spec.ts b/spec/unit/matrixrtc/MembershipManager.spec.ts index 1e0e0b5e7..8c4f90c00 100644 --- a/spec/unit/matrixrtc/MembershipManager.spec.ts +++ b/spec/unit/matrixrtc/MembershipManager.spec.ts @@ -23,6 +23,7 @@ import { MatrixError, UnsupportedDelayedEventsEndpointError, type Room, + MAX_STICKY_DURATION_MS, } from "../../../src"; import { MembershipManagerEvent, @@ -32,7 +33,7 @@ import { type LivekitFocusSelection, } from "../../../src/matrixrtc"; import { makeMockClient, makeMockRoom, membershipTemplate, mockCallMembership, type MockClient } from "./mocks"; -import { MembershipManager } from "../../../src/matrixrtc/MembershipManager.ts"; +import { MembershipManager, StickyEventMembershipManager } from "../../../src/matrixrtc/MembershipManager.ts"; /** * Create a promise that will resolve once a mocked method is called. @@ -93,7 +94,9 @@ describe("MembershipManager", () => { // Provide a default mock that is like the default "non error" server behaviour. (client._unstable_sendDelayedStateEvent as Mock).mockResolvedValue({ delay_id: "id" }); (client._unstable_updateDelayedEvent as Mock).mockResolvedValue(undefined); - (client.sendStateEvent as Mock).mockResolvedValue(undefined); + (client._unstable_sendStickyEvent as Mock).mockResolvedValue({ event_id: "id" }); + (client._unstable_sendStickyDelayedEvent as Mock).mockResolvedValue({ delay_id: "id" }); + (client.sendStateEvent as Mock).mockResolvedValue({ event_id: "id" }); }); afterEach(() => { @@ -151,43 +154,6 @@ describe("MembershipManager", () => { expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledTimes(1); }); - it("sends a rtc membership event when using `useRtcMemberFormat`", async () => { - // Spys/Mocks - - const updateDelayedEventHandle = createAsyncHandle(client._unstable_updateDelayedEvent as Mock); - - // Test - const memberManager = new MembershipManager({ useRtcMemberFormat: true }, room, client, callSession); - memberManager.join([], focus); - // expects - await waitForMockCall(client.sendStateEvent, Promise.resolve({ event_id: "id" })); - expect(client.sendStateEvent).toHaveBeenCalledWith( - room.roomId, - "org.matrix.msc4143.rtc.member", - { - application: { type: "m.call" }, - member: { - user_id: "@alice:example.org", - id: "_@alice:example.org_AAAAAAA_m.call", - device_id: "AAAAAAA", - }, - slot_id: "m.call#", - rtc_transports: [focus], - versions: [], - }, - "_@alice:example.org_AAAAAAA_m.call", - ); - updateDelayedEventHandle.resolve?.(); - expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledWith( - room.roomId, - { delay: 8000 }, - "org.matrix.msc4143.rtc.member", - {}, - "_@alice:example.org_AAAAAAA_m.call", - ); - expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledTimes(1); - }); - it("reschedules delayed leave event if sending state cancels it", async () => { const memberManager = new MembershipManager(undefined, room, client, callSession); const waitForSendState = waitForMockCall(client.sendStateEvent); @@ -921,6 +887,63 @@ describe("MembershipManager", () => { expect(client.sendStateEvent).toHaveBeenCalledTimes(0); }); }); + + describe("StickyEventMembershipManager", () => { + beforeEach(() => { + // Provide a default mock that is like the default "non error" server behaviour. + (client._unstable_sendStickyDelayedEvent as Mock).mockResolvedValue({ delay_id: "id" }); + (client._unstable_sendStickyEvent as Mock).mockResolvedValue(undefined); + }); + + describe("join()", () => { + describe("sends an rtc membership event", () => { + it("sends a membership event and schedules delayed leave when joining a call", async () => { + const updateDelayedEventHandle = createAsyncHandle( + client._unstable_updateDelayedEvent as Mock, + ); + const memberManager = new StickyEventMembershipManager(undefined, room, client, callSession); + + memberManager.join([], focus); + + await waitForMockCall(client._unstable_sendStickyEvent, Promise.resolve({ event_id: "id" })); + // Test we sent the initial join + expect(client._unstable_sendStickyEvent).toHaveBeenCalledWith( + room.roomId, + 3600000, + null, + "org.matrix.msc4143.rtc.member", + { + application: { type: "m.call" }, + member: { + user_id: "@alice:example.org", + id: "_@alice:example.org_AAAAAAA_m.call", + device_id: "AAAAAAA", + }, + slot_id: "m.call#", + rtc_transports: [focus], + versions: [], + msc4354_sticky_key: "_@alice:example.org_AAAAAAA_m.call", + }, + ); + updateDelayedEventHandle.resolve?.(); + + // Ensure we have sent the delayed disconnect event. + expect(client._unstable_sendStickyDelayedEvent).toHaveBeenCalledWith( + room.roomId, + MAX_STICKY_DURATION_MS, + { delay: 8000 }, + null, + "org.matrix.msc4143.rtc.member", + { + msc4354_sticky_key: "_@alice:example.org_AAAAAAA_m.call", + }, + ); + // ..once + expect(client._unstable_sendStickyDelayedEvent).toHaveBeenCalledTimes(1); + }); + }); + }); + }); }); it("Should prefix log with MembershipManager used", () => { diff --git a/spec/unit/matrixrtc/mocks.ts b/spec/unit/matrixrtc/mocks.ts index d61670d79..24982afe2 100644 --- a/spec/unit/matrixrtc/mocks.ts +++ b/spec/unit/matrixrtc/mocks.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { EventEmitter } from "stream"; +import { type Mocked } from "jest-mock"; import { EventType, type Room, RoomEvent, type MatrixClient, type MatrixEvent } from "../../../src"; import { CallMembership, type SessionMembershipData } from "../../../src/matrixrtc/CallMembership"; @@ -51,6 +52,8 @@ export type MockClient = Pick< | "sendStateEvent" | "_unstable_sendDelayedStateEvent" | "_unstable_updateDelayedEvent" + | "_unstable_sendStickyEvent" + | "_unstable_sendStickyDelayedEvent" | "cancelPendingEvent" >; /** @@ -65,15 +68,19 @@ export function makeMockClient(userId: string, deviceId: string): MockClient { cancelPendingEvent: jest.fn(), _unstable_updateDelayedEvent: jest.fn(), _unstable_sendDelayedStateEvent: jest.fn(), + _unstable_sendStickyEvent: jest.fn(), + _unstable_sendStickyDelayedEvent: jest.fn(), }; } export function makeMockRoom( membershipData: MembershipData[], -): Room & { emitTimelineEvent: (event: MatrixEvent) => void } { + useStickyEvents = false, +): Mocked void }> { const roomId = secureRandomString(8); // Caching roomState here so it does not get recreated when calling `getLiveTimeline.getState()` - const roomState = makeMockRoomState(membershipData, roomId); + const roomState = makeMockRoomState(useStickyEvents ? [] : membershipData, roomId); + const ts = Date.now(); const room = Object.assign(new EventEmitter(), { roomId: roomId, hasMembershipState: jest.fn().mockReturnValue(true), @@ -81,11 +88,16 @@ export function makeMockRoom( getState: jest.fn().mockReturnValue(roomState), }), getVersion: jest.fn().mockReturnValue("default"), - }) as unknown as Room; + _unstable_getStickyEvents: jest + .fn() + .mockImplementation(() => + useStickyEvents ? membershipData.map((m) => mockRTCEvent(m, roomId, 10000, ts)) : [], + ) as any, + }); return Object.assign(room, { emitTimelineEvent: (event: MatrixEvent) => room.emit(RoomEvent.Timeline, event, room, undefined, false, {} as any), - }); + }) as unknown as Mocked void }>; } function makeMockRoomState(membershipData: MembershipData[], roomId: string) { @@ -129,6 +141,7 @@ export function makeMockEvent( roomId: string | undefined, content: any, timestamp?: number, + stateKey?: string, ): MatrixEvent { return { getType: jest.fn().mockReturnValue(type), @@ -137,12 +150,28 @@ export function makeMockEvent( getTs: jest.fn().mockReturnValue(timestamp ?? Date.now()), getRoomId: jest.fn().mockReturnValue(roomId), getId: jest.fn().mockReturnValue(secureRandomString(8)), + getStateKey: jest.fn().mockReturnValue(stateKey), isDecryptionFailure: jest.fn().mockReturnValue(false), } as unknown as MatrixEvent; } -export function mockRTCEvent({ user_id: sender, ...membershipData }: MembershipData, roomId: string): MatrixEvent { - return makeMockEvent(EventType.GroupCallMemberPrefix, sender, roomId, membershipData); +export function mockRTCEvent( + { user_id: sender, ...membershipData }: MembershipData, + roomId: string, + stickyDuration?: number, + timestamp?: number, +): MatrixEvent { + return { + ...makeMockEvent( + stickyDuration !== undefined ? EventType.RTCMembership : EventType.GroupCallMemberPrefix, + sender, + roomId, + membershipData, + timestamp, + !stickyDuration && "device_id" in membershipData ? `_${sender}_${membershipData.device_id}` : "", + ), + unstableStickyExpiresAt: stickyDuration, + } as unknown as MatrixEvent; } export function mockCallMembership(membershipData: MembershipData, roomId: string): CallMembership { diff --git a/src/@types/event.ts b/src/@types/event.ts index 1364d9ca7..96780da84 100644 --- a/src/@types/event.ts +++ b/src/@types/event.ts @@ -338,6 +338,7 @@ export interface TimelineEvents { [M_BEACON.name]: MBeaconEventContent; [M_POLL_START.name]: PollStartEventContent; [M_POLL_END.name]: PollEndEventContent; + [EventType.RTCMembership]: RtcMembershipData | { msc4354_sticky_key: string }; // An object containing just the sticky key is empty. } /** diff --git a/src/matrixrtc/CallMembership.ts b/src/matrixrtc/CallMembership.ts index 59ff3778e..ba142ab06 100644 --- a/src/matrixrtc/CallMembership.ts +++ b/src/matrixrtc/CallMembership.ts @@ -195,6 +195,10 @@ export type SessionMembershipData = { * something else. */ "m.call.intent"?: RTCCallIntent; + /** + * The sticky key in case of a sticky event. This string encodes the application + device_id indicating the used slot + device. + */ + "msc4354_sticky_key"?: string; }; const checkSessionsMembershipData = (data: IContent, errors: string[]): data is SessionMembershipData => { diff --git a/src/matrixrtc/MatrixRTCSession.ts b/src/matrixrtc/MatrixRTCSession.ts index 9a61a7238..f5b39c48f 100644 --- a/src/matrixrtc/MatrixRTCSession.ts +++ b/src/matrixrtc/MatrixRTCSession.ts @@ -24,7 +24,7 @@ import { KnownMembership } from "../@types/membership.ts"; import { type ISendEventResponse } from "../@types/requests.ts"; import { CallMembership } from "./CallMembership.ts"; import { RoomStateEvent } from "../models/room-state.ts"; -import { MembershipManager } from "./MembershipManager.ts"; +import { MembershipManager, StickyEventMembershipManager } from "./MembershipManager.ts"; import { EncryptionManager, type IEncryptionManager } from "./EncryptionManager.ts"; import { deepCompare, logDurationSync } from "../utils.ts"; import type { @@ -50,6 +50,8 @@ import { } from "./RoomAndToDeviceKeyTransport.ts"; import { TypedReEmitter } from "../ReEmitter.ts"; import { ToDeviceKeyTransport } from "./ToDeviceKeyTransport.ts"; +import { type MatrixEvent } from "../models/event.ts"; +import { RoomStickyEventsEvent, type RoomStickyEventsMap } from "../models/room-sticky-events.ts"; /** * Events emitted by MatrixRTCSession @@ -123,14 +125,6 @@ export function slotDescriptionToId(slotDescription: SlotDescription): string { // - we use a `Ms` postfix if the option is a duration to avoid using words like: // `time`, `duration`, `delay`, `timeout`... that might be mistaken/confused with technical terms. export interface MembershipConfig { - /** - * Use the new Manager. - * - * Default: `false`. - * @deprecated does nothing anymore we always default to the new membership manager. - */ - useNewMembershipManager?: boolean; - /** * The timeout (in milliseconds) after we joined the call, that our membership should expire * unless we have explicitly updated it. @@ -192,7 +186,14 @@ export interface MembershipConfig { * but only applies to calls to the `_unstable_updateDelayedEvent` endpoint with a body of `{action:"restart"}`.) */ delayedLeaveEventRestartLocalTimeoutMs?: number; - useRtcMemberFormat?: boolean; + + /** + * Send membership using sticky events rather than state events. + * This also make the client use the new m.rtc.member MSC4354 event format. (instead of m.call.member) + * + * **WARNING**: This is an unstable feature and not all clients will support it. + */ + unstableSendStickyEvents?: boolean; } export interface EncryptionConfig { @@ -238,6 +239,19 @@ export interface EncryptionConfig { } export type JoinSessionConfig = SessionConfig & MembershipConfig & EncryptionConfig; +interface SessionMembershipsForRoomOpts { + /** + * Listen for incoming sticky member events. If disabled, this session will + * ignore any incoming sticky events. + */ + listenForStickyEvents: boolean; + /** + * Listen for incoming member state events (legacy). If disabled, this session will + * ignore any incoming state events. + */ + listenForMemberStateEvents: boolean; +} + /** * A MatrixRTCSession manages the membership & properties of a MatrixRTC session. * This class doesn't deal with media at all, just membership & properties of a session. @@ -307,7 +321,7 @@ export class MatrixRTCSession extends TypedEventEmitter< * @deprecated Use `MatrixRTCSession.sessionMembershipsForSlot` instead. */ public static callMembershipsForRoom( - room: Pick, + room: Pick, ): CallMembership[] { return MatrixRTCSession.sessionMembershipsForSlot(room, { id: "", @@ -319,7 +333,7 @@ export class MatrixRTCSession extends TypedEventEmitter< * @deprecated use `MatrixRTCSession.slotMembershipsForRoom` instead. */ public static sessionMembershipsForRoom( - room: Pick, + room: Pick, sessionDescription: SlotDescription, ): CallMembership[] { return this.sessionMembershipsForSlot(room, sessionDescription); @@ -328,30 +342,58 @@ export class MatrixRTCSession extends TypedEventEmitter< /** * Returns all the call memberships for a room that match the provided `sessionDescription`, * oldest first. + * + * By default, this will return *both* sticky and member state events. */ public static sessionMembershipsForSlot( - room: Pick, + room: Pick, slotDescription: SlotDescription, + // default both true this implied we combine sticky and state events for the final call state + // (prefer sticky events in case of a duplicate) + { listenForStickyEvents, listenForMemberStateEvents }: SessionMembershipsForRoomOpts = { + listenForStickyEvents: true, + listenForMemberStateEvents: true, + }, ): CallMembership[] { const logger = rootLogger.getChild(`[MatrixRTCSession ${room.roomId}]`); - const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS); - if (!roomState) { - logger.warn("Couldn't get state for room " + room.roomId); - throw new Error("Could't get state for room " + room.roomId); + let callMemberEvents = [] as MatrixEvent[]; + if (listenForStickyEvents) { + // prefill with sticky events + callMemberEvents = [...room._unstable_getStickyEvents()].filter( + (e) => e.getType() === EventType.RTCMembership, + ); + } + if (listenForMemberStateEvents) { + const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS); + if (!roomState) { + logger.warn("Couldn't get state for room " + room.roomId); + throw new Error("Could't get state for room " + room.roomId); + } + const callMemberStateEvents = roomState.getStateEvents(EventType.GroupCallMemberPrefix); + callMemberEvents = callMemberEvents.concat( + callMemberStateEvents.filter( + (callMemberStateEvent) => + !callMemberEvents.some( + // only care about state events which have keys which we have not yet seen in the sticky events. + (stickyEvent) => + stickyEvent.getContent().msc4354_sticky_key === callMemberStateEvent.getStateKey(), + ), + ), + ); } - const callMemberEvents = roomState.getStateEvents(EventType.GroupCallMemberPrefix); const callMemberships: CallMembership[] = []; for (const memberEvent of callMemberEvents) { const content = memberEvent.getContent(); - const eventKeysCount = Object.keys(content).length; + // Ignore sticky keys for the count + const eventKeysCount = Object.keys(content).filter((k) => k !== "msc4354_sticky_key").length; // Dont even bother about empty events (saves us from costly type/"key in" checks in bigger rooms) if (eventKeysCount === 0) continue; const membershipContents: any[] = []; // We first decide if its a MSC4143 event (per device state key) - if (eventKeysCount > 1 && "focus_active" in content) { + if (eventKeysCount > 1 && "application" in content) { // We have a MSC4143 event membership event membershipContents.push(content); } else if (eventKeysCount === 1 && "memberships" in content) { @@ -411,8 +453,16 @@ export class MatrixRTCSession extends TypedEventEmitter< * * @deprecated Use `MatrixRTCSession.sessionForSlot` with sessionDescription `{ id: "", application: "m.call" }` instead. */ - public static roomSessionForRoom(client: MatrixClient, room: Room): MatrixRTCSession { - const callMemberships = MatrixRTCSession.sessionMembershipsForSlot(room, { id: "", application: "m.call" }); + public static roomSessionForRoom( + client: MatrixClient, + room: Room, + opts?: SessionMembershipsForRoomOpts, + ): MatrixRTCSession { + const callMemberships = MatrixRTCSession.sessionMembershipsForSlot( + room, + { id: "", application: "m.call" }, + opts, + ); return new MatrixRTCSession(client, room, callMemberships, { id: "", application: "m.call" }); } @@ -428,9 +478,13 @@ export class MatrixRTCSession extends TypedEventEmitter< * This returned session can be used to find out if there are active sessions * for the requested room and `slotDescription`. */ - public static sessionForSlot(client: MatrixClient, room: Room, slotDescription: SlotDescription): MatrixRTCSession { - const callMemberships = MatrixRTCSession.sessionMembershipsForSlot(room, slotDescription); - + public static sessionForSlot( + client: MatrixClient, + room: Room, + slotDescription: SlotDescription, + opts?: SessionMembershipsForRoomOpts, + ): MatrixRTCSession { + const callMemberships = MatrixRTCSession.sessionMembershipsForSlot(room, slotDescription, opts); return new MatrixRTCSession(client, room, callMemberships, slotDescription); } @@ -461,10 +515,12 @@ export class MatrixRTCSession extends TypedEventEmitter< MatrixClient, | "getUserId" | "getDeviceId" + | "sendEvent" | "sendStateEvent" | "_unstable_sendDelayedStateEvent" | "_unstable_updateDelayedEvent" - | "sendEvent" + | "_unstable_sendStickyEvent" + | "_unstable_sendStickyDelayedEvent" | "cancelPendingEvent" | "encryptAndSendToDevice" | "off" @@ -488,9 +544,10 @@ export class MatrixRTCSession extends TypedEventEmitter< const roomState = this.roomSubset.getLiveTimeline().getState(EventTimeline.FORWARDS); // TODO: double check if this is actually needed. Should be covered by refreshRoom in MatrixRTCSessionManager roomState?.on(RoomStateEvent.Members, this.onRoomMemberUpdate); + this.roomSubset.on(RoomStickyEventsEvent.Update, this.onStickyEventUpdate); + this.setExpiryTimer(); } - /* * Returns true if we intend to be participating in the MatrixRTC session. * This is determined by checking if the relativeExpiry has been set. @@ -510,7 +567,9 @@ export class MatrixRTCSession extends TypedEventEmitter< } const roomState = this.roomSubset.getLiveTimeline().getState(EventTimeline.FORWARDS); roomState?.off(RoomStateEvent.Members, this.onRoomMemberUpdate); + this.roomSubset.off(RoomStickyEventsEvent.Update, this.onStickyEventUpdate); } + private reEmitter = new TypedReEmitter< MatrixRTCSessionEvent | RoomAndToDeviceEvents | MembershipManagerEvent, MatrixRTCSessionEventHandlerMap & RoomAndToDeviceEventsHandlerMap & MembershipManagerEventHandlerMap @@ -540,14 +599,15 @@ export class MatrixRTCSession extends TypedEventEmitter< return; } else { // Create MembershipManager and pass the RTCSession logger (with room id info) - - this.membershipManager = new MembershipManager( - joinConfig, - this.roomSubset, - this.client, - this.slotDescription, - this.logger, - ); + this.membershipManager = joinConfig?.unstableSendStickyEvents + ? new StickyEventMembershipManager( + joinConfig, + this.roomSubset, + this.client, + this.slotDescription, + this.logger, + ) + : new MembershipManager(joinConfig, this.roomSubset, this.client, this.slotDescription, this.logger); this.reEmitter.reEmit(this.membershipManager!, [ MembershipManagerEvent.ProbablyLeft, @@ -786,10 +846,27 @@ export class MatrixRTCSession extends TypedEventEmitter< /** * Call this when the Matrix room members have changed. */ - public onRoomMemberUpdate = (): void => { + private readonly onRoomMemberUpdate = (): void => { this.recalculateSessionMembers(); }; + /** + * Call this when a sticky event update has occured. + */ + private readonly onStickyEventUpdate: RoomStickyEventsMap[RoomStickyEventsEvent.Update] = ( + added, + updated, + removed, + ): void => { + if ( + [...added, ...removed, ...updated.flatMap((v) => [v.current, v.previous])].some( + (e) => e.getType() === EventType.RTCMembership, + ) + ) { + this.recalculateSessionMembers(); + } + }; + /** * Call this when something changed that may impacts the current MatrixRTC members in this session. */ @@ -839,6 +916,8 @@ export class MatrixRTCSession extends TypedEventEmitter< // If anyone else joins the session it is no longer our responsibility to send the notification. // (If we were the joiner we already did sent the notification in the block above.) if (this.memberships.length > 0) this.pendingNotificationToSend = undefined; + } else { + this.logger.debug(`No membership changes detected for room ${this.roomSubset.roomId}`); } // This also needs to be done if `changed` = false // A member might have updated their fingerprint (created_ts) diff --git a/src/matrixrtc/MatrixRTCSessionManager.ts b/src/matrixrtc/MatrixRTCSessionManager.ts index 792132d27..a103b39db 100644 --- a/src/matrixrtc/MatrixRTCSessionManager.ts +++ b/src/matrixrtc/MatrixRTCSessionManager.ts @@ -18,7 +18,7 @@ import { type Logger } from "../logger.ts"; import { type MatrixClient, ClientEvent } from "../client.ts"; import { TypedEventEmitter } from "../models/typed-event-emitter.ts"; import { type Room } from "../models/room.ts"; -import { type RoomState, RoomStateEvent } from "../models/room-state.ts"; +import { RoomStateEvent } from "../models/room-state.ts"; import { type MatrixEvent } from "../models/event.ts"; import { MatrixRTCSession, type SlotDescription } from "./MatrixRTCSession.ts"; import { EventType } from "../@types/event.ts"; @@ -73,6 +73,7 @@ export class MatrixRTCSessionManager extends TypedEventEmitter { + private readonly onEvent = (event: MatrixEvent): void => { + if (!event.unstableStickyExpiresAt) return; // Not sticky, not interested. + + if (event.getType() !== EventType.RTCMembership) return; + + const room = this.client.getRoom(event.getRoomId()); + if (!room) return; + + this.refreshRoom(room); + }; + + private readonly onRoomState = (event: MatrixEvent): void => { + if (event.getType() !== EventType.GroupCallMemberPrefix) { + return; + } const room = this.client.getRoom(event.getRoomId()); if (!room) { this.logger.error(`Got room state event for unknown room ${event.getRoomId()}!`); return; } - if (event.getType() == EventType.GroupCallMemberPrefix) { - this.refreshRoom(room); - } + this.refreshRoom(room); }; private refreshRoom(room: Room): void { diff --git a/src/matrixrtc/MembershipManager.ts b/src/matrixrtc/MembershipManager.ts index 45f0a5ce9..533f9adfc 100644 --- a/src/matrixrtc/MembershipManager.ts +++ b/src/matrixrtc/MembershipManager.ts @@ -16,7 +16,12 @@ limitations under the License. import { AbortError } from "p-retry"; import { EventType, RelationType } from "../@types/event.ts"; -import { UpdateDelayedEventAction } from "../@types/requests.ts"; +import { + type ISendEventResponse, + type SendDelayedEventResponse, + UpdateDelayedEventAction, +} from "../@types/requests.ts"; +import { type EmptyObject } from "../@types/common.ts"; import type { MatrixClient } from "../client.ts"; import { ConnectionError, HTTPError, MatrixError } from "../http-api/errors.ts"; import { type Logger, logger as rootLogger } from "../logger.ts"; @@ -84,6 +89,12 @@ On Leave: ───────── STOP ALL ABOVE (s) Successful restart/resend */ +/** + * Call membership should always remain sticky for this amount + * of time. + */ +const MEMBERSHIP_STICKY_DURATION_MS = 60 * 60 * 1000; // 60 minutes + /** * The different types of actions the MembershipManager can take. * @internal @@ -144,6 +155,23 @@ export interface MembershipManagerState { probablyLeft: boolean; } +function createInsertActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate { + return { + insert: [{ ts: Date.now() + (offset ?? 0), type }], + }; +} + +function createReplaceActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate { + return { + replace: [{ ts: Date.now() + (offset ?? 0), type }], + }; +} + +type MembershipManagerClient = Pick< + MatrixClient, + "getUserId" | "getDeviceId" | "sendStateEvent" | "_unstable_sendDelayedStateEvent" | "_unstable_updateDelayedEvent" +>; + /** * This class is responsible for sending all events relating to the own membership of a matrixRTC call. * It has the following tasks: @@ -162,8 +190,8 @@ export class MembershipManager implements IMembershipManager { private activated = false; - private logger: Logger; - private callIntent: RTCCallIntent | undefined; + private readonly logger: Logger; + protected callIntent: RTCCallIntent | undefined; public isActivated(): boolean { return this.activated; @@ -295,16 +323,9 @@ export class MembershipManager * @param client */ public constructor( - private joinConfig: (SessionConfig & MembershipConfig) | undefined, - private room: Pick, - private client: Pick< - MatrixClient, - | "getUserId" - | "getDeviceId" - | "sendStateEvent" - | "_unstable_sendDelayedStateEvent" - | "_unstable_updateDelayedEvent" - >, + private readonly joinConfig: (SessionConfig & MembershipConfig) | undefined, + protected readonly room: Pick, + protected readonly client: MembershipManagerClient, public readonly slotDescription: SlotDescription, parentLogger?: Logger, ) { @@ -361,11 +382,11 @@ export class MembershipManager }; } // Membership Event static parameters: - private deviceId: string; - private memberId: string; + protected deviceId: string; + protected memberId: string; + protected rtcTransport?: Transport; /** @deprecated This will be removed in favor or rtcTransport becoming a list of actively used transports */ private fociPreferred?: Transport[]; - private rtcTransport?: Transport; // Config: private delayedLeaveEventDelayMsOverride?: number; @@ -380,9 +401,13 @@ export class MembershipManager return this.joinConfig?.membershipEventExpiryHeadroomMs ?? 5_000; } private computeNextExpiryActionTs(iteration: number): number { - return this.state.startTime + this.membershipEventExpiryMs * iteration - this.membershipEventExpiryHeadroomMs; + return ( + this.state.startTime + + Math.min(this.membershipEventExpiryMs, MEMBERSHIP_STICKY_DURATION_MS) * iteration - + this.membershipEventExpiryHeadroomMs + ); } - private get delayedLeaveEventDelayMs(): number { + protected get delayedLeaveEventDelayMs(): number { return this.delayedLeaveEventDelayMsOverride ?? this.joinConfig?.delayedLeaveEventDelayMs ?? 8_000; } private get delayedLeaveEventRestartMs(): number { @@ -394,13 +419,10 @@ export class MembershipManager private get maximumNetworkErrorRetryCount(): number { return this.joinConfig?.maximumNetworkErrorRetryCount ?? 10; } - private get delayedLeaveEventRestartLocalTimeoutMs(): number { return this.joinConfig?.delayedLeaveEventRestartLocalTimeoutMs ?? 2000; } - private get useRtcMemberFormat(): boolean { - return this.joinConfig?.useRtcMemberFormat ?? false; - } + // LOOP HANDLER: private async membershipLoopHandler(type: MembershipActionType): Promise { switch (type) { @@ -455,22 +477,23 @@ export class MembershipManager } } + // an abstraction to switch between sending state or a sticky event + protected clientSendDelayedDisconnectMembership: () => Promise = () => + this.client._unstable_sendDelayedStateEvent( + this.room.roomId, + { delay: this.delayedLeaveEventDelayMs }, + EventType.GroupCallMemberPrefix, + {}, + this.memberId, + ); + // HANDLERS (used in the membershipLoopHandler) private async sendOrResendDelayedLeaveEvent(): Promise { // We can reach this at the start of a call (where we do not yet have a membership: state.hasMemberStateEvent=false) // or during a call if the state event canceled our delayed event or caused by an unexpected error that removed our delayed event. // (Another client could have canceled it, the homeserver might have removed/lost it due to a restart, ...) // In the `then` and `catch` block we treat both cases differently. "if (this.state.hasMemberStateEvent) {} else {}" - return await this.client - ._unstable_sendDelayedStateEvent( - this.room.roomId, - { - delay: this.delayedLeaveEventDelayMs, - }, - this.useRtcMemberFormat ? EventType.RTCMembership : EventType.GroupCallMemberPrefix, - {}, // leave event - this.memberId, - ) + return await this.clientSendDelayedDisconnectMembership() .then((response) => { this.state.expectedServerDelayLeaveTs = Date.now() + this.delayedLeaveEventDelayMs; this.setAndEmitProbablyLeft(false); @@ -494,7 +517,7 @@ export class MembershipManager if (this.manageMaxDelayExceededSituation(e)) { return createInsertActionUpdate(repeatActionType); } - const update = this.actionUpdateFromErrors(e, repeatActionType, "sendDelayedStateEvent"); + const update = this.actionUpdateFromErrors(e, repeatActionType, "_unstable_sendDelayedStateEvent"); if (update) return update; if (this.state.hasMemberStateEvent) { @@ -650,14 +673,19 @@ export class MembershipManager }); } + protected clientSendMembership: ( + myMembership: RtcMembershipData | SessionMembershipData | EmptyObject, + ) => Promise = (myMembership) => { + return this.client.sendStateEvent( + this.room.roomId, + EventType.GroupCallMemberPrefix, + myMembership as EmptyObject | SessionMembershipData, + this.memberId, + ); + }; + private async sendJoinEvent(): Promise { - return await this.client - .sendStateEvent( - this.room.roomId, - this.useRtcMemberFormat ? EventType.RTCMembership : EventType.GroupCallMemberPrefix, - this.makeMyMembership(this.membershipEventExpiryMs), - this.memberId, - ) + return await this.clientSendMembership(this.makeMyMembership(this.membershipEventExpiryMs)) .then(() => { this.setAndEmitProbablyLeft(false); this.state.startTime = Date.now(); @@ -697,13 +725,9 @@ export class MembershipManager private async updateExpiryOnJoinedEvent(): Promise { const nextExpireUpdateIteration = this.state.expireUpdateIterations + 1; - return await this.client - .sendStateEvent( - this.room.roomId, - this.useRtcMemberFormat ? EventType.RTCMembership : EventType.GroupCallMemberPrefix, - this.makeMyMembership(this.membershipEventExpiryMs * nextExpireUpdateIteration), - this.memberId, - ) + return await this.clientSendMembership( + this.makeMyMembership(this.membershipEventExpiryMs * nextExpireUpdateIteration), + ) .then(() => { // Success, we reset retries and schedule update. this.resetRateLimitCounter(MembershipActionType.UpdateExpiry); @@ -725,13 +749,7 @@ export class MembershipManager }); } private async sendFallbackLeaveEvent(): Promise { - return await this.client - .sendStateEvent( - this.room.roomId, - this.useRtcMemberFormat ? EventType.RTCMembership : EventType.GroupCallMemberPrefix, - {}, - this.memberId, - ) + return await this.clientSendMembership({}) .then(() => { this.resetRateLimitCounter(MembershipActionType.SendLeaveEvent); this.state.hasMemberStateEvent = false; @@ -757,45 +775,29 @@ export class MembershipManager /** * Constructs our own membership */ - private makeMyMembership(expires: number): SessionMembershipData | RtcMembershipData { + protected makeMyMembership(expires: number): SessionMembershipData | RtcMembershipData { const ownMembership = this.ownMembership; - if (this.useRtcMemberFormat) { - const relationObject = ownMembership?.eventId - ? { "m.relation": { rel_type: RelationType.Reference, event_id: ownMembership?.eventId } } - : {}; - return { - application: { - type: this.slotDescription.application, - ...(this.callIntent ? { "m.call.intent": this.callIntent } : {}), - }, - slot_id: slotDescriptionToId(this.slotDescription), - rtc_transports: this.rtcTransport ? [this.rtcTransport] : [], - member: { device_id: this.deviceId, user_id: this.client.getUserId()!, id: this.memberId }, - versions: [], - ...relationObject, - }; - } else { - const focusObjects = - this.rtcTransport === undefined - ? { - focus_active: { type: "livekit", focus_selection: "oldest_membership" } as const, - foci_preferred: this.fociPreferred ?? [], - } - : { - focus_active: { type: "livekit", focus_selection: "multi_sfu" } as const, - foci_preferred: [this.rtcTransport, ...(this.fociPreferred ?? [])], - }; - return { - "application": this.slotDescription.application, - "call_id": this.slotDescription.id, - "scope": "m.room", - "device_id": this.deviceId, - expires, - "m.call.intent": this.callIntent, - ...focusObjects, - ...(ownMembership !== undefined ? { created_ts: ownMembership.createdTs() } : undefined), - }; - } + + const focusObjects = + this.rtcTransport === undefined + ? { + focus_active: { type: "livekit", focus_selection: "oldest_membership" } as const, + foci_preferred: this.fociPreferred ?? [], + } + : { + focus_active: { type: "livekit", focus_selection: "multi_sfu" } as const, + foci_preferred: [this.rtcTransport, ...(this.fociPreferred ?? [])], + }; + return { + "application": this.slotDescription.application, + "call_id": this.slotDescription.id, + "scope": "m.room", + "device_id": this.deviceId, + expires, + "m.call.intent": this.callIntent, + ...focusObjects, + ...(ownMembership !== undefined ? { created_ts: ownMembership.createdTs() } : undefined), + }; } // Error checks and handlers @@ -830,7 +832,7 @@ export class MembershipManager return false; } - private actionUpdateFromErrors( + protected actionUpdateFromErrors( error: unknown, type: MembershipActionType, method: string, @@ -878,7 +880,7 @@ export class MembershipManager return createInsertActionUpdate(type, resendDelay); } - throw Error("Exceeded maximum retries for " + type + " attempts (client." + method + "): " + (error as Error)); + throw Error("Exceeded maximum retries for " + type + " attempts (client." + method + ")", { cause: error }); } /** @@ -1022,14 +1024,68 @@ export class MembershipManager } } -function createInsertActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate { - return { - insert: [{ ts: Date.now() + (offset ?? 0), type }], - }; -} +/** + * Implementation of the Membership manager that uses sticky events + * rather than state events. + */ +export class StickyEventMembershipManager extends MembershipManager { + public constructor( + joinConfig: (SessionConfig & MembershipConfig) | undefined, + room: Pick, + private readonly clientWithSticky: MembershipManagerClient & + Pick, + sessionDescription: SlotDescription, + parentLogger?: Logger, + ) { + super(joinConfig, room, clientWithSticky, sessionDescription, parentLogger); + } -function createReplaceActionUpdate(type: MembershipActionType, offset?: number): ActionUpdate { - return { - replace: [{ ts: Date.now() + (offset ?? 0), type }], + protected clientSendDelayedDisconnectMembership: () => Promise = () => + this.clientWithSticky._unstable_sendStickyDelayedEvent( + this.room.roomId, + MEMBERSHIP_STICKY_DURATION_MS, + { delay: this.delayedLeaveEventDelayMs }, + null, + EventType.RTCMembership, + { msc4354_sticky_key: this.memberId }, + ); + + protected clientSendMembership: ( + myMembership: RtcMembershipData | SessionMembershipData | EmptyObject, + ) => Promise = (myMembership) => { + return this.clientWithSticky._unstable_sendStickyEvent( + this.room.roomId, + MEMBERSHIP_STICKY_DURATION_MS, + null, + EventType.RTCMembership, + { ...myMembership, msc4354_sticky_key: this.memberId }, + ); }; + + private static nameMap = new Map([ + ["sendStateEvent", "_unstable_sendStickyEvent"], + ["sendDelayedStateEvent", "_unstable_sendStickyDelayedEvent"], + ]); + protected actionUpdateFromErrors(e: unknown, t: MembershipActionType, m: string): ActionUpdate | undefined { + return super.actionUpdateFromErrors(e, t, StickyEventMembershipManager.nameMap.get(m) ?? "unknown"); + } + + protected makeMyMembership(expires: number): SessionMembershipData | RtcMembershipData { + const ownMembership = this.ownMembership; + + const relationObject = ownMembership?.eventId + ? { "m.relation": { rel_type: RelationType.Reference, event_id: ownMembership?.eventId } } + : {}; + return { + application: { + type: this.slotDescription.application, + ...(this.callIntent ? { "m.call.intent": this.callIntent } : {}), + }, + slot_id: slotDescriptionToId(this.slotDescription), + rtc_transports: this.rtcTransport ? [this.rtcTransport] : [], + member: { device_id: this.deviceId, user_id: this.client.getUserId()!, id: this.memberId }, + versions: [], + ...relationObject, + }; + } } diff --git a/src/models/room-sticky-events.ts b/src/models/room-sticky-events.ts index 85cee9f41..0f4c43f23 100644 --- a/src/models/room-sticky-events.ts +++ b/src/models/room-sticky-events.ts @@ -8,7 +8,7 @@ export enum RoomStickyEventsEvent { Update = "RoomStickyEvents.Update", } -type StickyMatrixEvent = MatrixEvent & { unstableStickyExpiresAt: number }; +export type StickyMatrixEvent = MatrixEvent & { unstableStickyExpiresAt: number }; export type RoomStickyEventsMap = { /**