diff --git a/README.md b/README.md index 1ac4b30..1c948f8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ntcore-ts-client -A TypeScript library for communication over [WPILib's NetworkTables 4.0 protocol](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc). +A TypeScript library for communication over [WPILib's NetworkTables 4.1 protocol](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc). ## Features @@ -8,6 +8,7 @@ A TypeScript library for communication over [WPILib's NetworkTables 4.0 protocol - Togglable auto-reconnect - Callbacks for new data on subscriptions - Callbacks for connection listeners +- Wildcard prefix listeners for multiple topics - Retrying for messages queued during a connection loss - On-the-fly server switching with resubscribing and republishing - Generic types for Topics @@ -84,8 +85,7 @@ Once a topic has been created, it can be used as a subscriber: ```typescript subscribe( - callback: (_: T | null) => void, - immediateNotify = false, + callback: (value: T | null, params: AnnounceMessageParams) => void, options: SubscribeOptions = {}, id?: number, save = true @@ -112,7 +112,12 @@ const gyroTopic = ntcore.createTopic('/MyTable/Gyro', NetworkTablesTypeI // Subscribe and immediately call the callback with the current value gyroTopic.subscribe((value) => { console.log(`Got Gyro Value: ${value}`); -}, true); +}); + +// Or you can use the topic's announce parameters to get more info, like the topic ID +gyroTopic.subscribe((value, params) => { + console.log(`Got Gyro Value: ${value} at from topic id ${params.id}`); +}); ``` Or a publisher for an auto mode: @@ -133,7 +138,70 @@ await autoModeTopic.publish(); autoModeTopic.setValue('25 Ball Auto and Climb'); ``` -### More info +### Subscribing to Multiple Topics + +You can also subscribe to multiple topics by using a "wildcard" through creating a prefix topic. + +For example, here's a subscription for an Accelerometer with topics `/MyTable/Accelerometer/X`, `/MyTable/Accelerometer/Y`, and `/MyTable/Accelerometer/Z`: + +```typescript +import { NetworkTables } from 'ntcore-ts-client'; + +// Get or create the NT client instance +const ntcore = NetworkTables.getInstanceByTeam(973); + +// Create the accelerator topic +const accelerometerTopic = ntcore.createPrefixTopic('/MyTable/Accelerometer/'); + +let x, y, z; + +// Subscribe to all topics under the prefix /MyTable/Accelerometer/ +accelerometerTopic.subscribe((value, params) => { + console.log(`Got Accelerometer Value: ${value} from topic ${params.name}`); // i.e. Got Accelerometer Value: 9.81 from topic /MyTable/Accelerometer/Y + + // You can also use the topic name to determine which value to set + if (params.name.endsWith('X')) { + x = value; + } else if (params.name.endsWith('Y')) { + y = value; + } else if (params.name.endsWith('Z')) { + z = value; + } + + // Since there can be many types in subtopics, + // you can use the type information for other checks... + if (params.type === 'int') { + console.warn('Hmm... the accelerometer seems low precision'); + } else if (params.type === 'double') { + console.log('The accelerometer is high precision'); + } +}); + +// x, y, and z will be updated as new values come in +``` + +### Subscribing to All Topics + +You can also subscribe to all topics by doing the above, but with a prefix of `/`. + +For example, here's a subscription for all topics: + +```typescript +import { NetworkTables } from 'ntcore-ts-client'; + +// Get or create the NT client instance +const ntcore = NetworkTables.getInstanceByTeam(973); + +// Create a prefix for all topics +const allTopics = ntcore.createPrefixTopic('/'); + +// Subscribe to all topics +allTopics.subscribe((value, params) => { + console.log(`Got Value: ${value} from topic ${params.name}`); +}); +``` + +### More Info The API for Topics is much more exhaustive than this quick example. Feel free to view the docs at [https://ntcore.chrislawson.dev](https://ntcore.chrislawson.dev). diff --git a/apps/example-client/.eslintrc.json b/apps/example-client/.eslintrc.json new file mode 100644 index 0000000..9b37187 --- /dev/null +++ b/apps/example-client/.eslintrc.json @@ -0,0 +1,20 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": { + "no-console": "off" + } + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + } + ] +} diff --git a/apps/example-client/project.json b/apps/example-client/project.json new file mode 100644 index 0000000..6b22118 --- /dev/null +++ b/apps/example-client/project.json @@ -0,0 +1,61 @@ +{ + "name": "example-client", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/example-client/src", + "projectType": "application", + "tags": [], + "targets": { + "build": { + "executor": "@nx/esbuild:esbuild", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "platform": "node", + "outputPath": "dist/apps/example-client", + "format": ["cjs"], + "bundle": false, + "main": "apps/example-client/src/main.ts", + "tsConfig": "apps/example-client/tsconfig.app.json", + "assets": ["apps/example-client/src/assets"], + "generatePackageJson": true, + "esbuildOptions": { + "sourcemap": true, + "outExtension": { + ".js": ".js" + } + } + }, + "configurations": { + "development": {}, + "production": { + "esbuildOptions": { + "sourcemap": false, + "outExtension": { + ".js": ".js" + } + } + } + } + }, + "serve": { + "executor": "@nx/js:node", + "defaultConfiguration": "development", + "dependsOn": ["build"], + "options": { + "buildTarget": "example-client:build", + "runBuildTargetDependencies": false + }, + "configurations": { + "development": { + "buildTarget": "example-client:build:development" + }, + "production": { + "buildTarget": "example-client:build:production" + } + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/apps/example-client/src/main.ts b/apps/example-client/src/main.ts new file mode 100644 index 0000000..b893907 --- /dev/null +++ b/apps/example-client/src/main.ts @@ -0,0 +1,88 @@ +// eslint-disable-next-line @nx/enforce-module-boundaries +import { NetworkTables, NetworkTablesTypeInfos } from '../../../packages/ntcore-ts-client/src'; + +// Get or create the NT client instance +const ntcore = NetworkTables.getInstanceByURI('localhost'); + +// ------------------------------------------------ // +// Example of using a topic to subscribe to a value // +// ------------------------------------------------ // + +// Create the gyro topic +const gyroTopic = ntcore.createTopic('/MyTable/Gyro', NetworkTablesTypeInfos.kDouble); + +// Subscribe and immediately call the callback with the current value +gyroTopic.subscribe((value) => { + console.log(`Got Gyro Value: ${value}`); +}); + +// Or you can use the topic's announce parameters to get more info, like the topic ID +gyroTopic.subscribe((value, params) => { + console.log(`Got Gyro Value: ${value} at from topic id ${params.id}`); +}); + +// ---------------------------------------------- // +// Example of using a topic to publish to a value // +// --------------------------------------------- + +// Create the autoMode topic w/ a default return value of 'No Auto' +(async () => { + const autoModeTopic = ntcore.createTopic('/MyTable/autoMode', NetworkTablesTypeInfos.kString, 'No Auto'); + + // Make us the publisher + await autoModeTopic.publish(); + + // Set a new value, this will error if we aren't the publisher! + autoModeTopic.setValue('25 Ball Auto and Climb'); +})(); + +// --------------------------------------------------------------- // +// Example of using a prefix topic to subscribe to multiple topics // +// --------------------------------------------------------------- // + +// Create the accelerator topic +const accelerometerTopic = ntcore.createPrefixTopic('/MyTable/Accelerometer/'); + +let x, y, z: any; + +// Subscribe to all topics under the prefix /MyTable/Accelerometer/ +accelerometerTopic.subscribe((value, params) => { + console.log(`Got Accelerometer Value: ${value} from topic ${params.name}`); // i.e. Got Accelerometer Value: 9.81 from topic /MyTable/Accelerometer/Y + + // You can also use the topic name to determine which value to set + if (params.name.endsWith('X')) { + x = value; + } else if (params.name.endsWith('Y')) { + y = value; + } else if (params.name.endsWith('Z')) { + z = value; + } + + // Since there can be THAT many different types in subtopics, + // you can use the type information for other checks... + if (params.type === 'int') { + console.warn('Hmm... the accelerometer seems low precision'); + } else if (params.type === 'double') { + console.log('The accelerometer is high precision'); + + const typedX = x as number; + const typedY = y as number; + const typedZ = z as number; + + console.log(`Latest update: X: ${typedX}, Y: ${typedY}, Z: ${typedZ}`); + } +}); + +// x, y, and z will be updated as new values come in + +// ---------------------------------------------------------- // +// Example of using a prefix topic to subscribe to all topics // +// ---------------------------------------------------------- // + +// Create a prefix for all topics +const allTopics = ntcore.createPrefixTopic(''); + +// Sub scribe to all topics +allTopics.subscribe((value, params) => { + console.log(`Got Value: ${value} from topic ${params.name}`); +}); diff --git a/apps/example-client/tsconfig.app.json b/apps/example-client/tsconfig.app.json new file mode 100644 index 0000000..1a5e940 --- /dev/null +++ b/apps/example-client/tsconfig.app.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "ESNext", + "types": ["node"] + }, + "include": ["src/main.ts"] +} diff --git a/apps/example-client/tsconfig.json b/apps/example-client/tsconfig.json new file mode 100644 index 0000000..3685ac7 --- /dev/null +++ b/apps/example-client/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ], + "compilerOptions": { + "esModuleInterop": true + } +} diff --git a/docs/assets/search.js b/docs/assets/search.js index 4b45b03..c238df6 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/docs/classes/NetworkTables.html b/docs/classes/NetworkTables.html index 97469ef..f1b3ea6 100644 --- a/docs/classes/NetworkTables.html +++ b/docs/classes/NetworkTables.html @@ -1,7 +1,8 @@ NetworkTables | ntcore-ts-client

NetworkTables class for interacting with NetworkTables over a WebSocket connection.

-

Accessors

Accessors

Methods

Methods

  • Adds a listener for robot connection status updates.

    Parameters

    • callback: (_: boolean) => void

      The callback to call when the connection status changes.

    • OptionalimmediateNotify: boolean

      Whether to immediately notify the callback of the current connection status.

    Returns () => void

    A function to remove the listener.

    -
  • Creates a new topic.

    Type Parameters

    • T extends string | number | boolean | string[] | ArrayBuffer | boolean[] | number[]

    Parameters

    • name: string

      The name of the topic.

    • typeInfo: NetworkTablesTypeInfo

      The type information of the topic.

    • OptionaldefaultValue: T

      The default value of the topic.

    Returns NetworkTablesTopic<T>

    The topic.

    -
  • Creates a new NetworkTables instance if it does not exist.

    Parameters

    • team: number

      The team number of the robot.

    • port: number = 5810

      The port to connect to the robot on. Defaults to 5810.

    Returns NetworkTables

    The NetworkTables instance.

    Error if the team number is not provided.

    -
  • Creates a new NetworkTables instance if it does not exist.

    +
+
diff --git a/docs/classes/NetworkTablesTopic.html b/docs/classes/NetworkTablesTopic.html index 1969642..9395a9e 100644 --- a/docs/classes/NetworkTablesTopic.html +++ b/docs/classes/NetworkTablesTopic.html @@ -1,24 +1,30 @@ -NetworkTablesTopic | ntcore-ts-client

Class NetworkTablesTopic<T>

Type Parameters

Constructors

Accessors

announced -id -lastChangedTime -name +NetworkTablesTopic | ntcore-ts-client

Class NetworkTablesTopic<T>

Type Parameters

Hierarchy

  • NetworkTablesBaseTopic<T>
    • NetworkTablesTopic

Constructors

  • Creates a new topic. This should only be done after the base NTCore client has been initialized.

    @@ -26,56 +32,56 @@
  • name: string

    The name of the topic.

  • typeInfo: NetworkTablesTypeInfo

    The type info for the topic.

  • OptionaldefaultValue: T

    The default value for the topic.

    -

Returns NetworkTablesTopic<T>

Accessors

  • get announced(): boolean
  • Whether the topic has been announced.

    +

Returns NetworkTablesTopic<T>

Properties

_announceParams:
    | null
    | {
        id: number;
        name: string;
        properties: { cached?: boolean; persistent?: boolean; retained?: boolean };
        pubuid?: number;
        type:
            | "string"
            | "boolean"
            | "float"
            | "double"
            | "int"
            | "json"
            | "raw"
            | "rpc"
            | "msgpack"
            | "protobuf"
            | "boolean[]"
            | "double[]"
            | "int[]"
            | "float[]"
            | "string[]";
    }
_lastChangedTime?: number
client: PubSubClient
type: "regular" = 'regular'

Accessors

  • get subscribers(): Map<
        number,
        {
            callback: (_: null | T) => void;
            immediateNotify: boolean;
            options: {
                all?: boolean;
                periodic?: number;
                prefix?: boolean;
                topicsonly?: boolean;
            };
        },
    >
  • Gets the subscribers to the topic.

    -

    Returns Map<
        number,
        {
            callback: (_: null | T) => void;
            immediateNotify: boolean;
            options: {
                all?: boolean;
                periodic?: number;
                prefix?: boolean;
                topicsonly?: boolean;
            };
        },
    >

    The subscribers to the topic.

    -
  • get subscribers(): Map<
        number,
        {
            callback: CallbackFn<T>;
            options: {
                all?: boolean;
                periodic?: number;
                prefix?: boolean;
                topicsonly?: boolean;
            };
        },
    >
  • Gets the subscribers to the topic.

    +

    Returns Map<
        number,
        {
            callback: CallbackFn<T>;
            options: {
                all?: boolean;
                periodic?: number;
                prefix?: boolean;
                topicsonly?: boolean;
            };
        },
    >

    The subscribers to the topic.

    +

Methods

  • Marks the topic as announced. This should only be called by the PubSubClient.

    -

    Parameters

    • id: number

      The ID of the topic.

      -
    • Optionalpubuid: number

      The UID of the publisher.

      -

    Returns void

