diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 067c5246..2cd63d63 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. `; module.exports = { - plugins: ["matrix-org", "rxjs"], + plugins: ["matrix-org", "rxjs", "jsdoc"], extends: [ "plugin:matrix-org/react", "plugin:matrix-org/a11y", @@ -26,6 +26,13 @@ module.exports = { node: true, }, rules: { + "jsdoc/no-types": "error", + "jsdoc/empty-tags": "error", + "jsdoc/check-property-names": "error", + "jsdoc/check-values": "error", + "jsdoc/check-param-names": "warn", + // "jsdoc/require-param": "warn", + "jsdoc/require-param-description": "warn", "matrix-org/require-copyright-header": ["error", COPYRIGHT_HEADER], "jsx-a11y/media-has-caption": "off", "react/display-name": "error", @@ -75,6 +82,17 @@ module.exports = { "no-console": ["error"], }, }, + { + files: ["**/*.test.ts", "**/*.test.tsx", "**/test.ts", "**/test.tsx", "**/test-**"], + rules: { + "jsdoc/no-types": "off", + "jsdoc/empty-tags": "off", + "jsdoc/check-property-names": "off", + "jsdoc/check-values": "off", + "jsdoc/check-param-names": "off", + "jsdoc/require-param-description": "off", + } + } ], settings: { react: { diff --git a/package.json b/package.json index c67c2e4c..e5b57444 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,12 @@ "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", - "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip", + "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip && yarn lint:tsdoc", "lint:eslint": "eslint --max-warnings 0 src playwright", "lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix", "lint:knip": "knip", "lint:types": "tsc", + "lint:tsdoc": "eslint --ext .ts,.tsx src", "i18n": "i18next", "i18n:check": "i18next --fail-on-warnings --fail-on-update", "test": "vitest", @@ -95,6 +96,7 @@ "eslint-config-prettier": "^10.0.0", "eslint-plugin-deprecate": "^0.8.2", "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsdoc": "^61.5.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-matrix-org": "2.1.0", "eslint-plugin-react": "^7.29.4", diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index 6236928c..f1f738b7 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -67,7 +67,6 @@ const CONFIG_JSON = { /** * Set the Element Call URL in the dev tool settings using `window.mxSettingsStore` via `page.evaluate`. - * @param page */ const setDevToolElementCallDevUrl = process.env.USE_DOCKER ? async (page: Page): Promise => { diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index c68ba453..18d007e2 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -34,8 +34,8 @@ const getRoomSharedKeyLocalStorageKey = (roomId: string): string => `room-shared-key-${roomId}`; /** - * An upto-date shared key for the room. Either from local storage or the value from `setInitialValue`. - * @param roomId + * An up-to-date shared key for the room. Either from local storage or the value from `setInitialValue`. + * @param roomId The room ID we want the shared key for. * @param setInitialValue The value we get from the URL. The hook will overwrite the local storage value with this. * @returns [roomSharedKey, setRoomSharedKey] like a react useState hook. */ diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index 5b1149e9..741529b8 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -166,7 +166,11 @@ interface StereoPanAudioTrackProps { * It main purpose is to remount the AudioTrack component when switching from * audioContext to normal audio playback. * As of now the AudioTrack component does not support adding audio nodes while being mounted. - * @param param0 + * @param props The component props + * @param props.trackRef The track reference + * @param props.muted If the track should be muted + * @param props.audioContext The audio context to use + * @param props.audioNodes The audio nodes to use * @returns */ function AudioTrackWithAudioNodes({ diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index b3c07397..34c98a88 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -63,9 +63,9 @@ export type OpenIDClientParts = Pick< * Gets a bearer token from the homeserver and then use it to authenticate * to the matrix RTC backend in order to get acces to the SFU. * It has built-in retry for calls to the homeserver with a backoff policy. - * @param client - * @param serviceUrl - * @param matrixRoomId + * @param client The Matrix client + * @param serviceUrl The URL of the livekit SFU service + * @param matrixRoomId The Matrix room ID for which to get the SFU config * @returns Object containing the token information * @throws FailToGetOpenIdToken */ diff --git a/src/reactions/ReactionsReader.ts b/src/reactions/ReactionsReader.ts index 74b47c77..7ce59812 100644 --- a/src/reactions/ReactionsReader.ts +++ b/src/reactions/ReactionsReader.ts @@ -135,10 +135,10 @@ export class ReactionsReader { } /** - * Fetchest any hand wave reactions by the given sender on the given + * Fetches any hand wave reactions by the given sender on the given * membership event. - * @param membershipEventId - * @param expectedSender + * @param membershipEventId - The user membership event id. + * @param expectedSender - The expected sender of the reaction. * @returns A MatrixEvent if one was found. */ private getLastReactionEvent( diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts index ab6ccf64..2cd0d40b 100644 --- a/src/room/useLoadGroupCall.ts +++ b/src/room/useLoadGroupCall.ts @@ -106,22 +106,18 @@ async function joinRoomAfterInvite( export class CallTerminatedMessage extends Error { /** + * Creates a new CallTerminatedMessage. + * + * @param icon The icon to display with the message * @param messageTitle The title of the call ended screen message (translated) + * @param messageBody The message explaining the kind of termination + * (kick, ban, knock reject, etc.) (translated) + * @param reason The user-provided reason for the termination (kick/ban) */ public constructor( - /** - * The icon to display with the message. - */ public readonly icon: ComponentType>, messageTitle: string, - /** - * The message explaining the kind of termination (kick, ban, knock reject, - * etc.) (translated) - */ public readonly messageBody: string, - /** - * The user-provided reason for the termination (kick/ban) - */ public readonly reason?: string, ) { super(messageTitle); diff --git a/src/settings/rageshake.ts b/src/settings/rageshake.ts index 6c1a0f61..26d0839b 100644 --- a/src/settings/rageshake.ts +++ b/src/settings/rageshake.ts @@ -99,7 +99,7 @@ class ConsoleLogger extends EventEmitter { /** * Returns the log lines to flush to disk and empties the internal log buffer - * @return {string} \n delimited log lines + * @return \n delimited log lines */ public popLogs(): string { const logsToFlush = this.logs; @@ -109,7 +109,7 @@ class ConsoleLogger extends EventEmitter { /** * Returns lines currently in the log buffer without removing them - * @return {string} \n delimited log lines + * @return \n delimited log lines */ public peekLogs(): string { return this.logs; @@ -139,7 +139,7 @@ class IndexedDBLogStore { } /** - * @return {Promise} Resolves when the store is ready. + * @return Resolves when the store is ready. */ public async connect(): Promise { const req = this.indexedDB.open("logs"); @@ -219,7 +219,7 @@ class IndexedDBLogStore { * This guarantees that we will always eventually do a flush when flush() is * called. * - * @return {Promise} Resolved when the logs have been flushed. + * @return Resolved when the logs have been flushed. */ public flush = async (): Promise => { // check if a flush() operation is ongoing @@ -270,7 +270,7 @@ class IndexedDBLogStore { * returned are deleted at the same time, so this can be called at startup * to do house-keeping to keep the logs from growing too large. * - * @return {Promise} Resolves to an array of objects. The array is + * @return Resolves to an array of objects. The array is * sorted in time (oldest first) based on when the log file was created (the * log ID). The objects have said log ID in an "id" field and "lines" which * is a big string with all the new-line delimited logs. @@ -421,12 +421,12 @@ class IndexedDBLogStore { /** * Helper method to collect results from a Cursor and promiseify it. - * @param {ObjectStore|Index} store The store to perform openCursor on. - * @param {IDBKeyRange=} keyRange Optional key range to apply on the cursor. - * @param {Function} resultMapper A function which is repeatedly called with a + * @param store - The store to perform openCursor on. + * @param keyRange - Optional key range to apply on the cursor. + * @param resultMapper - A function which is repeatedly called with a * Cursor. * Return the data you want to keep. - * @return {Promise} Resolves to an array of whatever you returned from + * @return Resolves to an array of whatever you returned from * resultMapper. */ async function selectQuery( @@ -464,9 +464,7 @@ declare global { /** * Configure rage shaking support for sending bug reports. * Modifies globals. - * @param {boolean} setUpPersistence When true (default), the persistence will - * be set up immediately for the logs. - * @return {Promise} Resolves when set up. + * @return Resolves when set up. */ export async function init(): Promise { global.mx_rage_logger = new ConsoleLogger(); @@ -503,7 +501,7 @@ export async function init(): Promise { /** * Try to start up the rageshake storage for logs. If not possible (client unsupported) * then this no-ops. - * @return {Promise} Resolves when complete. + * @return Resolves when complete. */ async function tryInitStorage(): Promise { if (global.mx_rage_initStoragePromise) { @@ -536,7 +534,7 @@ async function tryInitStorage(): Promise { /** * Get a recent snapshot of the logs, ready for attaching to a bug report * - * @return {LogEntry[]} list of log data + * @return list of log data */ export async function getLogsForReport(): Promise { if (!global.mx_rage_logger) { diff --git a/src/state/CallViewModel/CallNotificationLifecycle.ts b/src/state/CallViewModel/CallNotificationLifecycle.ts index 2a0bf2f1..d90f35ba 100644 --- a/src/state/CallViewModel/CallNotificationLifecycle.ts +++ b/src/state/CallViewModel/CallNotificationLifecycle.ts @@ -81,7 +81,7 @@ export interface Props { localUser: { deviceId: string; userId: string }; } /** - * @returns {callPickupState$, autoLeave$} + * @returns two observables: * `callPickupState$` The current call pickup state of the call. * - "unknown": The client has not yet sent the notification event. We don't know if it will because it first needs to send its own membership. * Then we can conclude if we were the first one to join or not. diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 6d28bc56..dc22db23 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -138,7 +138,16 @@ interface Props { * We want * - a publisher * - - * @param param0 + * @param props The properties required to create the local membership. + * @param props.scope The observable scope to use. + * @param props.connectionManager The connection manager to get connections from. + * @param props.createPublisherFactory Factory to create a publisher once we have a connection. + * @param props.joinMatrixRTC Callback to join the matrix RTC session once we have a transport. + * @param props.homeserverConnected The homeserver connected state. + * @param props.localTransport$ The local transport to use for publishing. + * @param props.logger The logger to use. + * @param props.muteStates The mute states for video and audio. + * @param props.matrixRTCSession The matrix RTC session to join. * @returns * - publisher: The handle to create tracks and publish them to the room. * - connected$: the current connection state. Including matrix server and livekit server connection. (only considering the livekit server we are using for our own media publication) @@ -676,9 +685,11 @@ interface EnterRTCSessionOptions { * - Delay events management * - Handles retries (fails only after several attempts) * - * @param rtcSession - * @param transport - * @param options + * @param rtcSession - The MatrixRTCSession to join. + * @param transport - The LivekitTransport to use for this session. + * @param options - Options for entering the RTC session. + * @param options.encryptMedia - Whether to encrypt media. + * @param options.matrixRTCMode - The Matrix RTC mode to use. * @throws If the widget could not send ElementWidgetActions.JoinCall action. */ // Exported for unit testing diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 3cb3bd04..27c53726 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -143,7 +143,7 @@ export class Publisher { this.logger.debug("createAndSetupTracks called"); const lkRoom = this.connection.livekitRoom; // Observe mute state changes and update LiveKit microphone/camera states accordingly - this.observeMuteStates(this.scope); + this.observeMuteStates(); // Check if audio and/or video is enabled. We only create tracks if enabled, // because it could prompt for permission, and we don't want to do that unnecessarily. @@ -356,10 +356,9 @@ export class Publisher { /** * Observe changes in the mute states and update the LiveKit room accordingly. - * @param scope * @private */ - private observeMuteStates(scope: ObservableScope): void { + private observeMuteStates(): void { const lkRoom = this.connection.livekitRoom; this.muteStates.audio.setHandler(async (enable) => { try { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index cf92e2a6..41dfe665 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -218,7 +218,7 @@ export class Connection { * * @param opts - Connection options {@link ConnectionOpts}. * - * @param logger + * @param logger - The logger to use. */ public constructor(opts: ConnectionOpts, logger: Logger) { this.logger = logger.getChild("[Connection]"); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 48e5b8d8..c3364059 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -43,11 +43,11 @@ export class ECConnectionFactory implements ConnectionFactory { * @param client - The OpenID client parts for authentication, needed to get openID and JWT tokens. * @param devices - Used for video/audio out/in capture options. * @param processorState$ - Effects like background blur (only for publishing connection?) - * @param livekitKeyProvider + * @param livekitKeyProvider - Optional key provider for end-to-end encryption. * @param controlledAudioDevices - Option to indicate whether audio output device is controlled externally (native mobile app). + * @param livekitRoomFactory - Optional factory function (for testing) to create LivekitRoom instances. If not provided, a default factory is used. * @param echoCancellation - Whether to enable echo cancellation for audio capture. * @param noiseSuppression - Whether to enable noise suppression for audio capture. - * @param livekitRoomFactory - Optional factory function (for testing) to create LivekitRoom instances. If not provided, a default factory is used. */ public constructor( private client: OpenIDClientParts, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index c1b4af59..101e34ed 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -76,9 +76,11 @@ export interface IConnectionManager { /** * Crete a `ConnectionManager` - * @param scope the observable scope used by this object. - * @param connectionFactory used to create new connections. - * @param _transportsSubscriptions$ A list of Behaviors each containing a LIST of LivekitTransport. + * @param props - Configuration object + * @param props.scope - The observable scope used by this object + * @param props.connectionFactory - Used to create new connections + * @param props.inputTransports$ - A list of Behaviors each containing a LIST of LivekitTransport. + * @param props.logger - The logger to use * Each of these behaviors can be interpreted as subscribed list of transports. * * Using `registerTransports` independent external modules can control what connections diff --git a/src/useAudioContext.tsx b/src/useAudioContext.tsx index 59334dda..4d08dde8 100644 --- a/src/useAudioContext.tsx +++ b/src/useAudioContext.tsx @@ -22,9 +22,12 @@ import * as controls from "./controls"; * Play a sound though a given AudioContext. Will take * care of connecting the correct buffer and gating * through gain. - * @param volume The volume to play at. * @param ctx The context to play through. * @param buffer The buffer to play. + * @param volume The volume to play at. + * @param stereoPan The stereo pan to apply. + * @param delayS Delay in seconds before starting playing. + * @param abort Optional AbortController that can be used to stop playback. * @returns A promise that resolves when the sound has finished playing. */ async function playSound( @@ -55,9 +58,11 @@ async function playSound( * Play a sound though a given AudioContext, looping until stopped. Will take * care of connecting the correct buffer and gating * through gain. - * @param volume The volume to play at. * @param ctx The context to play through. * @param buffer The buffer to play. + * @param volume The volume to play at. + * @param stereoPan The stereo pan to apply. + * @param delayS Delay in seconds between each loop. * @returns A function used to end the sound. This function will return a promise when the sound has stopped. */ function playSoundLooping( @@ -120,7 +125,7 @@ interface UseAudioContext { /** * Add an audio context which can be used to play * a set of preloaded sounds. - * @param props + * @param props The properties for the audio context. * @returns Either an instance that can be used to play sounds, or null if not ready. */ export function useAudioContext( diff --git a/src/utils/displayname.ts b/src/utils/displayname.ts index 5ab5de9b..bc49b29e 100644 --- a/src/utils/displayname.ts +++ b/src/utils/displayname.ts @@ -77,6 +77,13 @@ export function shouldDisambiguate( ); } +/** + * Calculates a display name for a member, optionally disambiguating it. + * @param member - The member to calculate the display name for. + * @param member.rawDisplayName - The raw display name of the member + * @param member.userId - The user ID of the member + * @param disambiguate - Whether to disambiguate the display name. + */ export function calculateDisplayName( member: { rawDisplayName?: string; userId: string }, disambiguate: boolean, diff --git a/src/utils/errors.ts b/src/utils/errors.ts index bb37754a..3ac2527a 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -57,9 +57,16 @@ export class ElementCallError extends Error { } } +/** + * Configuration problem due to no MatrixRTC backend/SFU is exposed via .well-known and no fallback configured. + */ export class MatrixRTCTransportMissingError extends ElementCallError { public domain: string; + /** + * Creates an instance of MatrixRTCTransportMissingError. + * @param domain - The domain where the MatrixRTC transport is missing. + */ public constructor(domain: string) { super( t("error.call_is_not_supported"), @@ -75,7 +82,11 @@ export class MatrixRTCTransportMissingError extends ElementCallError { } } +/** + * Error indicating that the connection to the call was lost and could not be re-established. + */ export class ConnectionLostError extends ElementCallError { + public constructor() { super( t("error.connection_lost"), @@ -86,7 +97,17 @@ export class ConnectionLostError extends ElementCallError { } } +/** + * Error indicating a failure in the membership manager causing the join call + * operation to fail. + */ export class MembershipManagerError extends ElementCallError { + + /** + * Creates an instance of MembershipManagerError. + * + * @param error - The underlying error that caused the membership manager failure. + */ public constructor(error: Error) { super( t("error.membership_manager"), @@ -98,7 +119,11 @@ export class MembershipManagerError extends ElementCallError { } } +/** + * Error indicating that end-to-end encryption is not supported in the current environment. + */ export class E2EENotSupportedError extends ElementCallError { + public constructor() { super( t("error.e2ee_unsupported"), @@ -109,7 +134,15 @@ export class E2EENotSupportedError extends ElementCallError { } } +/** + * Error indicating an unknown issue occurred during a call operation. + */ export class UnknownCallError extends ElementCallError { + + /** + * Creates an instance of UnknownCallError. + * @param error - The underlying error that caused the unknown issue. + */ public constructor(error: Error) { super( t("error.generic"), @@ -122,7 +155,14 @@ export class UnknownCallError extends ElementCallError { } } +/** + * Error indicating a failure to obtain an OpenID token. + */ export class FailToGetOpenIdToken extends ElementCallError { + /** + * Creates an instance of FailToGetOpenIdToken. + * @param error - The underlying error that caused the failure. + */ public constructor(error: Error) { super( t("error.generic"), @@ -135,7 +175,15 @@ export class FailToGetOpenIdToken extends ElementCallError { } } +/** + * Error indicating a failure to start publishing on a LiveKit connection. + */ export class FailToStartLivekitConnection extends ElementCallError { + + /** + * Creates an instance of FailToStartLivekitConnection. + * @param e - An optional error message providing additional context. + */ public constructor(e?: string) { super( t("error.failed_to_start_livekit"), @@ -146,6 +194,9 @@ export class FailToStartLivekitConnection extends ElementCallError { } } +/** + * Error indicating that a LiveKit's server has hit its track limits. + */ export class InsufficientCapacityError extends ElementCallError { public constructor() { super( @@ -157,6 +208,10 @@ export class InsufficientCapacityError extends ElementCallError { } } +/** + * Error indicating that room creation is restricted by the SFU. + * Only authorized users can create rooms, so the room must exist before connecting (done by the auth jwt service) + */ export class SFURoomCreationRestrictedError extends ElementCallError { public constructor() { super( diff --git a/src/utils/matrix.ts b/src/utils/matrix.ts index 0a2b5c1a..4e3ae3c3 100644 --- a/src/utils/matrix.ts +++ b/src/utils/matrix.ts @@ -188,7 +188,6 @@ function fullAliasFromRoomName(roomName: string, client: MatrixClient): string { * Applies some basic sanitisation to a room name that the user * has given us * @param input The room name from the user - * @param client A matrix client object */ export function sanitiseRoomNameInput(input: string): string { // check to see if the user has entered a fully qualified room @@ -304,8 +303,9 @@ export async function createRoom( /** * Returns an absolute URL to that will load Element Call with the given room * @param roomId ID of the room - * @param roomName Name of the room * @param encryptionSystem what encryption (or EncryptionSystem.Unencrypted) the room uses + * @param roomName Name of the room + * @param viaServers Optional list of servers to include as 'via' parameters in the URL */ export function getAbsoluteRoomUrl( roomId: string, @@ -321,8 +321,9 @@ export function getAbsoluteRoomUrl( /** * Returns a relative URL to that will load Element Call with the given room * @param roomId ID of the room - * @param roomName Name of the room * @param encryptionSystem what encryption (or EncryptionSystem.Unencrypted) the room uses + * @param roomName Name of the room + * @param viaServers Optional list of servers to include as 'via' parameters in the URL */ export function getRelativeRoomUrl( roomId: string, diff --git a/src/utils/media.ts b/src/utils/media.ts index cdd81aa7..3750aa4e 100644 --- a/src/utils/media.ts +++ b/src/utils/media.ts @@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details. /** * Finds a media device with label matching 'deviceName' * @param deviceName The label of the device to look for + * @param kind The kind of media device to look for * @param devices The list of devices to search * @returns A matching media device or undefined if no matching device was found */ diff --git a/src/utils/observable.ts b/src/utils/observable.ts index a6dafea3..9739353f 100644 --- a/src/utils/observable.ts +++ b/src/utils/observable.ts @@ -135,7 +135,6 @@ interface ItemHandle { * requested at a later time, and destroyed (have their scope ended) when the * key is no longer requested. * - * @param input$ The input value to be mapped. * @param generator A generator function yielding a tuple of keys and the * currently associated data for each item that it wants to exist. * @param factory A function constructing an individual item, given the item's key, diff --git a/yarn.lock b/yarn.lock index abb3ef95..401bb7c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2224,6 +2224,26 @@ __metadata: languageName: node linkType: hard +"@es-joy/jsdoccomment@npm:~0.76.0": + version: 0.76.0 + resolution: "@es-joy/jsdoccomment@npm:0.76.0" + dependencies: + "@types/estree": "npm:^1.0.8" + "@typescript-eslint/types": "npm:^8.46.0" + comment-parser: "npm:1.4.1" + esquery: "npm:^1.6.0" + jsdoc-type-pratt-parser: "npm:~6.10.0" + checksum: 10c0/8fe4edec7d60562787ea8c77193ebe8737a9e28ec3143d383506b63890d0ffd45a2813e913ad1f00f227cb10e3a1fb913e5a696b33d499dc564272ff1a6f3fdb + languageName: node + linkType: hard + +"@es-joy/resolve.exports@npm:1.2.0": + version: 1.2.0 + resolution: "@es-joy/resolve.exports@npm:1.2.0" + checksum: 10c0/7e4713471f5eccb17a925a12415a2d9e372a42376813a19f6abd9c35e8d01ab1403777265817da67c6150cffd4f558d9ad51e26a8de6911dad89d9cb7eedacd8 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/aix-ppc64@npm:0.25.1" @@ -4898,6 +4918,13 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/base62@npm:^1.0.0": + version: 1.0.0 + resolution: "@sindresorhus/base62@npm:1.0.0" + checksum: 10c0/9a14df0f058fdf4731c30f0f05728a4822144ee42236030039d7fa5a1a1072c2879feba8091fd4a17c8922d1056bc07bada77c31fddc3e15836fc05a266fd918 + languageName: node + linkType: hard + "@stylistic/eslint-plugin@npm:^3.0.0": version: 3.1.0 resolution: "@stylistic/eslint-plugin@npm:3.1.0" @@ -5196,7 +5223,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.8": +"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 @@ -5526,6 +5553,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:^8.46.0": + version: 8.51.0 + resolution: "@typescript-eslint/types@npm:8.51.0" + checksum: 10c0/eb3473d0bb71eb886438f35887b620ffadae7853b281752a40c73158aee644d136adeb82549be7d7c30f346fe888b2e979dff7e30e67b35377e8281018034529 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" @@ -5886,6 +5920,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.15.0": + version: 8.15.0 + resolution: "acorn@npm:8.15.0" + bin: + acorn: bin/acorn + checksum: 10c0/dec73ff59b7d6628a01eebaece7f2bdb8bb62b9b5926dcad0f8931f2b8b79c2be21f6c68ac095592adb5adb15831a3635d9343e6a91d028bbe85d564875ec3ec + languageName: node + linkType: hard + "acorn@npm:^8.9.0": version: 8.12.1 resolution: "acorn@npm:8.12.1" @@ -5995,6 +6038,13 @@ __metadata: languageName: node linkType: hard +"are-docs-informative@npm:^0.0.2": + version: 0.0.2 + resolution: "are-docs-informative@npm:0.0.2" + checksum: 10c0/f0326981bd699c372d268b526b170a28f2e1aec2cf99d7de0686083528427ecdf6ae41fef5d9988e224a5616298af747ad8a76e7306b0a7c97cc085a99636d60 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -7045,6 +7095,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:1.4.1": + version: 1.4.1 + resolution: "comment-parser@npm:1.4.1" + checksum: 10c0/d6c4be3f5be058f98b24f2d557f745d8fe1cc9eb75bebbdccabd404a0e1ed41563171b16285f593011f8b6a5ec81f564fb1f2121418ac5cbf0f49255bf0840dd + languageName: node + linkType: hard + "common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" @@ -7455,6 +7512,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + "decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" @@ -7825,6 +7894,7 @@ __metadata: eslint-config-prettier: "npm:^10.0.0" eslint-plugin-deprecate: "npm:^0.8.2" eslint-plugin-import: "npm:^2.26.0" + eslint-plugin-jsdoc: "npm:^61.5.0" eslint-plugin-jsx-a11y: "npm:^6.5.1" eslint-plugin-matrix-org: "npm:2.1.0" eslint-plugin-react: "npm:^7.29.4" @@ -8399,6 +8469,30 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-jsdoc@npm:^61.5.0": + version: 61.5.0 + resolution: "eslint-plugin-jsdoc@npm:61.5.0" + dependencies: + "@es-joy/jsdoccomment": "npm:~0.76.0" + "@es-joy/resolve.exports": "npm:1.2.0" + are-docs-informative: "npm:^0.0.2" + comment-parser: "npm:1.4.1" + debug: "npm:^4.4.3" + escape-string-regexp: "npm:^4.0.0" + espree: "npm:^10.4.0" + esquery: "npm:^1.6.0" + html-entities: "npm:^2.6.0" + object-deep-merge: "npm:^2.0.0" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.3" + spdx-expression-parse: "npm:^4.0.0" + to-valid-identifier: "npm:^1.0.0" + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/fabb04f6efe58a167a0839d3c05676a76080c6e91d98a269fa768c1bfd835aa0ded5822d400da2874216177044d2d227ebe241d73e923f3fe1c08bafd19cfd3d + languageName: node + linkType: hard + "eslint-plugin-jsx-a11y@npm:^6.5.1": version: 6.10.2 resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" @@ -8633,6 +8727,17 @@ __metadata: languageName: node linkType: hard +"espree@npm:^10.4.0": + version: 10.4.0 + resolution: "espree@npm:10.4.0" + dependencies: + acorn: "npm:^8.15.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/c63fe06131c26c8157b4083313cb02a9a54720a08e21543300e55288c40e06c3fc284bdecf108d3a1372c5934a0a88644c98714f38b6ae8ed272b40d9ea08d6b + languageName: node + linkType: hard + "espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" @@ -9526,6 +9631,13 @@ __metadata: languageName: node linkType: hard +"html-entities@npm:^2.6.0": + version: 2.6.0 + resolution: "html-entities@npm:2.6.0" + checksum: 10c0/7c8b15d9ea0cd00dc9279f61bab002ba6ca8a7a0f3c36ed2db3530a67a9621c017830d1d2c1c65beb9b8e3436ea663e9cf8b230472e0e413359399413b27c8b7 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -10295,6 +10407,13 @@ __metadata: languageName: node linkType: hard +"jsdoc-type-pratt-parser@npm:~6.10.0": + version: 6.10.0 + resolution: "jsdoc-type-pratt-parser@npm:6.10.0" + checksum: 10c0/8ea395df0cae0e41d4bdba5f8d81b8d3e467fe53d1e4182a5d4e653235a5f17d60ed137343d68dbc74fa10e767f1c58fb85b1f6d5489c2cf16fc7216cc6d3e1a + languageName: node + linkType: hard + "jsdom@npm:^26.0.0": version: 26.1.0 resolution: "jsdom@npm:26.1.0" @@ -11250,6 +11369,13 @@ __metadata: languageName: node linkType: hard +"object-deep-merge@npm:^2.0.0": + version: 2.0.0 + resolution: "object-deep-merge@npm:2.0.0" + checksum: 10c0/69e8741131ad49fa8720fb96007a3c82dca1119b5d874151d2ecbcc3b44ccd46e8553c7a30b0abcba752c099ba361bbba97f33a68c9ae54c57eed7be116ffc97 + languageName: node + linkType: hard + "object-inspect@npm:^1.13.3": version: 1.13.3 resolution: "object-inspect@npm:1.13.3" @@ -11563,6 +11689,15 @@ __metadata: languageName: node linkType: hard +"parse-imports-exports@npm:^0.2.4": + version: 0.2.4 + resolution: "parse-imports-exports@npm:0.2.4" + dependencies: + parse-statements: "npm:1.0.11" + checksum: 10c0/51b729037208abdf65c4a1f8e9ed06f4e7ccd907c17c668a64db54b37d95bb9e92081f8b16e4133e14102af3cb4e89870975b6ad661b4d654e9ec8f4fb5c77d6 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11575,6 +11710,13 @@ __metadata: languageName: node linkType: hard +"parse-statements@npm:1.0.11": + version: 1.0.11 + resolution: "parse-statements@npm:1.0.11" + checksum: 10c0/48960e085019068a5f5242e875fd9d21ec87df2e291acf5ad4e4887b40eab6929a8c8d59542acb85a6497e870c5c6a24f5ab7f980ef5f907c14cc5f7984a93f3 + languageName: node + linkType: hard + "parse5-htmlparser2-tree-adapter@npm:^7.0.0": version: 7.1.0 resolution: "parse5-htmlparser2-tree-adapter@npm:7.1.0" @@ -12820,6 +12962,13 @@ __metadata: languageName: node linkType: hard +"reserved-identifiers@npm:^1.0.0": + version: 1.2.0 + resolution: "reserved-identifiers@npm:1.2.0" + checksum: 10c0/b82651b12e6c608e80463c3753d275bc20fd89294d0415f04e670aeec3611ae3582ddc19e8fedd497e7d0bcbfaddab6a12823ec86e855b1e6a245e0a734eb43d + languageName: node + linkType: hard + "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -13280,6 +13429,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.7.3 + resolution: "semver@npm:7.7.3" + bin: + semver: bin/semver.js + checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -13548,6 +13706,16 @@ __metadata: languageName: node linkType: hard +"spdx-expression-parse@npm:^4.0.0": + version: 4.0.0 + resolution: "spdx-expression-parse@npm:4.0.0" + dependencies: + spdx-exceptions: "npm:^2.1.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10c0/965c487e77f4fb173f1c471f3eef4eb44b9f0321adc7f93d95e7620da31faa67d29356eb02523cd7df8a7fc1ec8238773cdbf9e45bd050329d2b26492771b736 + languageName: node + linkType: hard + "spdx-license-ids@npm:^3.0.0": version: 3.0.20 resolution: "spdx-license-ids@npm:3.0.20" @@ -14055,6 +14223,16 @@ __metadata: languageName: node linkType: hard +"to-valid-identifier@npm:^1.0.0": + version: 1.0.0 + resolution: "to-valid-identifier@npm:1.0.0" + dependencies: + "@sindresorhus/base62": "npm:^1.0.0" + reserved-identifiers: "npm:^1.0.0" + checksum: 10c0/569b49f43b5aaaa20677e67f0f1cdcff344855149934cfb80c793c7ac7c30e191b224bc81cab40fb57641af9ca73795c78053c164a2addc617671e2d22c13a4a + languageName: node + linkType: hard + "toggle-selection@npm:^1.0.6": version: 1.0.6 resolution: "toggle-selection@npm:1.0.6"