Methods

  • Marks the topic as announced. This should only be called by the PubSubClient.

    +

    Parameters

    • params: {
          id: number;
          name: string;
          properties: { cached?: boolean; persistent?: boolean; retained?: boolean };
          pubuid?: number;
          type:
              | "string"
              | "boolean"
              | "float"
              | "double"
              | "int"
              | "json"
              | "raw"
              | "rpc"
              | "msgpack"
              | "protobuf"
              | "boolean[]"
              | "double[]"
              | "int[]"
              | "float[]"
              | "string[]";
      }

      The parameters of the announcement.

      +

    Returns void

  • Publishes the topic.

    Parameters

    • properties: { cached?: boolean; persistent?: boolean; retained?: boolean } = {}

      The properties to publish the topic with.

      -
    • Optionalid: number

      The UID of the publisher.

      +
    • Optionalid: number

      The UID of the publisher. You must verify that the ID is not already in use.

    Returns Promise<
        | void
        | {
            method: "announce";
            params: {
                id: number;
                name: string;
                properties: {
                    cached?: boolean;
                    persistent?: boolean;
                    retained?: boolean;
                };
                pubuid?: number;
                type: | "string"
                | "boolean"
                | "float"
                | "double"
                | "int"
                | "json"
                | "raw"
                | "rpc"
                | "msgpack"
                | "protobuf"
                | "boolean[]"
                | "double[]"
                | "int[]"
                | "float[]"
                | "string[]";
            };
        },
    >

    A promise that resolves when the topic is published.

    -
  • Republishes the topic.

    Parameters

    • client: PubSubClient

      The client to republish with.

    Returns Promise<
        | void
        | {
            method: "announce";
            params: {
                id: number;
                name: string;
                properties: {
                    cached?: boolean;
                    persistent?: boolean;
                    retained?: boolean;
                };
                pubuid?: number;
                type: | "string"
                | "boolean"
                | "float"
                | "double"
                | "int"
                | "json"
                | "raw"
                | "rpc"
                | "msgpack"
                | "protobuf"
                | "boolean[]"
                | "double[]"
                | "int[]"
                | "float[]"
                | "string[]";
            };
        },
    >

    A promise that resolves when the topic is republished.

    -
  • Sets the properties of the topic.

    +

Returns void

  • Sets the properties of the topic.

    Parameters

    • Optionalpersistent: boolean

      If true, the last set value will be periodically saved to persistent storage on the server and be restored during server startup. Topics with this property set to true will not be deleted by the server when the last publisher stops publishing.

    • Optionalretained: boolean

      Topics with this property set to true will not be deleted by the server when the last publisher stops publishing.

    Returns Promise<{ method: "properties"; params: { ack: boolean; name: string } }>

    The server's response.

    -
  • Creates a new subscriber. This should only be called by the PubSubClient.

    -

    Parameters

    • callback: (_: null | T) => void

      The callback to call when the topic value changes.

      -
    • immediateNotify: boolean = false

      Whether to immediately notify the subscriber of the current value.

      -
    • options: { all?: boolean; periodic?: number; prefix?: boolean; topicsonly?: boolean } = {}

      The options for the subscriber.

      -
    • Optionalid: number

      The UID of the subscriber.

      +

    Returns void

  • Creates a new subscriber.

    +

    Parameters

    • callback: CallbackFn<T>

      The callback to call when the topic value changes.

      +
    • options: Omit<
          {
              all?: boolean;
              periodic?: number;
              prefix?: boolean;
              topicsonly?: boolean;
          },
          "prefix",
      > = {}

      The options for the subscriber.

      +
    • Optionalid: number

      The UID of the subscriber. You must verify that the ID is not already in use.

    • save: boolean = true

      Whether to save the subscriber.

    Returns number

    The UID of the subscriber.

    -
  • Removes a subscriber

    Parameters

    • subuid: number

      The UID of the subscriber.

    • removeCallback: boolean = true

      Whether to remove the callback. Leave this as true unless you know what you're doing.

      -

    Returns void

  • Updates the value of the topic. +

Returns void

  • Updates the value of the topic. This should only be called by the PubSubClient.

    Parameters

    • value: T

      The value to update.

    • lastChangedTime: number

      The server time of the last value change.

      -

    Returns void

+

Returns void

diff --git a/docs/classes/NetworkTablesTypeInfos.html b/docs/classes/NetworkTablesTypeInfos.html index ed7ad63..c2cb678 100644 --- a/docs/classes/NetworkTablesTypeInfos.html +++ b/docs/classes/NetworkTablesTypeInfos.html @@ -1,4 +1,4 @@ -NetworkTablesTypeInfos | ntcore-ts-client

Class NetworkTablesTypeInfos

Constructors

constructor +NetworkTablesTypeInfos | ntcore-ts-client

Class NetworkTablesTypeInfos

Constructors

Properties

kArrayBuffer: NetworkTablesTypeInfo = ...
kBoolean: NetworkTablesTypeInfo = ...
kBooleanArray: NetworkTablesTypeInfo = ...
kDouble: NetworkTablesTypeInfo = ...
kDoubleArray: NetworkTablesTypeInfo = ...
kInteger: NetworkTablesTypeInfo = ...
kIntegerArray: NetworkTablesTypeInfo = ...
kString: NetworkTablesTypeInfo = ...
kStringArray: NetworkTablesTypeInfo = ...
+

Constructors

Properties

kArrayBuffer: NetworkTablesTypeInfo = ...
kBoolean: NetworkTablesTypeInfo = ...
kBooleanArray: NetworkTablesTypeInfo = ...
kDouble: NetworkTablesTypeInfo = ...
kDoubleArray: NetworkTablesTypeInfo = ...
kInteger: NetworkTablesTypeInfo = ...
kIntegerArray: NetworkTablesTypeInfo = ...
kString: NetworkTablesTypeInfo = ...
kStringArray: NetworkTablesTypeInfo = ...
diff --git a/docs/interfaces/BinaryMessageData.html b/docs/interfaces/BinaryMessageData.html index e51fc4a..5dc5e44 100644 --- a/docs/interfaces/BinaryMessageData.html +++ b/docs/interfaces/BinaryMessageData.html @@ -1,5 +1,5 @@ -BinaryMessageData | ntcore-ts-client

Interface BinaryMessageData

interface BinaryMessageData {
    serverTime: number;
    topicId: number;
    typeInfo: NetworkTablesTypeInfos;
    value:
        | string
        | number
        | boolean
        | string[]
        | ArrayBuffer
        | boolean[]
        | number[];
}

Properties

serverTime +BinaryMessageData | ntcore-ts-client

Interface BinaryMessageData

interface BinaryMessageData {
    serverTime: number;
    topicId: number;
    typeInfo: NetworkTablesTypeInfos;
    value:
        | string
        | number
        | boolean
        | string[]
        | ArrayBuffer
        | boolean[]
        | number[];
}

Properties

serverTime: number
topicId: number
value: string | number | boolean | string[] | ArrayBuffer | boolean[] | number[]
+

Properties

serverTime: number
topicId: number
value: string | number | boolean | string[] | ArrayBuffer | boolean[] | number[]
diff --git a/docs/types/AnnounceMessage.html b/docs/types/AnnounceMessage.html index d2dd1a2..56dc42a 100644 --- a/docs/types/AnnounceMessage.html +++ b/docs/types/AnnounceMessage.html @@ -1 +1 @@ -AnnounceMessage | ntcore-ts-client

Type Alias AnnounceMessage

AnnounceMessage: z.infer<typeof announceMessageSchema>
+AnnounceMessage | ntcore-ts-client

Type Alias AnnounceMessage

AnnounceMessage: z.infer<typeof announceMessageSchema>
diff --git a/docs/types/AnnounceMessageParams.html b/docs/types/AnnounceMessageParams.html index b339585..2dae547 100644 --- a/docs/types/AnnounceMessageParams.html +++ b/docs/types/AnnounceMessageParams.html @@ -1 +1 @@ -AnnounceMessageParams | ntcore-ts-client

Type Alias AnnounceMessageParams

AnnounceMessageParams: AnnounceMessage["params"]
+AnnounceMessageParams | ntcore-ts-client

Type Alias AnnounceMessageParams

AnnounceMessageParams: AnnounceMessage["params"]
diff --git a/docs/types/BinaryMessage.html b/docs/types/BinaryMessage.html index 1788ae4..53d29c1 100644 --- a/docs/types/BinaryMessage.html +++ b/docs/types/BinaryMessage.html @@ -1 +1 @@ -BinaryMessage | ntcore-ts-client

Type Alias BinaryMessage

BinaryMessage: z.infer<typeof msgPackSchema>
+BinaryMessage | ntcore-ts-client

Type Alias BinaryMessage

BinaryMessage: z.infer<typeof msgPackSchema>
diff --git a/docs/types/Message.html b/docs/types/Message.html index c17547c..ef7dfba 100644 --- a/docs/types/Message.html +++ b/docs/types/Message.html @@ -1 +1 @@ -Message | ntcore-ts-client
+Message | ntcore-ts-client
diff --git a/docs/types/NetworkTablesTypeInfo.html b/docs/types/NetworkTablesTypeInfo.html index a7622c8..c8dcc64 100644 --- a/docs/types/NetworkTablesTypeInfo.html +++ b/docs/types/NetworkTablesTypeInfo.html @@ -1 +1 @@ -NetworkTablesTypeInfo | ntcore-ts-client

Type Alias NetworkTablesTypeInfo

NetworkTablesTypeInfo: [TypeNum, TypeString]
+NetworkTablesTypeInfo | ntcore-ts-client

Type Alias NetworkTablesTypeInfo

NetworkTablesTypeInfo: [TypeNum, TypeString]
diff --git a/docs/types/NetworkTablesTypes.html b/docs/types/NetworkTablesTypes.html index 5d1aae6..22b200c 100644 --- a/docs/types/NetworkTablesTypes.html +++ b/docs/types/NetworkTablesTypes.html @@ -1 +1 @@ -NetworkTablesTypes | ntcore-ts-client

Type Alias NetworkTablesTypes

NetworkTablesTypes: z.infer<typeof msgPackValueSchema>
+NetworkTablesTypes | ntcore-ts-client

Type Alias NetworkTablesTypes

NetworkTablesTypes: z.infer<typeof msgPackValueSchema>
diff --git a/docs/types/PropertiesMessage.html b/docs/types/PropertiesMessage.html index cda65cd..364966c 100644 --- a/docs/types/PropertiesMessage.html +++ b/docs/types/PropertiesMessage.html @@ -1 +1 @@ -PropertiesMessage | ntcore-ts-client

Type Alias PropertiesMessage

PropertiesMessage: z.infer<typeof propertiesMessageSchema>
+PropertiesMessage | ntcore-ts-client

Type Alias PropertiesMessage

PropertiesMessage: z.infer<typeof propertiesMessageSchema>
diff --git a/docs/types/PropertiesMessageParams.html b/docs/types/PropertiesMessageParams.html index 748e75e..651dd24 100644 --- a/docs/types/PropertiesMessageParams.html +++ b/docs/types/PropertiesMessageParams.html @@ -1 +1 @@ -PropertiesMessageParams | ntcore-ts-client

Type Alias PropertiesMessageParams

PropertiesMessageParams: PropertiesMessage["params"]
+PropertiesMessageParams | ntcore-ts-client

Type Alias PropertiesMessageParams

PropertiesMessageParams: PropertiesMessage["params"]
diff --git a/docs/types/PublishMessage.html b/docs/types/PublishMessage.html index df77c8d..98f2b3b 100644 --- a/docs/types/PublishMessage.html +++ b/docs/types/PublishMessage.html @@ -1 +1 @@ -PublishMessage | ntcore-ts-client

Type Alias PublishMessage

PublishMessage: z.infer<typeof publishMessageSchema>
+PublishMessage | ntcore-ts-client

Type Alias PublishMessage

PublishMessage: z.infer<typeof publishMessageSchema>
diff --git a/docs/types/PublishMessageParams.html b/docs/types/PublishMessageParams.html index 225d31d..63e2e0c 100644 --- a/docs/types/PublishMessageParams.html +++ b/docs/types/PublishMessageParams.html @@ -1 +1 @@ -PublishMessageParams | ntcore-ts-client

Type Alias PublishMessageParams

PublishMessageParams: PublishMessage["params"]
+PublishMessageParams | ntcore-ts-client

Type Alias PublishMessageParams

PublishMessageParams: PublishMessage["params"]
diff --git a/docs/types/SetPropertiesMessage.html b/docs/types/SetPropertiesMessage.html index 302d4bb..29d8302 100644 --- a/docs/types/SetPropertiesMessage.html +++ b/docs/types/SetPropertiesMessage.html @@ -1 +1 @@ -SetPropertiesMessage | ntcore-ts-client

Type Alias SetPropertiesMessage

SetPropertiesMessage: z.infer<typeof setPropertiesMessageSchema>
+SetPropertiesMessage | ntcore-ts-client

Type Alias SetPropertiesMessage

SetPropertiesMessage: z.infer<typeof setPropertiesMessageSchema>
diff --git a/docs/types/SetPropertiesMessageParams.html b/docs/types/SetPropertiesMessageParams.html index ad5dcac..15b0f9c 100644 --- a/docs/types/SetPropertiesMessageParams.html +++ b/docs/types/SetPropertiesMessageParams.html @@ -1 +1 @@ -SetPropertiesMessageParams | ntcore-ts-client

Type Alias SetPropertiesMessageParams

SetPropertiesMessageParams: SetPropertiesMessage["params"]
+SetPropertiesMessageParams | ntcore-ts-client

Type Alias SetPropertiesMessageParams

SetPropertiesMessageParams: SetPropertiesMessage["params"]
diff --git a/docs/types/SubscribeMessage.html b/docs/types/SubscribeMessage.html index b5d7f75..e14ae59 100644 --- a/docs/types/SubscribeMessage.html +++ b/docs/types/SubscribeMessage.html @@ -1 +1 @@ -SubscribeMessage | ntcore-ts-client

Type Alias SubscribeMessage

SubscribeMessage: z.infer<typeof subscribeMessageSchema>
+SubscribeMessage | ntcore-ts-client

Type Alias SubscribeMessage

SubscribeMessage: z.infer<typeof subscribeMessageSchema>
diff --git a/docs/types/SubscribeMessageParams.html b/docs/types/SubscribeMessageParams.html index 7cc6f4c..729d1d2 100644 --- a/docs/types/SubscribeMessageParams.html +++ b/docs/types/SubscribeMessageParams.html @@ -1 +1 @@ -SubscribeMessageParams | ntcore-ts-client

Type Alias SubscribeMessageParams

SubscribeMessageParams: SubscribeMessage["params"]
+SubscribeMessageParams | ntcore-ts-client

Type Alias SubscribeMessageParams

SubscribeMessageParams: SubscribeMessage["params"]
diff --git a/docs/types/SubscribeOptions.html b/docs/types/SubscribeOptions.html index 9c96b18..c2cb7ac 100644 --- a/docs/types/SubscribeOptions.html +++ b/docs/types/SubscribeOptions.html @@ -1 +1 @@ -SubscribeOptions | ntcore-ts-client

Type Alias SubscribeOptions

SubscribeOptions: z.infer<typeof subscriptionOptionsSchema>
+SubscribeOptions | ntcore-ts-client

Type Alias SubscribeOptions

SubscribeOptions: z.infer<typeof subscriptionOptionsSchema>
diff --git a/docs/types/TopicProperties.html b/docs/types/TopicProperties.html index d9ef598..310daf9 100644 --- a/docs/types/TopicProperties.html +++ b/docs/types/TopicProperties.html @@ -1 +1 @@ -TopicProperties | ntcore-ts-client

Type Alias TopicProperties

TopicProperties: z.infer<typeof topicPropertiesSchema>
+TopicProperties | ntcore-ts-client

Type Alias TopicProperties

TopicProperties: z.infer<typeof topicPropertiesSchema>
diff --git a/docs/types/TypeNum.html b/docs/types/TypeNum.html index e6def77..6e7925b 100644 --- a/docs/types/TypeNum.html +++ b/docs/types/TypeNum.html @@ -1 +1 @@ -TypeNum | ntcore-ts-client

Type Alias TypeNum

TypeNum: z.infer<typeof typeNumSchema>
+TypeNum | ntcore-ts-client

Type Alias TypeNum

TypeNum: z.infer<typeof typeNumSchema>
diff --git a/docs/types/TypeString.html b/docs/types/TypeString.html index c09323b..8bad08f 100644 --- a/docs/types/TypeString.html +++ b/docs/types/TypeString.html @@ -1 +1 @@ -TypeString | ntcore-ts-client

Type Alias TypeString

TypeString: z.infer<typeof typeStringSchema>
+TypeString | ntcore-ts-client

Type Alias TypeString

TypeString: z.infer<typeof typeStringSchema>
diff --git a/docs/types/UnannounceMessage.html b/docs/types/UnannounceMessage.html index f42a3ee..1c6ea0e 100644 --- a/docs/types/UnannounceMessage.html +++ b/docs/types/UnannounceMessage.html @@ -1 +1 @@ -UnannounceMessage | ntcore-ts-client

Type Alias UnannounceMessage

UnannounceMessage: z.infer<typeof unannounceMessageSchema>
+UnannounceMessage | ntcore-ts-client

Type Alias UnannounceMessage

UnannounceMessage: z.infer<typeof unannounceMessageSchema>
diff --git a/docs/types/UnannounceMessageParams.html b/docs/types/UnannounceMessageParams.html index bb07ee1..f89cddc 100644 --- a/docs/types/UnannounceMessageParams.html +++ b/docs/types/UnannounceMessageParams.html @@ -1 +1 @@ -UnannounceMessageParams | ntcore-ts-client

Type Alias UnannounceMessageParams

UnannounceMessageParams: UnannounceMessage["params"]
+UnannounceMessageParams | ntcore-ts-client

Type Alias UnannounceMessageParams

UnannounceMessageParams: UnannounceMessage["params"]
diff --git a/docs/types/UnpublishMessage.html b/docs/types/UnpublishMessage.html index 87bb9ae..3b82642 100644 --- a/docs/types/UnpublishMessage.html +++ b/docs/types/UnpublishMessage.html @@ -1 +1 @@ -UnpublishMessage | ntcore-ts-client

Type Alias UnpublishMessage

UnpublishMessage: z.infer<typeof unpublishMessageSchema>
+UnpublishMessage | ntcore-ts-client

Type Alias UnpublishMessage

UnpublishMessage: z.infer<typeof unpublishMessageSchema>
diff --git a/docs/types/UnpublishMessageParams.html b/docs/types/UnpublishMessageParams.html index 1f628af..7a9f580 100644 --- a/docs/types/UnpublishMessageParams.html +++ b/docs/types/UnpublishMessageParams.html @@ -1 +1 @@ -UnpublishMessageParams | ntcore-ts-client

Type Alias UnpublishMessageParams

UnpublishMessageParams: UnpublishMessage["params"]
+UnpublishMessageParams | ntcore-ts-client

Type Alias UnpublishMessageParams

UnpublishMessageParams: UnpublishMessage["params"]
diff --git a/docs/types/UnsubscribeMessage.html b/docs/types/UnsubscribeMessage.html index 39abda7..7651dce 100644 --- a/docs/types/UnsubscribeMessage.html +++ b/docs/types/UnsubscribeMessage.html @@ -1 +1 @@ -UnsubscribeMessage | ntcore-ts-client

Type Alias UnsubscribeMessage

UnsubscribeMessage: z.infer<typeof unsubscribeMessageSchema>
+UnsubscribeMessage | ntcore-ts-client

Type Alias UnsubscribeMessage

UnsubscribeMessage: z.infer<typeof unsubscribeMessageSchema>
diff --git a/docs/types/UnsubscribeMessageParams.html b/docs/types/UnsubscribeMessageParams.html index 4bafabe..6573173 100644 --- a/docs/types/UnsubscribeMessageParams.html +++ b/docs/types/UnsubscribeMessageParams.html @@ -1 +1 @@ -UnsubscribeMessageParams | ntcore-ts-client

Type Alias UnsubscribeMessageParams

UnsubscribeMessageParams: UnsubscribeMessage["params"]
+UnsubscribeMessageParams | ntcore-ts-client

Type Alias UnsubscribeMessageParams

UnsubscribeMessageParams: UnsubscribeMessage["params"]
diff --git a/nx.json b/nx.json index 6f9118b..3a992ad 100644 --- a/nx.json +++ b/nx.json @@ -27,6 +27,11 @@ "@nx/eslint:lint": { "cache": true, "inputs": ["default", "{workspaceRoot}/.eslintrc.json", "{workspaceRoot}/tools/eslint-rules/**/*"] + }, + "@nx/esbuild:esbuild": { + "cache": true, + "dependsOn": ["^build"], + "inputs": ["production", "^production"] } }, "namedInputs": { diff --git a/package-lock.json b/package-lock.json index eb85960..1815c25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,41 +12,41 @@ "@msgpack/msgpack": "^2.8.0", "isomorphic-ws": "^5.0.0", "tslib": "^2.8.1", - "uuid": "^11.0.5", "ws": "^8.18.0", "zod": "^3.24.1" }, "devDependencies": { "@commitlint/cli": "^19.6.1", "@commitlint/config-conventional": "^19.6.0", - "@nx/devkit": "20.3.1", - "@nx/eslint": "20.3.1", - "@nx/eslint-plugin": "20.3.1", - "@nx/jest": "20.3.1", - "@nx/js": "20.3.1", - "@nx/node": "20.3.1", - "@nx/workspace": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/esbuild": "20.3.2", + "@nx/eslint": "20.3.2", + "@nx/eslint-plugin": "20.3.2", + "@nx/jest": "20.3.2", + "@nx/js": "20.3.2", + "@nx/node": "20.3.2", + "@nx/workspace": "20.3.2", "@types/jest": "29.5.14", - "@types/node": "22.10.5", - "@types/uuid": "^10.0.0", + "@types/node": "^22.10.7", "@types/ws": "^8.5.13", - "@typescript-eslint/eslint-plugin": "7.18.0", - "@typescript-eslint/parser": "7.18.0", - "@typescript-eslint/utils": "^8.13.0", + "@typescript-eslint/eslint-plugin": "^8.21.0", + "@typescript-eslint/parser": "^8.21.0", + "@typescript-eslint/utils": "^8.20.0", + "esbuild": "^0.19.12", "eslint": "8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.10.0", - "eslint-plugin-jsdoc": "^48.11.0", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.2", "eslint-plugin-json": "^3.1.0", - "eslint-plugin-tsdoc": "^0.2.17", + "eslint-plugin-tsdoc": "^0.4.0", "husky": "^9.1.7", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-websocket-mock": "^2.5.0", - "lint-staged": "^15.3.0", - "nx": "20.3.1", + "lint-staged": "^15.4.1", + "nx": "20.3.2", "prettier": "^3.4.2", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", @@ -1349,9 +1349,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.5.tgz", - "integrity": "sha512-OHqczNm4NTQlW1ghrVY43FPoiRzbmzNVbcgVnMKZN/RQYezHUSdjACjaX50CD3B7UIAjv39+MlsrVDb3v741FA==", + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "dev": true, "license": "MIT", "dependencies": { @@ -2284,20 +2284,411 @@ } }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", - "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz", + "integrity": "sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==", "dev": true, "license": "MIT", "dependencies": { "comment-parser": "1.4.1", "esquery": "^1.6.0", - "jsdoc-type-pratt-parser": "~4.0.0" + "jsdoc-type-pratt-parser": "~4.1.0" }, "engines": { "node": ">=16" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -2452,14 +2843,14 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.26.1.tgz", - "integrity": "sha512-gHFUvv9f1fU2Piou/5Y7Sx5moYxcERbC7CXc6rkDLQTUBg5Dgg9L4u29/nHqfoQ3Y9R0h0BcOhd14uOEZIBP7Q==", + "version": "1.27.2", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.27.2.tgz", + "integrity": "sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/engine-oniguruma": "^1.26.1", - "@shikijs/types": "^1.26.1", + "@shikijs/engine-oniguruma": "^1.27.2", + "@shikijs/types": "^1.27.2", "@shikijs/vscode-textmate": "^10.0.1" } }, @@ -3129,35 +3520,35 @@ } }, "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz", + "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==", "dev": true, "license": "MIT" }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.1.tgz", + "integrity": "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", + "@microsoft/tsdoc": "0.15.1", + "ajv": "~8.12.0", "jju": "~1.4.0", - "resolve": "~1.19.0" + "resolve": "~1.22.2" } }, "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -3165,27 +3556,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@msgpack/msgpack": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", @@ -3256,9 +3626,9 @@ } }, "node_modules/@nx/devkit": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.3.1.tgz", - "integrity": "sha512-Z6VdBg5GRu2Vg9FpeQJY+zQ1TvBoMWk8cTCZOf8J6myjoWYbksRfpWfNIvEk9OUsEMhpg98vxH2Cc8JR1zfiew==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.3.2.tgz", + "integrity": "sha512-VhbxEsSTCZlOVgjuQC+6HQmb9Oz9VoHUeo4001Pw6BFBcSXZUi5q37C/lxbAgQPnMKLkFcLva3WKZ+fOLwhGIg==", "dev": true, "license": "MIT", "dependencies": { @@ -3275,15 +3645,38 @@ "nx": ">= 19 <= 21" } }, + "node_modules/@nx/esbuild": { + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/esbuild/-/esbuild-20.3.2.tgz", + "integrity": "sha512-MOiDyLh4GcWjae0nIrFSTJg7djc/BjxvF1jv06GyT3JznhvXGa6ht5/BRy3aoBbznux4oH7aAwtbGqtRrrFLyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/devkit": "20.3.2", + "@nx/js": "20.3.2", + "picocolors": "^1.1.0", + "tinyglobby": "^0.2.10", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "esbuild": "~0.19.2" + }, + "peerDependenciesMeta": { + "esbuild": { + "optional": true + } + } + }, "node_modules/@nx/eslint": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.3.1.tgz", - "integrity": "sha512-7yhS9LIipg60Dj0/3tGA11jpz1+ToeITze1/wTcQfgNSVN+ZXC21t2/UracI9+ReituWENM12S0ZurNef7zm/A==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.3.2.tgz", + "integrity": "sha512-vWvMmJ4aU/CjqomTVLuMlmhxKj/Q2wlhu9tQhZlDexDGfGF4QMidrbb25Rqog9NSeeI5hhBp57TQjfDyEF8HhQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.1", - "@nx/js": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/js": "20.3.2", "semver": "^7.5.3", "tslib": "^2.3.0", "typescript": "~5.6.2" @@ -3299,14 +3692,14 @@ } }, "node_modules/@nx/eslint-plugin": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-20.3.1.tgz", - "integrity": "sha512-R+slt72ZLisT2uPpOJGUt/HnVf8hDWZvUcqyrSKJ8A8XZQlBYnSaFuKerse/if/en6iRAzjSWjUo9vnBIFgVIQ==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-20.3.2.tgz", + "integrity": "sha512-m3gWjOY9Cn4lujMZITfxuD+T7iPf0MOqfiTU8gnlybGpqxOL2F6roHtVRX3aas2cKtSTY/Kk+fIalIJVSxfSoQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.1", - "@nx/js": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/js": "20.3.2", "@typescript-eslint/type-utils": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", "chalk": "^4.1.0", @@ -3374,66 +3767,33 @@ } }, "node_modules/@nx/jest": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.3.1.tgz", - "integrity": "sha512-sns9zDeWNZ/25oh/n6EOPh+dwggw3g7ENNGBjZBzIVM5npNLcuKFjhzwfUCD4j0jX2ACuGIxpaCNbc5QsEMqiw==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.3.2.tgz", + "integrity": "sha512-YW+KVoQEZi1Otm1wBAu0Bf3uq1Kp7ighPW73e8bL0SQPTdp6Afdn/52HZfrOGvBjdHLrZ50N817IJLUpApJ82g==", "dev": true, "license": "MIT", "dependencies": { "@jest/reporters": "^29.4.1", "@jest/test-result": "^29.4.1", - "@nx/devkit": "20.3.1", - "@nx/js": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/js": "20.3.2", "@phenomnomnominal/tsquery": "~5.0.1", - "chalk": "^4.1.0", "identity-obj-proxy": "3.0.0", "jest-config": "^29.4.1", "jest-resolve": "^29.4.1", "jest-util": "^29.4.1", "minimatch": "9.0.3", + "picocolors": "^1.1.0", "resolve.exports": "2.0.3", "semver": "^7.5.3", "tslib": "^2.3.0", "yargs-parser": "21.1.1" } }, - "node_modules/@nx/jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nx/jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@nx/js": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.3.1.tgz", - "integrity": "sha512-IHf1rLiwH1NUMphedJJMfstehD94IkwU4YxOkUMRA1tPbrmidF391gh70pE4VMkji/jzzkQXYhNsrNnAN6LRpw==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.3.2.tgz", + "integrity": "sha512-t2mLCogVc/DWpkJ1SW4pFgeyWAmuy7EI4IPyShtF4s9mhqyIDfd29fGYsocuv84skX6y4JMOw3O+c+LXdQ9QWw==", "dev": true, "license": "MIT", "dependencies": { @@ -3444,8 +3804,8 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.22.5", "@babel/runtime": "^7.22.6", - "@nx/devkit": "20.3.1", - "@nx/workspace": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/workspace": "20.3.2", "@zkochan/js-yaml": "0.0.7", "babel-plugin-const-enum": "^1.0.1", "babel-plugin-macros": "^2.8.0", @@ -3555,23 +3915,23 @@ } }, "node_modules/@nx/node": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/node/-/node-20.3.1.tgz", - "integrity": "sha512-IdY77rgjqBTpxR43CHqkIb4uT9PwVl0uqP4kBo38qxXvEydFqoecRTfDikeVjMOkHaesqReNAKLaY/mITQXaOA==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/node/-/node-20.3.2.tgz", + "integrity": "sha512-JvYXPjoPho+RJKXgg2b0/hQ2SivccfGG+vkoQ4XcwBLW7qUjKUjxmkgSHD4XaAgf9Fe9L9Pqni58CriwzNfaFg==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.1", - "@nx/eslint": "20.3.1", - "@nx/jest": "20.3.1", - "@nx/js": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/eslint": "20.3.2", + "@nx/jest": "20.3.2", + "@nx/js": "20.3.2", "tslib": "^2.3.0" } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.3.1.tgz", - "integrity": "sha512-bx++T9/8l4PK1yDTxPnROT7RG8CkWGkxKC0D7xlS/YQzE7CelDfgNYu0Bd7upZF4gafW2Uz3dd3j6WhvZLxbbg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.3.2.tgz", + "integrity": "sha512-lQOXMIPmE9o36TuZ+SX6iq7PPWa3s1fjNRqCujlviExX69245NNCMxd754gXlLrsxC1onrx/zmJciKmmEWDIiw==", "cpu": [ "arm64" ], @@ -3586,9 +3946,9 @@ } }, "node_modules/@nx/nx-darwin-x64": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.3.1.tgz", - "integrity": "sha512-elg2GiSivMHU1iLFYZ+FojM2V/FmTlC8e5FKM6nZ+bIqeoBoJm8Rxxe/kEtcsPdvjj+YiKSmXOP9s45DJb9WWw==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.3.2.tgz", + "integrity": "sha512-RvvSz4QYVOYOfC8sUE63b6dy8iHk2AEI0r1FF5FCQuqE1DdTeTjPETY2sY35tRqF+mO/6oLGp2+m9ti/ysRoTg==", "cpu": [ "x64" ], @@ -3603,9 +3963,9 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.3.1.tgz", - "integrity": "sha512-1iKZOCcU7bVAC2kdoukfJ7AOTLBhm69+vPff3HCJQ0DI/5ZbmiaPeBMsAVFtJ0jFGix8yYIhgvtXgDEfbXXRFQ==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.3.2.tgz", + "integrity": "sha512-KBDTyGn1evlZ17pupwRUDh2wrCMuHhP2j8cOCdgF5cl7vRki8BOK9yyL6jD11d/d/6DgXzy1jmQEX4Xx+AGCug==", "cpu": [ "x64" ], @@ -3620,9 +3980,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.3.1.tgz", - "integrity": "sha512-LAteJ1/mWYdvj7zpXuWRUq1lvUiV6YVXCdFK3+7lDW+qvW3bb5zzUwbVDAF/pPeTjBrsdHDzSWOCLm/LKtYtMw==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.3.2.tgz", + "integrity": "sha512-mW+OcOnJEMvs7zD3aSwEG3z5M9bI4CuUU5Q/ePmnNzWIucRHpoAMNt/Sd+yu6L4+QttvoUf967uwcMsX8l4nrw==", "cpu": [ "arm" ], @@ -3637,9 +3997,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.3.1.tgz", - "integrity": "sha512-2Qf+6NcAeODELyJR+V9hjC9kl2DwJTdI7Bw+BuiyXftfPHvZ86P//FC8kPjNaJCEEm/ZStP6Jcb1zlp4Eo2wBw==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.3.2.tgz", + "integrity": "sha512-hbXpZqUvGY5aeEWvh0SNsiYjP1ytSM30XOT6qN6faLO2CL/7j9D2UB69SKOqF3TJOvuNU6cweFgZCxyGfXBYIQ==", "cpu": [ "arm64" ], @@ -3654,9 +4014,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.3.1.tgz", - "integrity": "sha512-8S8jlN6GFQpRakZ2ZVWq6eFnLVrEObIaxnYD0QMbsMf+qiedDJt+cDh1xebcPRvgpSgJVlJ8P6hun5+K/FiQDQ==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.3.2.tgz", + "integrity": "sha512-HXthtN7adXCNVWs2F4wIqq2f7BcKTjsEnqg2LWV5lm4hRYvMfEvPftb0tECsEhcSQQYcvIJnLfv3vtu9HZSfVA==", "cpu": [ "arm64" ], @@ -3671,9 +4031,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.3.1.tgz", - "integrity": "sha512-qC2On2qwYCtn/Kt8epvUn0H3NY6zG9yYhiNjkm6RvVTDmvogFQ4gtfiWSRP/EnabCRqM8FACDIO/ws5CnRBX+Q==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.3.2.tgz", + "integrity": "sha512-HhgHqOUT05H45zuQL+XPywQbRNFttd7Rkkr7dZnpCRdp4W8GDjfyKCoCS5qVyowAyNh9Vc7VEq9qmiLMlvf6Zg==", "cpu": [ "x64" ], @@ -3688,9 +4048,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.3.1.tgz", - "integrity": "sha512-KKwHSfV1PEKW82eJ8vxZTPepoaLbaXH/aI0VOKZbBO4ytGyGUr9wFuWPsyo06rK7qtSD7w9bN7xpiBGQk0QTsg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.3.2.tgz", + "integrity": "sha512-NrZ8L9of2GmYEM8GMJX6QRrLJlAwM+ds2rhdY1bxwpiyCNcD3IO/gzJlBs+kG4ly05F1u/X4k/FI5dXPpjUSgw==", "cpu": [ "x64" ], @@ -3705,9 +4065,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.3.1.tgz", - "integrity": "sha512-YujkXXHn9rhtwZRDxiaxSPOMX7JkfGmXAFdyEfxhE3Dc/HjFgI+xJZ478/atttR7DWIwGpQJVLpbFWbFFpoNNg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.3.2.tgz", + "integrity": "sha512-yLjacZND7C1XmsC0jfRLSgeLWZUw2Oz+u3nXNvj5JX6YHtYTVLFnRbTAcI+pG2Y6v0Otf2GKb3VT5d1mQb8JvA==", "cpu": [ "arm64" ], @@ -3722,9 +4082,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.3.1.tgz", - "integrity": "sha512-Os8iCamvHhE5noQKFE9D9xkiI529918tufTYmEhJ9ZmLU/ybVA0We6r7gXjYzdNfA3DtwfGXvNvUpy3u+pZXOg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.3.2.tgz", + "integrity": "sha512-oDhcctfk0UB1V+Otp1161VKNMobzkFQxGyiEIjp0CjCBa2eRHC1r35L695F1Hj0bvLQPSni9XIe9evh2taeAkg==", "cpu": [ "x64" ], @@ -3739,16 +4099,16 @@ } }, "node_modules/@nx/workspace": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.3.1.tgz", - "integrity": "sha512-2GQX19POWzTDV8XIAc/UCNruzs77jD2WwAkYAOveiTBqJIJVd64ueOBXZw1YkZLhXTFd0C13xT1CFo2fOvyJLg==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.3.2.tgz", + "integrity": "sha512-Dj2AbG9X8Uo6k3XhcuNOblDgR/U8u5+x41hMNKHSG9Pi3CyAJ24didtn1SMf78GElzPOV94KJZmioGHw3rKyCg==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "20.3.1", + "@nx/devkit": "20.3.2", "chalk": "^4.1.0", "enquirer": "~2.3.6", - "nx": "20.3.1", + "nx": "20.3.2", "tslib": "^2.3.0", "yargs-parser": "21.1.1" } @@ -3820,20 +4180,20 @@ "license": "MIT" }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.26.1.tgz", - "integrity": "sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.1.tgz", + "integrity": "sha512-gSt2WhLNgEeLstcweQOSp+C+MhOpTsgdNXRqr3zP6M+BUBZ8Md9OU2BYwUYsALBxHza7hwaIWtFHjQ/aOOychw==", "dev": true, "license": "MIT", "dependencies": { - "@shikijs/types": "1.26.1", + "@shikijs/types": "1.29.1", "@shikijs/vscode-textmate": "^10.0.1" } }, "node_modules/@shikijs/types": { - "version": "1.26.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.26.1.tgz", - "integrity": "sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==", + "version": "1.29.1", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.1.tgz", + "integrity": "sha512-aBqAuhYRp5vSir3Pc9+QPu9WESBOjUo03ao0IHLC4TyTioSsp/SkbAZSrIH4ghYYC1T1KTEpRSBa83bas4RnPA==", "dev": true, "license": "MIT", "dependencies": { @@ -4056,9 +4416,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", "dev": true, "license": "MIT", "dependencies": { @@ -4093,13 +4453,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -4117,142 +4470,83 @@ "dev": true, "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@types/yargs-parser": "*" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz", + "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/type-utils": "8.21.0", + "@typescript-eslint/utils": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz", + "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.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", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz", + "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/visitor-keys": "8.21.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -4260,14 +4554,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", - "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz", + "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.1", - "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/typescript-estree": "8.21.0", + "@typescript-eslint/utils": "8.21.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, @@ -4283,10 +4577,10 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", - "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", + "node_modules/@typescript-eslint/types": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz", + "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==", "dev": true, "license": "MIT", "engines": { @@ -4297,15 +4591,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", - "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz", + "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", + "@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", @@ -4324,109 +4618,6 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", - "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.19.1", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -4444,16 +4635,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", - "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz", + "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.1", - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/typescript-estree": "8.19.1" + "@typescript-eslint/scope-manager": "8.21.0", + "@typescript-eslint/types": "8.21.0", + "@typescript-eslint/typescript-estree": "8.21.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4467,73 +4658,14 @@ "typescript": ">=4.8.4 <5.8.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", - "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", - "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", - "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.19.1", - "@typescript-eslint/visitor-keys": "8.19.1", - "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" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", - "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz", + "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/types": "8.21.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4544,7 +4676,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", @@ -4557,53 +4689,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/ts-api-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", - "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", @@ -4872,16 +4957,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlastindex": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", @@ -5502,9 +5577,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001692", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", - "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "version": "1.0.30001695", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", + "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", "dev": true, "funding": [ { @@ -6291,19 +6366,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -6405,9 +6467,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.80", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", - "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", + "version": "1.5.84", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.84.tgz", + "integrity": "sha512-I+DQ8xgafao9Ha6y0qjHHvpZ9OfyA1qKlkHkjywxzniORU2awxyz7f/iVJcULmrF2yrM3nHQf+iDjJtbbexd/g==", "dev": true, "license": "ISC" }, @@ -6608,9 +6670,9 @@ "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { @@ -6664,6 +6726,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -6993,9 +7094,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "28.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.10.0.tgz", - "integrity": "sha512-hyMWUxkBH99HpXT3p8hc7REbEZK3D+nk8vHXGgpB+XXsi0gO4PxMSP+pjfUzb67GnV9yawV9a53eUmcde1CCZA==", + "version": "28.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.11.0.tgz", + "integrity": "sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==", "dev": true, "license": "MIT", "dependencies": { @@ -7019,16 +7120,16 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "48.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.11.0.tgz", - "integrity": "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==", + "version": "50.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.2.tgz", + "integrity": "sha512-n7GNZ4czMAAbDg7DsDA7PvHo1IPIUwAXYmxTx6j/hTlXbt5V0x5q/kGkiJ7s4wA9SpB/yaiK8jF7CO237lOLew==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.46.0", + "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", - "debug": "^4.3.5", + "debug": "^4.3.6", "escape-string-regexp": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.6.0", @@ -7090,14 +7191,14 @@ } }, "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", - "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.4.0.tgz", + "integrity": "sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==", "dev": true, "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "0.16.2" + "@microsoft/tsdoc": "0.15.1", + "@microsoft/tsdoc-config": "0.17.1" } }, "node_modules/eslint-scope": { @@ -7499,9 +7600,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "dev": true, "funding": [ { @@ -7900,9 +8001,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.9.0.tgz", + "integrity": "sha512-52n24W52sIueosRe0XZ8Ex5Yle+WbhfCKnV/gWXpbVR8FXNTfqdKEKUSypKso66VRHTvvcQxL44UTZbJRlCTnw==", "dev": true, "license": "MIT", "dependencies": { @@ -8035,27 +8136,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -10348,9 +10428,9 @@ } }, "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", "dev": true, "license": "MIT", "engines": { @@ -10588,9 +10668,9 @@ } }, "node_modules/lint-staged": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", - "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.1.tgz", + "integrity": "sha512-P8yJuVRyLrm5KxCtFx+gjI5Bil+wO7wnTl7C3bXhvtTaAFGirzeB24++D0wGoUwxrUKecNiehemgCob9YL39NA==", "dev": true, "license": "MIT", "dependencies": { @@ -11331,9 +11411,9 @@ "license": "MIT" }, "node_modules/nx": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.3.1.tgz", - "integrity": "sha512-pO48DoQAwVKBEF7/od3bc1tHBYfafgiuS/hHX3yGmhpWW58baIlxMWFp6QY9+A9Q0R+26pd6AEGnE7d1f7+i/g==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.3.2.tgz", + "integrity": "sha512-VWUHX0uCn8ACFbpBTpgucDzwe4q/a/UU3AYOhzKCvTzb3kQiyvoxLjORSze93ZNEqgor0PMkCQgcoMBUjxJfzQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -11378,16 +11458,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.3.1", - "@nx/nx-darwin-x64": "20.3.1", - "@nx/nx-freebsd-x64": "20.3.1", - "@nx/nx-linux-arm-gnueabihf": "20.3.1", - "@nx/nx-linux-arm64-gnu": "20.3.1", - "@nx/nx-linux-arm64-musl": "20.3.1", - "@nx/nx-linux-x64-gnu": "20.3.1", - "@nx/nx-linux-x64-musl": "20.3.1", - "@nx/nx-win32-arm64-msvc": "20.3.1", - "@nx/nx-win32-x64-msvc": "20.3.1" + "@nx/nx-darwin-arm64": "20.3.2", + "@nx/nx-darwin-x64": "20.3.2", + "@nx/nx-freebsd-x64": "20.3.2", + "@nx/nx-linux-arm-gnueabihf": "20.3.2", + "@nx/nx-linux-arm64-gnu": "20.3.2", + "@nx/nx-linux-arm64-musl": "20.3.2", + "@nx/nx-linux-x64-gnu": "20.3.2", + "@nx/nx-linux-x64-musl": "20.3.2", + "@nx/nx-win32-arm64-msvc": "20.3.2", + "@nx/nx-win32-x64-msvc": "20.3.2" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -12928,9 +13008,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -13332,9 +13412,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -13419,16 +13499,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-jest": { @@ -13891,19 +13971,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uuid": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", - "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index a6e6e9f..c338e49 100644 --- a/package.json +++ b/package.json @@ -20,41 +20,41 @@ "@msgpack/msgpack": "^2.8.0", "isomorphic-ws": "^5.0.0", "tslib": "^2.8.1", - "uuid": "^11.0.5", "ws": "^8.18.0", "zod": "^3.24.1" }, "devDependencies": { "@commitlint/cli": "^19.6.1", "@commitlint/config-conventional": "^19.6.0", - "@nx/devkit": "20.3.1", - "@nx/eslint": "20.3.1", - "@nx/eslint-plugin": "20.3.1", - "@nx/jest": "20.3.1", - "@nx/js": "20.3.1", - "@nx/node": "20.3.1", - "@nx/workspace": "20.3.1", + "@nx/devkit": "20.3.2", + "@nx/esbuild": "20.3.2", + "@nx/eslint": "20.3.2", + "@nx/eslint-plugin": "20.3.2", + "@nx/jest": "20.3.2", + "@nx/js": "20.3.2", + "@nx/node": "20.3.2", + "@nx/workspace": "20.3.2", "@types/jest": "29.5.14", - "@types/node": "22.10.5", - "@types/uuid": "^10.0.0", + "@types/node": "^22.10.7", "@types/ws": "^8.5.13", - "@typescript-eslint/eslint-plugin": "7.18.0", - "@typescript-eslint/parser": "7.18.0", - "@typescript-eslint/utils": "^8.13.0", + "@typescript-eslint/eslint-plugin": "^8.21.0", + "@typescript-eslint/parser": "^8.21.0", + "@typescript-eslint/utils": "^8.20.0", + "esbuild": "^0.19.12", "eslint": "8.57.1", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-jest": "^28.10.0", - "eslint-plugin-jsdoc": "^48.11.0", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.2", "eslint-plugin-json": "^3.1.0", - "eslint-plugin-tsdoc": "^0.2.17", + "eslint-plugin-tsdoc": "^0.4.0", "husky": "^9.1.7", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-websocket-mock": "^2.5.0", - "lint-staged": "^15.3.0", - "nx": "20.3.1", + "lint-staged": "^15.4.1", + "nx": "20.3.2", "prettier": "^3.4.2", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", diff --git a/packages/ntcore-ts-client/CHANGELOG.md b/packages/ntcore-ts-client/CHANGELOG.md index 9a0190c..de53da9 100644 --- a/packages/ntcore-ts-client/CHANGELOG.md +++ b/packages/ntcore-ts-client/CHANGELOG.md @@ -2,6 +2,21 @@ Note: there may be breaking changes between each beta version, but if a breaking change is introduced out of beta, it will be a major version change +## 3.0.0 + +### Breaking Changes + +- **BREAKING CHANGE: Remove immediateNotify from subscribe** + - This complicated prefix topics and was not a very valuable feature + - Workaround: you can manually call the subscription's callback yourself after subscribing + +### Changes + +- Add prefix topic support + - You can now subscribe to multiple topics with a single subscription + - This is done by creating a topic with a prefix, and then subscribing to that topic + - For example, if you have topics `/MyTable/Accelerometer/X`, `/MyTable/Accelerometer/Y`, and `/MyTable/Accelerometer/Z`, you can create a prefix topic `/MyTable/Accelerometer/` and subscribe to that to get notifications for all three subtopics + ## 2.0.0 ### Breaking Changes diff --git a/packages/ntcore-ts-client/README.md b/packages/ntcore-ts-client/README.md index 7bc5967..ae43f24 100644 --- a/packages/ntcore-ts-client/README.md +++ b/packages/ntcore-ts-client/README.md @@ -1,6 +1,6 @@ # ntcore-ts-client -A TypeScript library for communication over [WPILib's NetworkTables 4.0 protocol](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc). +A TypeScript library for communication over [WPILib's NetworkTables 4.1 protocol](https://github.com/wpilibsuite/allwpilib/blob/main/ntcore/doc/networktables4.adoc). ## Usage diff --git a/packages/ntcore-ts-client/package.json b/packages/ntcore-ts-client/package.json index a54c7f0..6cbb5ed 100644 --- a/packages/ntcore-ts-client/package.json +++ b/packages/ntcore-ts-client/package.json @@ -1,6 +1,6 @@ { "name": "ntcore-ts-client", - "version": "2.0.0", + "version": "3.0.0", "license": "MIT", "keywords": [ "ntcore", diff --git a/packages/ntcore-ts-client/src/lib/ntcore-ts-client.spec.ts b/packages/ntcore-ts-client/src/lib/ntcore-ts-client.spec.ts index 85eb2de..f60b4b5 100644 --- a/packages/ntcore-ts-client/src/lib/ntcore-ts-client.spec.ts +++ b/packages/ntcore-ts-client/src/lib/ntcore-ts-client.spec.ts @@ -64,4 +64,10 @@ describe('NetworkTables', () => { const topic = networkTables.createTopic('/foo', NetworkTablesTypeInfos.kDouble, 1.0); expect(topic).toBeDefined(); }); + + it('creates a prefix topic', () => { + const networkTables = NetworkTables.getInstanceByTeam(973); + const topic = networkTables.createPrefixTopic('/'); + expect(topic).toBeDefined(); + }); }); diff --git a/packages/ntcore-ts-client/src/lib/ntcore-ts-client.ts b/packages/ntcore-ts-client/src/lib/ntcore-ts-client.ts index e16d2cb..e2053cf 100644 --- a/packages/ntcore-ts-client/src/lib/ntcore-ts-client.ts +++ b/packages/ntcore-ts-client/src/lib/ntcore-ts-client.ts @@ -1,3 +1,4 @@ +import { NetworkTablesPrefixTopic } from './pubsub/prefix-topic'; import { PubSubClient } from './pubsub/pubsub'; import { NetworkTablesTopic } from './pubsub/topic'; import { Util } from './util/util'; @@ -143,4 +144,13 @@ export class NetworkTables { createTopic(name: string, typeInfo: NetworkTablesTypeInfo, defaultValue?: T) { return new NetworkTablesTopic(this._client, name, typeInfo, defaultValue); } + + /** + * Creates a new topic with a prefix. + * @param prefix - The prefix of the topic. + * @returns The topic. + */ + createPrefixTopic(prefix: string) { + return new NetworkTablesPrefixTopic(this._client, prefix); + } } diff --git a/packages/ntcore-ts-client/src/lib/pubsub/base-topic.ts b/packages/ntcore-ts-client/src/lib/pubsub/base-topic.ts new file mode 100644 index 0000000..4e65adc --- /dev/null +++ b/packages/ntcore-ts-client/src/lib/pubsub/base-topic.ts @@ -0,0 +1,168 @@ +import type { NetworkTablesPrefixTopic } from './prefix-topic'; +import type { PubSubClient } from './pubsub'; +import type { NetworkTablesTopic } from './topic'; +import type { + AnnounceMessageParams, + NetworkTablesTypes, + PropertiesMessage, + SetPropertiesMessageParams, + SubscribeOptions, +} from '../types/types'; + +export type CallbackFn = (value: T | null, params: AnnounceMessageParams) => void; + +export abstract class NetworkTablesBaseTopic { + protected abstract readonly type: 'regular' | 'prefix'; + protected client: PubSubClient; + private _id?: number; + private readonly _name: string; + protected _lastChangedTime?: number; + protected _announceParams: AnnounceMessageParams | null; + private _subscribers: Map< + number, + { + callback: CallbackFn; + options: SubscribeOptions; + } + >; + + isRegular(): this is NetworkTablesTopic { + return this.type === 'regular'; + } + + isPrefix(): this is NetworkTablesPrefixTopic { + return this.type === 'prefix'; + } + + /** + * Gets the ID of the topic. + * @returns The ID of the topic. + */ + get id() { + return this._id; + } + + /** + * Gets the name of the topic. + * @returns The name of the topic. + */ + get name() { + return this._name; + } + + /** + * Gets the server time of the last value change. + * @returns The server time of the last value change. + */ + get lastChangedTime() { + return this._lastChangedTime; + } + + /** + * Whether the topic has been announced. + * @returns Whether the topic has been announced. + */ + get announced() { + return this._announceParams != null; + } + + /** + * Gets the subscribers to the topic. + * @returns The subscribers to the topic. + */ + get subscribers() { + return this._subscribers; + } + + /** + * Creates a new topic. This should only be done after the + * base NTCore client has been initialized. + * @param client - The client that owns the topic. + * @param name - The name of the topic. + */ + constructor(client: PubSubClient, name: string) { + this.client = client; + this._name = name; + this._announceParams = null; + this._subscribers = new Map(); + } + + /** */ + /* ANNOUNCEMENTS */ + /** */ + + /** + * Marks the topic as announced. This should only be called by the PubSubClient. + * @param params - The parameters of the announcement. + */ + announce(params: AnnounceMessageParams) { + this._announceParams = params; + this._id = params.id; + } + + /** Marks the topic as unannounced. This should only be called by the PubSubClient. */ + unannounce() { + this._announceParams = null; + this._id = undefined; + } + + /** */ + /* SUBSCRIBING */ + /** */ + + /** + * Creates a new subscriber. This should only be called by the PubSubClient. + * @param callback - The callback to call when the topic value changes. + * @param options - The options for the subscriber. + * @param id - The UID of the subscriber. + * @param save - Whether to save the subscriber. + * @returns The UID of the subscriber. + */ + abstract subscribe(callback: CallbackFn, options?: SubscribeOptions, id?: number, save?: boolean): number; + + /** + * Resubscribes all local subscribers. + * @param client - The client to resubscribe with. + */ + abstract resubscribeAll(client: PubSubClient): void; + + /** + * Removes a subscriber + * @param subuid - The UID of the subscriber. + * @param removeCallback - Whether to remove the callback. Leave this as true unless you know what you're doing. + */ + unsubscribe(subuid: number, removeCallback = true) { + this.client.messenger.unsubscribe(subuid); + if (removeCallback) this.subscribers.delete(subuid); + } + + /** + * Removes all local subscribers. + */ + unsubscribeAll() { + this.subscribers.forEach((_, subuid) => this.unsubscribe(subuid)); + } + + /** */ + /* PUBLISHING */ + /** */ + + /** + * Sets the properties of the topic. + * @param persistent - If true, the last set value will be periodically saved to persistent storage on the server and be restored during server startup. Topics with this property set to true will not be deleted by the server when the last publisher stops publishing. + * @param retained - Topics with this property set to true will not be deleted by the server when the last publisher stops publishing. + * @returns The server's response. + */ + async setProperties(persistent?: boolean, retained?: boolean): Promise { + const setPropertiesParams: SetPropertiesMessageParams = { + name: this.name, + update: { + persistent, + retained, + }, + }; + + // Send the set properties request + return await this.client.messenger.setProperties(setPropertiesParams); + } +} diff --git a/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.spec.ts b/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.spec.ts new file mode 100644 index 0000000..30c459c --- /dev/null +++ b/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.spec.ts @@ -0,0 +1,164 @@ +import WSMock from 'jest-websocket-mock'; + +import { NetworkTablesPrefixTopic } from './prefix-topic'; +import { PubSubClient } from './pubsub'; + +import type { CallbackFn } from './base-topic'; +import type { AnnounceMessageParams, NetworkTablesTypes, SubscribeMessageParams } from '../types/types'; + +describe('Prefix Topic', () => { + let topic: NetworkTablesPrefixTopic; + let server: WSMock; + let client: PubSubClient; + const serverUrl = 'ws://localhost:5810/nt/1234'; + + beforeAll(async () => { + server = new WSMock(serverUrl); + client = PubSubClient.getInstance(serverUrl); + + await server.connected; + }); + + beforeEach(() => { + topic = new NetworkTablesPrefixTopic(client, 'test'); + }); + + afterEach(() => { + topic['client']['prefixTopics'].clear(); + topic.subscribers.clear(); + }); + + describe('constructor', () => { + it('returns the existing topic if it already exists', () => { + const newTopic = new NetworkTablesPrefixTopic(topic['client'], 'test'); + expect(newTopic).toBe(topic); + }); + }); + + describe('updateValue', () => { + it('updates the value correctly', () => { + const params: AnnounceMessageParams = { id: 1, name: 'test', type: 'string', properties: {} }; + topic.announce(params); + topic.updateValue(params, 'new value', Date.now()); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + expect(topic.lastChangedTime! - Date.now()).toBeLessThan(10); + }); + }); + + describe('announce', () => { + it('marks the topic as announced when announce is called', () => { + expect(topic.announced).toBe(false); + topic.announce({ id: 1, name: 'test', type: 'string', properties: {} }); + expect(topic.announced).toBe(true); + expect(topic.id).toEqual(1); + }); + }); + + describe('unannounce', () => { + it('marks the topic as unannounced when unannounce is called', () => { + topic.announce({ id: 1, name: 'test', type: 'string', properties: {} }); + expect(topic.announced).toBe(true); + topic.unannounce(); + expect(topic.announced).toBe(false); + }); + }); + + describe('subscribe', () => { + let callback: jest.Mock; + beforeEach(() => { + callback = jest.fn(); + }); + + it('should add the callback to the list of subscribers', () => { + topic.subscribe(callback); + expect(topic.subscribers.size).toEqual(1); + expect(topic.subscribers.values().next().value).toEqual({ + callback, + options: {}, + }); + }); + + it('should send a subscribe message to the server', () => { + const send = jest.fn(); + topic['client']['_messenger']['_socket']['sendTextFrame'] = send; + topic.subscribe(callback); + expect(send).toHaveBeenCalledWith({ + method: 'subscribe', + params: { + topics: ['test'], + subuid: expect.any(Number), + options: { + prefix: true, + }, + } as SubscribeMessageParams, + }); + }); + }); + + describe('unsubscribe', () => { + it('removes the subscriber from the topic', () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const callback: CallbackFn = (_: NetworkTablesTypes | null) => jest.fn(); + topic.subscribe(callback); + expect(topic.subscribers.size).toBe(1); + topic.unsubscribe(topic.subscribers.keys().next().value!, true); + expect(topic.subscribers.size).toBe(0); + }); + it('does nothing if the callback is not a subscriber', () => { + expect(topic.subscribers.size).toBe(0); + topic.unsubscribe(topic.subscribers.keys().next().value!); + expect(topic.subscribers.size).toBe(0); + }); + }); + + describe('unsubscribeAll', () => { + it('removes all subscribers from the topic', () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const callback: CallbackFn = (_: NetworkTablesTypes | null) => jest.fn(); + topic.subscribe(callback); + topic.subscribe(callback); + expect(topic.subscribers.size).toBe(2); + topic.unsubscribeAll(); + expect(topic.subscribers.size).toBe(0); + }); + }); + + describe('resubscribeAll', () => { + it('resubscribes all subscribers to the topic', () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const callback: CallbackFn = (_: NetworkTablesTypes | null) => jest.fn(); + topic.subscribe(callback); + topic.subscribe(callback); + expect(topic.subscribers.size).toBe(2); + topic.resubscribeAll(topic['client']); + expect(topic.subscribers.size).toBe(2); + }); + }); + + describe('notifySubscribers', () => { + it('calls the callback with the value', () => { + const callback = jest.fn(); + topic.subscribe(callback); + const params = { type: 'string', name: 'test', id: 1, properties: {} }; + topic['notifySubscribers']({ type: 'string', name: 'test', id: 1, properties: {} }, 'foo'); + expect(callback).toHaveBeenCalledWith('foo', params); + }); + }); + + describe('setProperties', () => { + it('should set the properties', () => { + topic['client']['messenger']['_socket']['sendTextFrame'] = jest.fn(); + topic.setProperties(true, true); + expect(topic['client']['messenger']['_socket']['sendTextFrame']).toHaveBeenCalledWith({ + method: 'setproperties', + params: { + name: 'test', + update: { + persistent: true, + retained: true, + }, + }, + }); + }); + }); +}); diff --git a/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.ts b/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.ts new file mode 100644 index 0000000..88bc34f --- /dev/null +++ b/packages/ntcore-ts-client/src/lib/pubsub/prefix-topic.ts @@ -0,0 +1,88 @@ +import { NetworkTablesBaseTopic } from './base-topic'; + +import type { CallbackFn } from './base-topic'; +import type { PubSubClient } from './pubsub'; +import type { + AnnounceMessageParams, + NetworkTablesTypes, + SubscribeMessageParams, + SubscribeOptions, +} from '../types/types'; + +export class NetworkTablesPrefixTopic extends NetworkTablesBaseTopic { + readonly type = 'prefix'; + + /** + * Creates a new topic. This should only be done after the + * base NTCore client has been initialized. + * @param client - The client that owns the topic. + * @param name - The name of the topic. + */ + constructor(client: PubSubClient, name: string) { + super(client, name); + + const existingTopic = this.client.getPrefixTopicFromName(name); + if (existingTopic) { + return existingTopic; + } + + this.client.registerTopic(this); + } + + /** */ + /* SUBSCRIBING */ + /** */ + + /** + * Creates a new subscriber. + * @param callback - The callback to call when the topic value changes. + * @param options - The options for the subscriber. + * @param id - The UID of the subscriber. + * @param save - Whether to save the subscriber. + * @returns The UID of the subscriber. + */ + subscribe( + callback: CallbackFn, + options: Omit = {}, + id?: number, + save = true + ) { + const subuid = id || this.client.getNextSubUID(); + + const subscribeParams: SubscribeMessageParams = { + topics: [this.name], + subuid, + options: { + ...options, + prefix: true, + }, + }; + this.client.messenger.subscribe(subscribeParams); + + if (save) this.subscribers.set(subuid, { callback, options }); + + return subuid; + } + + resubscribeAll(client: PubSubClient) { + this.client = client; + this.subscribers.forEach((info, subuid) => { + this.subscribe(info.callback, info.options, subuid, false); + }); + } + + /** + * Updates the value of a subtopic. Notifies all subscribers of the change. + * @param params - The params of the subtopic + * @param value - The value of the subtopic + * @param serverTime - The time the value was updated + */ + updateValue(params: AnnounceMessageParams, value: NetworkTablesTypes, serverTime: number) { + this._lastChangedTime = serverTime; + this.notifySubscribers(params, value); + } + + private notifySubscribers(params: AnnounceMessageParams, value: NetworkTablesTypes) { + this.subscribers.forEach((info) => info.callback(value, params)); + } +} diff --git a/packages/ntcore-ts-client/src/lib/pubsub/pubsub.spec.ts b/packages/ntcore-ts-client/src/lib/pubsub/pubsub.spec.ts index f4a9eb8..9f80445 100644 --- a/packages/ntcore-ts-client/src/lib/pubsub/pubsub.spec.ts +++ b/packages/ntcore-ts-client/src/lib/pubsub/pubsub.spec.ts @@ -9,6 +9,8 @@ describe('PubSubClient', () => { afterEach(() => { client['topics'].clear(); + client['prefixTopics'].clear(); + client['knownTopicParams'].clear(); }); it('returns the same instance when calling getInstance multiple times', () => { @@ -18,14 +20,14 @@ describe('PubSubClient', () => { }); it('registers a topic', () => { - const topic = { name: 'test' }; + const topic = { name: 'test', isRegular: () => true }; client.registerTopic(topic as never); expect(client.getTopicFromName('test')).toBe(topic); }); it('throws an error when trying to register a topic with the same name', () => { - const topic1 = { name: 'test' }; - const topic2 = { name: 'test' }; + const topic1 = { name: 'test', isRegular: () => true }; + const topic2 = { name: 'test', isRegular: () => true }; client.registerTopic(topic1 as never); expect(() => { client.registerTopic(topic2 as never); @@ -33,7 +35,7 @@ describe('PubSubClient', () => { }); it('handles updates to a topic', () => { - const topic = { name: 'test', id: 123, updateValue: jest.fn() }; + const topic = { name: 'test', id: 123, updateValue: jest.fn(), isRegular: () => true }; client.registerTopic(topic as never); client['onTopicUpdate']({ topicId: 123, @@ -43,15 +45,49 @@ describe('PubSubClient', () => { expect(topic.updateValue).toHaveBeenCalledWith('test value', expect.any(Number)); }); + it('handles updates to a prefix topic', () => { + const topic = { + name: '/testprefix/', + id: 123, + updateValue: jest.fn(), + isRegular: () => false, + isPrefix: () => true, + }; + const params = { id: 1234, name: '/testprefix/test' }; + client['knownTopicParams'].set(1234, params as never); + client.registerTopic(topic as never); + client['onTopicUpdate']({ + topicId: 1234, + value: 'test value', + serverTime: Date.now(), + } as never); + expect(topic.updateValue).toHaveBeenCalledWith(params, 'test value', expect.any(Number)); + }); + it('handles announcements for a topic', () => { - const topic = { name: 'test', announce: jest.fn() }; + const topic = { name: 'test', announce: jest.fn(), isRegular: () => true, isPrefix: () => false }; client.registerTopic(topic as never); client['onTopicAnnounce']({ id: 123, name: 'test' } as never); - expect(topic.announce).toHaveBeenCalledWith(123, undefined); + expect(client.getKnownTopicParams(123)).toEqual({ id: 123, name: 'test' }); + expect(topic.announce).toHaveBeenCalledWith({ id: 123, name: 'test' }); + }); + + it('handles announcements for a prefix topic', () => { + const topic = { name: '/testprefix/', announce: jest.fn(), isRegular: () => false, isPrefix: () => true }; + client.registerTopic(topic as never); + client['onTopicAnnounce']({ id: 1234, name: '/testprefix/test' } as never); + expect(client.getKnownTopicParams(1234)).toEqual({ id: 1234, name: '/testprefix/test' }); + expect(topic.announce).toHaveBeenCalledWith({ id: 1234, name: '/testprefix/test' }); }); it('handles unannouncements for a topic', () => { - const topic = { name: 'test', announce: jest.fn(), unannounce: jest.fn() }; + const topic = { + name: 'test', + announce: jest.fn(), + unannounce: jest.fn(), + isRegular: () => true, + isPrefix: () => false, + }; client.registerTopic(topic as never); client['onTopicAnnounce']({ id: 123, name: 'test' } as never); client['onTopicUnannounce']({ name: 'test' } as never); @@ -62,6 +98,8 @@ describe('PubSubClient', () => { const topic = { name: 'test', publisher: true, + isRegular: () => true, + isPrefix: () => false, announce: jest.fn(), resubscribeAll: jest.fn(), republish: jest.fn(), @@ -69,6 +107,8 @@ describe('PubSubClient', () => { const topic2 = { name: 'test2', publisher: true, + isRegular: () => true, + isPrefix: () => false, announce: jest.fn(), resubscribeAll: jest.fn(), republish: jest.fn(), diff --git a/packages/ntcore-ts-client/src/lib/pubsub/pubsub.ts b/packages/ntcore-ts-client/src/lib/pubsub/pubsub.ts index 724c42e..2266520 100644 --- a/packages/ntcore-ts-client/src/lib/pubsub/pubsub.ts +++ b/packages/ntcore-ts-client/src/lib/pubsub/pubsub.ts @@ -1,5 +1,7 @@ import { Messenger } from '../socket/messenger'; +import type { NetworkTablesBaseTopic } from './base-topic'; +import type { NetworkTablesPrefixTopic } from './prefix-topic'; import type { NetworkTablesTopic } from './topic'; import type { AnnounceMessageParams, @@ -12,9 +14,13 @@ import type { /** The client for the PubSub protocol. */ export class PubSubClient { private readonly _messenger: Messenger; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private topics: Map>; + private readonly topics: Map>; + private readonly prefixTopics: Map; + // topic id -> topic params + private readonly knownTopicParams: Map; private static _instances = new Map(); + private _currentPubUID = 0; + private _currentSubUID = 0; get messenger() { return this._messenger; @@ -29,6 +35,8 @@ export class PubSubClient { this.onTopicProperties ); this.topics = new Map(); + this.prefixTopics = new Map(); + this.knownTopicParams = new Map(); // In the DOM, auto-cleanup if (typeof window !== 'undefined') { @@ -64,17 +72,27 @@ export class PubSubClient { topic.resubscribeAll(this); if (topic.publisher) topic.republish(this); }); + this.prefixTopics.forEach((prefixTopic) => { + prefixTopic.resubscribeAll(this); + }); } /** * Registers a topic with this PubSubClient. * @param topic - The topic to register */ - registerTopic(topic: NetworkTablesTopic) { - if (this.topics.has(topic.name)) { - throw new Error(`Topic ${topic.name} already exists. Cannot register a topic with the same name.`); + registerTopic(topic: NetworkTablesBaseTopic) { + if (topic.isRegular()) { + if (this.topics.has(topic.name)) { + throw new Error(`Topic ${topic.name} already exists. Cannot register a topic with the same name.`); + } + this.topics.set(topic.name, topic); + } else if (topic.isPrefix()) { + if (this.prefixTopics.has(topic.name)) { + throw new Error(`Prefix topic ${topic.name} already exists. Cannot register a topic with the same name.`); + } + this.prefixTopics.set(topic.name, topic); } - this.topics.set(topic.name, topic); } /** @@ -83,11 +101,23 @@ export class PubSubClient { */ private onTopicUpdate = (message: BinaryMessageData) => { const topic = this.getTopicFromId(message.topicId); - if (!topic) { - console.warn('Received message for unknown topic', message); - return; + if (topic) { + topic.updateValue(message.value, message.serverTime); + } + + const knownTopic = this.getKnownTopicParams(message.topicId); + + if (knownTopic) { + this.prefixTopics.forEach((prefixTopic) => { + if (knownTopic.name.startsWith(prefixTopic.name)) { + prefixTopic.updateValue(knownTopic, message.value, message.serverTime); + } + }); + } + + if (!topic && !knownTopic) { + console.warn(`Received update for unknown topic with ID ${message.topicId}`); } - topic.updateValue(message.value, message.serverTime); }; /** @@ -95,12 +125,18 @@ export class PubSubClient { * @param params - The announce message parameters. */ private onTopicAnnounce = (params: AnnounceMessageParams) => { + this.knownTopicParams.set(params.id, params); + + // Announce to the topic const topic = this.topics.get(params.name); - if (!topic) { - console.warn(`Topic ${params.name} was announced, but does not exist`); - return; - } - topic.announce(params.id, params.pubuid); + topic?.announce(params); + + // Find all prefix topics that match the announced topic + this.prefixTopics.forEach((prefixTopic) => { + if (params.name.startsWith(prefixTopic.name)) { + prefixTopic.announce(params); + } + }); }; /** @@ -144,12 +180,13 @@ export class PubSubClient { * @param topicId - The ID of the topic to get. * @returns The topic with the given ID, or null if no topic with that ID exists. */ - private getTopicFromId(topicId: number) { + private getTopicFromId(topicId: number): NetworkTablesTopic | null { for (const topic of this.topics.values()) { if (topic.id === topicId) { return topic; } } + return null; } @@ -162,15 +199,51 @@ export class PubSubClient { return this.topics.get(topicName) ?? null; } + /** + * Gets the topic with the given name. + * @param topicName - The name of the topic to get. + * @returns The topic with the given name, or null if no topic with that name exists. + */ + getPrefixTopicFromName(topicName: string) { + return this.prefixTopics.get(topicName) ?? null; + } + + /** + * Gets the known announcement parameters for a topic. + * @param id - The ID of the topic. + * @returns The known announcement parameters for the topic, or undefined if the topic is not known. + */ + getKnownTopicParams(id: number) { + return this.knownTopicParams.get(id); + } + /** * Cleans up the client by unsubscribing from all topics and stopping publishing for all topics. */ cleanup() { this.topics.forEach((topic) => { topic.unsubscribeAll(); - if (topic.publisher) topic.unpublish(); }); + this.prefixTopics.forEach((prefixTopic) => { + prefixTopic.unsubscribeAll(); + }); this._messenger.socket.close(); } + + /** + * Gets the next available publisher UID. + * @returns The next available publisher UID. + */ + getNextPubUID() { + return this._currentPubUID++; + } + + /** + * Gets the next available subscriber UID. + * @returns The next available subscriber UID. + */ + getNextSubUID() { + return this._currentSubUID++; + } } diff --git a/packages/ntcore-ts-client/src/lib/pubsub/topic.spec.ts b/packages/ntcore-ts-client/src/lib/pubsub/topic.spec.ts index 1f532dc..685f9b5 100644 --- a/packages/ntcore-ts-client/src/lib/pubsub/topic.spec.ts +++ b/packages/ntcore-ts-client/src/lib/pubsub/topic.spec.ts @@ -39,7 +39,7 @@ describe('Topic', () => { NetworkTablesTypeInfos.kString, 'default' ); - expect(topic).toBe(newTopic); + expect(newTopic).toBe(topic); }); it('should error if the existing topic has a different type', () => { @@ -94,7 +94,7 @@ describe('Topic', () => { describe('updateValue', () => { it('updates the value correctly', () => { - topic.announce(1); + topic.announce({ id: 1, name: 'test', type: 'string', properties: {} }); topic.updateValue('new value', Date.now()); expect(topic.getValue()).toEqual('new value'); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -105,7 +105,7 @@ describe('Topic', () => { describe('announce', () => { it('marks the topic as announced when announce is called', () => { expect(topic.announced).toBe(false); - topic.announce(1); + topic.announce({ id: 1, name: 'test', type: 'string', properties: {} }); expect(topic.announced).toBe(true); expect(topic.id).toEqual(1); }); @@ -113,7 +113,7 @@ describe('Topic', () => { describe('unannounce', () => { it('marks the topic as unannounced when unannounce is called', () => { - topic.announce(1); + topic.announce({ id: 1, name: 'test', type: 'string', properties: {} }); expect(topic.announced).toBe(true); topic.unannounce(); expect(topic.announced).toBe(false); @@ -131,7 +131,6 @@ describe('Topic', () => { expect(topic.subscribers.size).toEqual(1); expect(topic.subscribers.values().next().value).toEqual({ callback, - immediateNotify: false, options: {}, }); }); @@ -139,7 +138,7 @@ describe('Topic', () => { it('should send a subscribe message to the server', () => { const send = jest.fn(); topic['client']['_messenger']['_socket']['sendTextFrame'] = send; - topic.subscribe(callback, true); + topic.subscribe(callback); expect(send).toHaveBeenCalledWith({ method: 'subscribe', params: { @@ -149,18 +148,6 @@ describe('Topic', () => { } as SubscribeMessageParams, }); }); - - it('should immediately notify the callback if immediateNotify is true and there is a value', () => { - topic['value'] = 'foo'; - topic.subscribe(callback, true); - expect(callback).toHaveBeenCalledWith('foo'); - }); - - it('should not immediately notify the callback if immediateNotify is false', () => { - topic['value'] = 'foo'; - topic.subscribe(callback, false); - expect(callback).not.toHaveBeenCalled(); - }); }); describe('unsubscribe', () => { @@ -168,7 +155,7 @@ describe('Topic', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const callback = (_: string | null) => jest.fn(); const options = {}; - topic.subscribe(callback, true, options); + topic.subscribe(callback, options); expect(topic.subscribers.size).toBe(1); topic.unsubscribe(topic.subscribers.keys().next().value!, true); expect(topic.subscribers.size).toBe(0); @@ -185,8 +172,8 @@ describe('Topic', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const callback = (_: string | null) => jest.fn(); const options = {}; - topic.subscribe(callback, true, options); - topic.subscribe(callback, true, options); + topic.subscribe(callback, options); + topic.subscribe(callback, options); expect(topic.subscribers.size).toBe(2); topic.unsubscribeAll(); expect(topic.subscribers.size).toBe(0); @@ -198,8 +185,8 @@ describe('Topic', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const callback = (_: string | null) => jest.fn(); const options = {}; - topic.subscribe(callback, true, options); - topic.subscribe(callback, true, options); + topic.subscribe(callback, options); + topic.subscribe(callback, options); expect(topic.subscribers.size).toBe(2); topic.resubscribeAll(topic['client']); expect(topic.subscribers.size).toBe(2); @@ -212,7 +199,7 @@ describe('Topic', () => { topic.subscribe(callback); topic['value'] = 'foo'; topic['notifySubscribers'](); - expect(callback).toHaveBeenCalledWith('foo'); + expect(callback).toHaveBeenCalledWith('foo', null); }); }); diff --git a/packages/ntcore-ts-client/src/lib/pubsub/topic.ts b/packages/ntcore-ts-client/src/lib/pubsub/topic.ts index 69ddb7a..7d23fdf 100644 --- a/packages/ntcore-ts-client/src/lib/pubsub/topic.ts +++ b/packages/ntcore-ts-client/src/lib/pubsub/topic.ts @@ -1,53 +1,25 @@ -import { Util } from '../util/util'; +import { NetworkTablesBaseTopic } from './base-topic'; +import type { CallbackFn } from './base-topic'; import type { PubSubClient } from './pubsub'; import type { AnnounceMessage, + AnnounceMessageParams, NetworkTablesTypeInfo, NetworkTablesTypes, - PropertiesMessage, PublishMessageParams, - SetPropertiesMessageParams, SubscribeMessageParams, SubscribeOptions, TopicProperties, } from '../types/types'; -export class NetworkTablesTopic { - private client: PubSubClient; - private _id?: number; - private readonly _name: string; - private readonly _typeInfo: NetworkTablesTypeInfo; +export class NetworkTablesTopic extends NetworkTablesBaseTopic { + readonly type = 'regular'; private value: T | null; - private _lastChangedTime?: number; - private _announced: boolean; + private readonly _typeInfo: NetworkTablesTypeInfo; private _publisher: boolean; private _pubuid?: number; private _publishProperties?: TopicProperties; - private _subscribers: Map< - number, - { - callback: (_: T | null) => void; - immediateNotify: boolean; - options: SubscribeOptions; - } - >; - - /** - * Gets the ID of the topic. - * @returns The ID of the topic. - */ - get id() { - return this._id; - } - - /** - * Gets the name of the topic. - * @returns The name of the topic. - */ - get name() { - return this._name; - } /** * Gets the type info for the topic. @@ -57,22 +29,6 @@ export class NetworkTablesTopic { return this._typeInfo; } - /** - * Gets the server time of the last value change. - * @returns The server time of the last value change. - */ - get lastChangedTime() { - return this._lastChangedTime; - } - - /** - * Whether the topic has been announced. - * @returns Whether the topic has been announced. - */ - get announced() { - return this._announced; - } - /** * Gets whether the client is the publisher of the topic. * @returns Whether the client is the publisher of the topic. @@ -89,14 +45,6 @@ export class NetworkTablesTopic { return this._pubuid; } - /** - * Gets the subscribers to the topic. - * @returns The subscribers to the topic. - */ - get subscribers() { - return this._subscribers; - } - /** * Creates a new topic. This should only be done after the * base NTCore client has been initialized. @@ -106,13 +54,10 @@ export class NetworkTablesTopic { * @param defaultValue - The default value for the topic. */ constructor(client: PubSubClient, name: string, typeInfo: NetworkTablesTypeInfo, defaultValue?: T) { - this.client = client; - this._name = name; + super(client, name); this._typeInfo = typeInfo; this.value = defaultValue ?? null; - this._announced = false; this._publisher = false; - this._subscribers = new Map(); const existingTopic = this.client.getTopicFromName(name); if (existingTopic) { @@ -140,6 +85,10 @@ export class NetworkTablesTopic { this.client.updateServer(this, value); } + /** + * Gets the value of the topic. + * @returns The value of the topic. + */ getValue() { return this.value; } @@ -162,44 +111,29 @@ export class NetworkTablesTopic { /** * Marks the topic as announced. This should only be called by the PubSubClient. - * @param id - The ID of the topic. - * @param pubuid - The UID of the publisher. + * @param params - The parameters of the announcement. */ - announce(id: number, pubuid?: number) { - this._announced = true; - this._id = id; - if (pubuid === this._pubuid) { + override announce(params: AnnounceMessageParams) { + super.announce(params); + if (params.pubuid === this._pubuid) { this._publisher = true; } } - /** Marks the topic as unannounced. This should only be called by the PubSubClient. */ - unannounce() { - this._announced = false; - this._id = undefined; - } - /** */ /* SUBSCRIBING */ /** */ /** - * Creates a new subscriber. This should only be called by the PubSubClient. + * Creates a new subscriber. * @param callback - The callback to call when the topic value changes. - * @param immediateNotify - Whether to immediately notify the subscriber of the current value. * @param options - The options for the subscriber. - * @param id - The UID of the subscriber. + * @param id - The UID of the subscriber. You must verify that the ID is not already in use. * @param save - Whether to save the subscriber. * @returns The UID of the subscriber. */ - subscribe( - callback: (_: T | null) => void, - immediateNotify = false, - options: SubscribeOptions = {}, - id?: number, - save = true - ) { - const subuid = id || Util.generateUid(); + subscribe(callback: CallbackFn, options: Omit = {}, id?: number, save = true) { + const subuid = id || this.client.getNextSubUID(); const subscribeParams: SubscribeMessageParams = { topics: [this.name], @@ -208,38 +142,15 @@ export class NetworkTablesTopic { }; this.client.messenger.subscribe(subscribeParams); - if (immediateNotify) callback(this.value); - - if (save) this.subscribers.set(subuid, { callback, immediateNotify, options }); + if (save) this.subscribers.set(subuid, { callback, options }); return subuid; } - /** - * Removes a subscriber - * @param subuid - The UID of the subscriber. - * @param removeCallback - Whether to remove the callback. Leave this as true unless you know what you're doing. - */ - unsubscribe(subuid: number, removeCallback = true) { - this.client.messenger.unsubscribe(subuid); - if (removeCallback) this.subscribers.delete(subuid); - } - - /** - * Removes all local subscribers. - */ - unsubscribeAll() { - this.subscribers.forEach((_, subuid) => this.unsubscribe(subuid)); - } - - /** - * Resubscribes all local subscribers. - * @param client - The client to resubscribe with. - */ resubscribeAll(client: PubSubClient) { this.client = client; this.subscribers.forEach((info, subuid) => { - this.subscribe(info.callback, info.immediateNotify, info.options, subuid, false); + this.subscribe(info.callback, info.options, subuid, false); }); } @@ -247,7 +158,9 @@ export class NetworkTablesTopic { * Notifies all subscribers of the current value. */ private notifySubscribers() { - this.subscribers.forEach((info) => info.callback(this.value)); + // We know that _announceParams is not null here because we received a value update + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.subscribers.forEach((info) => info.callback(this.value, this._announceParams!)); } /** */ @@ -257,13 +170,13 @@ export class NetworkTablesTopic { /** * Publishes the topic. * @param properties - The properties to publish the topic with. - * @param id - The UID of the publisher. + * @param id - The UID of the publisher. You must verify that the ID is not already in use. * @returns A promise that resolves when the topic is published. */ async publish(properties: TopicProperties = {}, id?: number): Promise { if (this.publisher) return; - this._pubuid = id ?? Util.generateUid(); + this._pubuid = id ?? this.client.getNextPubUID(); this._publishProperties = properties; const publishParams: PublishMessageParams = { @@ -305,23 +218,4 @@ export class NetworkTablesTopic { return await this.publish(this._publishProperties, this._pubuid); } - - /** - * Sets the properties of the topic. - * @param persistent - If true, the last set value will be periodically saved to persistent storage on the server and be restored during server startup. Topics with this property set to true will not be deleted by the server when the last publisher stops publishing. - * @param retained - Topics with this property set to true will not be deleted by the server when the last publisher stops publishing. - * @returns The server's response. - */ - async setProperties(persistent?: boolean, retained?: boolean): Promise { - const setPropertiesParams: SetPropertiesMessageParams = { - name: this.name, - update: { - persistent, - retained, - }, - }; - - // Send the set properties request - return await this.client.messenger.setProperties(setPropertiesParams); - } } diff --git a/packages/ntcore-ts-client/src/lib/socket/messenger.ts b/packages/ntcore-ts-client/src/lib/socket/messenger.ts index ccea568..91ecb2e 100644 --- a/packages/ntcore-ts-client/src/lib/socket/messenger.ts +++ b/packages/ntcore-ts-client/src/lib/socket/messenger.ts @@ -190,11 +190,11 @@ export class Messenger { this._socket.sendTextFrame(message); // Reject the promise if the topic is not announced within 3 seconds - setTimeout(() => { - if (this.socket.isConnected()) { + this.socket.waitForConnection().then(() => { + setTimeout(() => { reject(new Error(`Topic ${params.name} was not announced within 3 seconds`)); - } - }, 3000); + }, 3000); + }); }); } diff --git a/packages/ntcore-ts-client/src/lib/socket/socket.ts b/packages/ntcore-ts-client/src/lib/socket/socket.ts index bfbb0cd..e9aa621 100644 --- a/packages/ntcore-ts-client/src/lib/socket/socket.ts +++ b/packages/ntcore-ts-client/src/lib/socket/socket.ts @@ -22,10 +22,8 @@ export class NetworkTablesSocket { private static instances = new Map(); private static readonly PROTOCOL_V4_0 = 'networktables.first.wpi.edu'; private static readonly PROTOCOL_V4_1 = 'v4.1.networktables.first.wpi.edu'; - private static readonly RTT_PROTOCOL = 'rtt.networktables.first.wpi.edu'; private static readonly RECONNECT_TIMEOUT = 1000; private static readonly RTT_PERIOD_V4_0 = 1000; - private static readonly RTT_PERIOD_V4_1 = 250; private static readonly TIMEOUT_V4_1 = 1000; private readonly connectionListeners = new Set<(_: boolean) => void>(); @@ -33,8 +31,6 @@ export class NetworkTablesSocket { private offset = 0; private bestRtt = -1; - private _rttWebsocket: WebSocket | null = null; - private _websocket: WebSocket; get websocket() { return this._websocket; @@ -43,9 +39,6 @@ export class NetworkTablesSocket { set websocket(websocket: WebSocket) { this._websocket = websocket; } - - private _disconnectTimout: NodeJS.Timeout | null = null; - private serverUrl: string; private readonly onSocketOpen: () => void; @@ -81,7 +74,6 @@ export class NetworkTablesSocket { ) { // Connect to the server using the provided URL this._websocket = new WebSocket(serverUrl, [NetworkTablesSocket.PROTOCOL_V4_1, NetworkTablesSocket.PROTOCOL_V4_0]); - this._rttWebsocket = new WebSocket(serverUrl, NetworkTablesSocket.RTT_PROTOCOL); this.serverUrl = serverUrl; this.onSocketOpen = onSocketOpen; this.onSocketClose = onSocketClose; @@ -140,51 +132,45 @@ export class NetworkTablesSocket { * the socket to refresh itself. */ private init() { - let heartbeatInterval: ReturnType; + let heartbeatInterval: ReturnType | undefined; if (this._websocket) { // Open handler this._websocket.onopen = () => { - this.updateConnectionListeners(); - this.onSocketOpen(); - // eslint-disable-next-line no-console - console.info('Robot Connected!'); - this.sendQueuedMessages(); - }; + // Setup heartbeat or RTT - if (this._websocket.protocol === 'v4.1.networktables.first.wpi.edu') { - // eslint-disable-next-line no-console - console.info('Connected on NT 4.1'); - this.initializeRTTWebsocket(); - } else { - // eslint-disable-next-line no-console - console.info('Connected on NT 4.0'); - } + if (this._websocket.protocol === 'v4.1.networktables.first.wpi.edu') { + // eslint-disable-next-line no-console + console.info('Connected on NT 4.1'); + } else { + // eslint-disable-next-line no-console + console.info('Connected on NT 4.0'); - // If running NT 4.1, start websocket heartbeat for RTT - if (this._rttWebsocket !== null) { - this._rttWebsocket.onopen = () => { // Start heartbeat + // Only send heartbeat at this rate if we are on NT 4.0 heartbeatInterval = setInterval(() => { - this.heartbeat(); - }, NetworkTablesSocket.RTT_PERIOD_V4_1); - }; - } else { - // Start heartbeat - // Only send heartbeat at this rate if we are on NT 4.0 - heartbeatInterval = setInterval(() => { - if (this.isConnected()) { - this.heartbeat(); - } - }, NetworkTablesSocket.RTT_PERIOD_V4_0); - } + if (this.isConnected()) { + this.heartbeat(); + } + }, NetworkTablesSocket.RTT_PERIOD_V4_0); + } + + // eslint-disable-next-line no-console + console.info('Robot Connected!'); + this.updateConnectionListeners(); + this.onSocketOpen(); + this.sendQueuedMessages(); + }; // Close handler this._websocket.onclose = (e: CloseEvent | WS_CloseEvent) => { // Notify client and cancel heartbeat this.updateConnectionListeners(); this.onSocketClose(); - clearInterval(heartbeatInterval); + + if (heartbeatInterval != null) { + clearInterval(heartbeatInterval); + } // Lost connection message console.warn('Unable to connect to Robot', e.reason); @@ -197,7 +183,6 @@ export class NetworkTablesSocket { NetworkTablesSocket.PROTOCOL_V4_1, NetworkTablesSocket.PROTOCOL_V4_0, ]); - this._rttWebsocket = new WebSocket(this.serverUrl, NetworkTablesSocket.RTT_PROTOCOL); this.init(); }, NetworkTablesSocket.RECONNECT_TIMEOUT); } @@ -205,47 +190,9 @@ export class NetworkTablesSocket { this._websocket.binaryType = 'arraybuffer'; - if (this._rttWebsocket !== null) { - this._rttWebsocket.binaryType = 'arraybuffer'; - } - // Set up event listeners for messages and errors this._websocket.onmessage = (event: MessageEvent | WS_MessageEvent) => this.onMessage(event); this._websocket.onerror = (event: Event | WS_ErrorEvent) => this.onError(event); - - if (this._rttWebsocket !== null) { - this._rttWebsocket.onmessage = (event: MessageEvent | WS_MessageEvent) => this.onRTTMessage(event); - this._rttWebsocket.onerror = (event: Event | WS_ErrorEvent) => this.onError(event); - } - } - } - - private initializeRTTWebsocket() { - if (this._rttWebsocket === null) { - this._rttWebsocket = new WebSocket(this.serverUrl, NetworkTablesSocket.RTT_PROTOCOL); - this._rttWebsocket.binaryType = 'arraybuffer'; - this.resetTimeout(); - this._rttWebsocket.onmessage = (event: MessageEvent | WS_MessageEvent) => this.onMessage(event); - this._rttWebsocket.onerror = (event: Event | WS_ErrorEvent) => this.onError(event); - } - } - - /** - * Handle resetting the timeout for auto disconnect if no heartbeat is received in a certain amount of time. - * - * This will only be used for NT 4.1 currently to preserve old behavior. - */ - private resetTimeout() { - if (this._disconnectTimout !== null) { - clearTimeout(this._disconnectTimout); - } - if (this._rttWebsocket !== null) { - this._disconnectTimout = setTimeout(() => { - // eslint-disable-next-line no-console - console.error(`No NT heartbeat received in ${NetworkTablesSocket.TIMEOUT_V4_1} ms. Closing...`); - this._websocket.close(); - this._rttWebsocket?.close(); - }, NetworkTablesSocket.TIMEOUT_V4_1); } } @@ -365,7 +312,6 @@ export class NetworkTablesSocket { * @param event - The message event. */ private onMessage(event: MessageEvent | WS_MessageEvent) { - this.resetTimeout(); this.connectionListeners?.forEach((f) => f(this.isConnected())); if (event.data instanceof ArrayBuffer || event.data instanceof Uint8Array) { @@ -375,12 +321,6 @@ export class NetworkTablesSocket { } } - private onRTTMessage(event: MessageEvent | WS_MessageEvent) { - if (event.data instanceof ArrayBuffer || event.data instanceof Uint8Array) { - this.handleBinaryFrame(event.data); - } - } - /** * Handle an error from the websocket. * @param event - The error event. @@ -568,7 +508,6 @@ export class NetworkTablesSocket { */ close() { this._websocket.close(); - this._rttWebsocket?.close(); } } diff --git a/packages/ntcore-ts-client/src/lib/util/util.spec.ts b/packages/ntcore-ts-client/src/lib/util/util.spec.ts index d1a74da..3807f74 100644 --- a/packages/ntcore-ts-client/src/lib/util/util.spec.ts +++ b/packages/ntcore-ts-client/src/lib/util/util.spec.ts @@ -1,4 +1,3 @@ -import { integerSchema } from '../types/schemas'; import { NetworkTablesTypeInfos } from '../types/types'; import { Util } from './util'; @@ -199,27 +198,6 @@ describe('Util', () => { }); }); - describe('generateUid', () => { - let id1: number; - let id2: number; - - beforeEach(() => { - id1 = Util.generateUid(); - id2 = Util.generateUid(); - }); - - it('should be a positive integer', () => { - // make sure it's an integer - expect(id1).toBeGreaterThanOrEqual(0); - expect(id2).toBeGreaterThanOrEqual(0); - expect(integerSchema.safeParse(id1).success).toBe(true); - expect(integerSchema.safeParse(id2).success).toBe(true); - }); - it('generates a different ID', () => { - expect(id1).not.toEqual(id2); - }); - }); - describe('splitArrayBuffer', () => { it('splits an ArrayBuffer into chunks of the specified size', () => { const buffer = new ArrayBuffer(51); diff --git a/packages/ntcore-ts-client/src/lib/util/util.ts b/packages/ntcore-ts-client/src/lib/util/util.ts index 6bd223d..d8168c6 100644 --- a/packages/ntcore-ts-client/src/lib/util/util.ts +++ b/packages/ntcore-ts-client/src/lib/util/util.ts @@ -1,5 +1,3 @@ -import { v4 as uuidv4 } from 'uuid'; - import { NetworkTablesTypeInfos } from '../types/types'; import type { BinaryMessage, NetworkTablesTypeInfo, NetworkTablesTypes, TypeNum, TypeString } from '../types/types'; @@ -138,30 +136,6 @@ export class Util { return [topicId, timestamp, type[0], data]; } - /** - * Get a decently unique integer ID. - * - * It is not guaranteed to be unique, but it uses uuidv4 to generate an integer ID. - * @returns An ID. - */ - static generateUid(): number { - const uuid = uuidv4(); - let id = 0; - for (let i = 0; i < uuid.length; i++) { - id += uuid.charCodeAt(i); - } - - const uid = id + Date.now(); - - // Just in case - if (Util.usedIds.has(uid)) { - return this.generateUid(); - } - - Util.usedIds.add(uid); - return uid; - } - /** * Splits an ArrayBuffer into chunks of a specified size. * @param buffer - The ArrayBuffer to split. @@ -190,7 +164,7 @@ export class Util { * @returns The server URL with a unique client ID. */ static createServerUrl(uri: string, port: number): string { - return `ws://${uri}:${port}/nt/ntcore-ts-${Util.generateUid()}`; + return `ws://${uri}:${port}/nt/ntcore-ts-${Math.floor(Math.random() * 1000)}`; } /**