diff --git a/.config/.readthedocs.yaml b/.config/.readthedocs.yaml index 7ea3e19..5ab6a0e 100644 --- a/.config/.readthedocs.yaml +++ b/.config/.readthedocs.yaml @@ -8,8 +8,14 @@ version: 2 build: os: ubuntu-22.04 tools: - # rust: latest + nodejs: latest + rust: latest python: latest + jobs: + pre_build: + - yarn install + - yarn build:debug + - yarn docs mkdocs: configuration: docs/mkdocs.yml @@ -20,3 +26,5 @@ mkdocs: python: install: - requirements: docs/requirements.txt + - method: pip + path: '.' diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 97f2724..5114299 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,7 +30,16 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - uses: actions/setup-node@v4 + with: + node-version: 20.x + - run: yarn install + - name: Build Node.js type definitions + run: yarn build:debug + - name: Generate Node.js API docs + run: yarn docs - run: pip install -r docs/requirements.txt + - run: pip install . - run: just docs-build - name: Save docs build as artifact uses: actions/upload-artifact@v4 diff --git a/.gitignore b/.gitignore index e0d0629..c829c4c 100644 --- a/.gitignore +++ b/.gitignore @@ -350,6 +350,3 @@ Cargo.lock # coverage output coverage.json lcov.info - -# supplemental docs build -docs/site/ diff --git a/bindings/node/Cargo.toml b/bindings/node/Cargo.toml index 3c74666..7aa6b47 100644 --- a/bindings/node/Cargo.toml +++ b/bindings/node/Cargo.toml @@ -7,9 +7,9 @@ version = "0.0.0" crate-type = ["cdylib"] [dependencies] -# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix -napi = { version = "2.12.2", default-features = false, features = ["napi4"] } -napi-derive = "2.12.2" +# Default `napi` features: see https://nodejs.org/api/n-api.html#node-api-version-matrix +napi = "2.16.13" +napi-derive = "2.16.12" [build-dependencies] napi-build = "2.0.1" diff --git a/bindings/node/README.md b/bindings/node/README.md new file mode 100644 index 0000000..15b4e8e --- /dev/null +++ b/bindings/node/README.md @@ -0,0 +1,41 @@ +# `@rf24/rf24` + +The node.js binding for the [rf24-rs] project (written in rust). + +[rf24-rs]: https://github.com/nRF24/rf24-rs + +This package is only functional on Linux machines. +Although, installing this package in non-Linux environments will +provide the typing information used on Linux. + +## Install + +To install from npmjs.org: + +```text +npm install @rf24/rf24 +``` + +To build from source: + +```text +yarn install +yarn build:debug +``` + +## Examples + +The examples are written in Typescript and located in the repository's root path "examples/node/ts". +To compile them to Javascript, run the following commands: + +```text +yarn install +yarn examples-build +``` + +Afterwards the Javascript files are located "examples/node/js". +To run them just pass the example file's path to the node interpreter: + +```text +node examples/node/js/gettingStarted.js +``` diff --git a/bindings/node/src/lib.rs b/bindings/node/src/lib.rs index bee4097..b499dc5 100644 --- a/bindings/node/src/lib.rs +++ b/bindings/node/src/lib.rs @@ -1,6 +1,6 @@ -mod types; #[cfg(target_os = "linux")] mod radio; +mod types; #[macro_use] extern crate napi_derive; diff --git a/bindings/node/src/radio.rs b/bindings/node/src/radio.rs index e0071a0..a2c8eb7 100644 --- a/bindings/node/src/radio.rs +++ b/bindings/node/src/radio.rs @@ -1,8 +1,8 @@ #![cfg(target_os = "linux")] use crate::types::{ - AvailablePipe, HardwareConfig, NodeCrcLength, NodeDataRate, NodeFifoState, NodePaLevel, - NodeStatusFlags, WriteConfig, + AvailablePipe, CrcLength, DataRate, FifoState, HardwareConfig, PaLevel, StatusFlags, + WriteConfig, }; use linux_embedded_hal::{ gpio_cdev::{chips, LineRequestFlags}, @@ -11,17 +11,27 @@ use linux_embedded_hal::{ }; use napi::{bindgen_prelude::Buffer, Error, Result, Status}; -use rf24::radio::{prelude::*, RF24}; -use rf24::StatusFlags; +use rf24::radio::prelude::*; +/// This class provides the user facing API to interact with a nRF24L01 transceiver. #[napi(js_name = "RF24")] -pub struct NodeRF24 { - inner: RF24, +pub struct RF24 { + inner: rf24::radio::RF24, read_buf: [u8; 32], } #[napi] -impl NodeRF24 { +impl RF24 { + /// Construct an object to control the radio. + /// + /// @param cePin - The GPIO pin number connected to the radio's CE pin. + /// @param csPin - The identifying number for the SPI bus' CS pin; + /// also labeled as "CEx" (where "x" is this parameter's value) on many + /// Raspberry Pi pin diagrams. See {@link HardwareConfig.devSpiBus} for more detail. + /// @param hardwareConfig - Optional parameters to fine tune hardware configuration + /// (like SPI bus number and GPIO chip number). + /// + /// @group Basic #[napi(constructor)] pub fn new(ce_pin: u32, cs_pin: u8, hardware_config: Option) -> Result { // convert optional arg to default values @@ -93,11 +103,17 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}")))?; Ok(Self { - inner: RF24::new(ce_pin, spi, Delay), + inner: rf24::radio::RF24::new(ce_pin, spi, Delay), read_buf: [0u8; 32], }) } + /// Initialize the radio on the configured hardware (as specified to {@link RF24} constructor). + /// + /// @throws A Generic Error if a hardware failure caused problems + /// (includes a message to describe what problem was detected). + /// + /// @group Basic #[napi] pub fn begin(&mut self) -> Result<()> { self.inner @@ -105,11 +121,21 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Is the radio in active RX mode? + /// + /// @group Basic #[napi(getter)] pub fn is_listening(&self) -> bool { self.inner.is_listening() } + /// Put the radio into active RX mode. + /// + /// > [!WARNING] + /// > Do not call {@link RF24.send} while in active RX mode because (internally in rust) + /// > that _will_ cause an infinite loop. + /// + /// @group Basic #[napi] pub fn start_listening(&mut self) -> Result<()> { self.inner @@ -117,6 +143,11 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Deactivates active RX mode and puts the radio into an inactive TX mode. + /// + /// The datasheet recommends idling the radio in an inactive TX mode. + /// + /// @group Basic #[napi] pub fn stop_listening(&mut self) -> Result<()> { self.inner @@ -124,6 +155,18 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Blocking function that loads a given `buf` into the TX FIFO, waits for a response + /// (if auto-ack is enabled), then returns a Boolean describing success. + /// + /// @param buf - The buffer of bytes to transmit. + /// @param askNoAck - A flag to disable the auto-ack feature for the given payload in `buf`. + /// This has no effect if auto-ack is disabled or + /// {@link RF24.allowAskNoAck | `RF24.allowAskNoAck()`} is not enabled. + /// + /// @returns A boolean that describes if transmission is successful or not. + /// This will always return true if auto-ack is disabled. + /// + /// @group Basic #[napi] pub fn send(&mut self, buf: Buffer, ask_no_ack: Option) -> Result { let buf = buf.to_vec(); @@ -132,6 +175,19 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// A non-blocking function that uploads a given `buf` to the radio's TX FIFO. + /// + /// This is a helper function to {@link RF24.send | `RF24.send()`}. + /// Use this in combination with {@link RF24.update | `RF24.update()`} and + /// {@link RF24.getStatusFlags | `RF24.getStatusFlags()`} + /// to determine if transmission was successful. + /// + /// @param buf - The buffer of bytes to load into the TX FIFO. + /// + /// @returns A Boolean that describes if the given `buf` was successfully loaded + /// into the TX FIFO. + /// + /// @group Advanced #[napi] pub fn write(&mut self, buf: Buffer, write_config: Option) -> Result { let buf = buf.to_vec(); @@ -145,6 +201,19 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Read data from the radio's RX FIFO. + /// + /// Use {@link RF24.available | `RF24.available()`} to determine if there is data ready to read from the RX FIFO. + /// + /// @param len - An optional number of bytes to read from the FIFO. This is capped at `32`. + /// If not specified, then the length of the next available payload is used (which automatically + /// respects if dynamic payloads are enabled). + /// + /// Use {@link RF24.setDynamicPayloads | `RF24.setDynamicPayloads()`} for dynamically sized + /// payload or {@link RF24.setPayloadLength | `RF24.setPayloadLength()`} for statically sized + /// payloads. + /// + /// @group Basic #[napi] pub fn read(&mut self, len: Option) -> Result { let len = self @@ -154,6 +223,12 @@ impl NodeRF24 { Ok(Buffer::from(&self.read_buf[0..len as usize])) } + /// A blocking function to resend a failed payload in the TX FIFO. + /// + /// This is similar to {@link RF24.send | `RF24.send`} but specifically for + /// failed transmissions. + /// + /// @group Basic #[napi] pub fn resend(&mut self) -> Result { self.inner @@ -161,6 +236,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// A non-blocking function to restart a failed transmission. + /// + /// This is a helper function to {@link RF24.resend | `RF24.resend()`}. + /// Use {@link RF24.update | `RF24.update()`} and + /// {@link RF24.getStatusFlags | `RF24.getStatusFlags()`} to determine if + /// retransmission was successful. + /// + /// @group Advanced #[napi] pub fn rewrite(&mut self) -> Result<()> { self.inner @@ -168,6 +251,15 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the Automatic Retry Count (ARC) of attempts made during the last transmission. + /// + /// This resets with every new transmission. The returned value is meaningless if the + /// auto-ack feature is disabled. + /// + /// Use {@link RF24.setAutoRetries | `RF24.setAutoRetries()`} to configure the + /// automatic retries feature. + /// + /// @group Advanced #[napi] pub fn get_last_arc(&mut self) -> Result { self.inner @@ -175,11 +267,21 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// A property that describes if the radio is a nRF24L01+ or not. + /// + /// @group Configuration #[napi(getter)] pub fn is_plus_variant(&self) -> bool { self.inner.is_plus_variant() } + /// A property that describes the radio's Received Power Detection (RPD). + /// + /// This is reset upon entering RX mode and is only set if the radio detects a + /// signal if strength -64 dBm or greater (actual threshold may vary depending + /// on radio model). + /// + /// @group Advanced #[napi(getter)] pub fn rpd(&mut self) -> Result { self.inner @@ -187,13 +289,31 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Start a constant carrier wave on the given `channel` using the specified + /// power amplitude `level`. + /// + /// This functionality is only useful for testing the radio hardware works as a + /// transmitter. + /// + /// @param level - The Power Amplitude level to use when transmitting. + /// @param channel - The channel (radio's frequency) used to transmit. + /// The channel should not be changed while transmitting because it can cause + /// undefined behavior. + /// + /// @group Advanced #[napi] - pub fn start_carrier_wave(&mut self, level: NodePaLevel, channel: u8) -> Result<()> { + pub fn start_carrier_wave(&mut self, level: PaLevel, channel: u8) -> Result<()> { self.inner .start_carrier_wave(level.into_inner(), channel) .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Stop transmitting the constant carrier wave. + /// + /// {@link RF24.startCarrierWave | `RF24.startCarrierWave()`} should be called before + /// this function. + /// + /// @group Advanced #[napi] pub fn stop_carrier_wave(&mut self) -> Result<()> { self.inner @@ -201,6 +321,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Enable or disable the LNA feature. + /// + /// On nRF24L01+ modules with a builtin antenna, this feature is always enabled. + /// For clone's and module's with a separate PA/LNA circuit (external antenna), + /// this function may not behave exactly as expected. Consult the radio module's + /// manufacturer. + /// + /// @group Configuration #[napi] pub fn set_lna(&mut self, enable: bool) -> Result<()> { self.inner @@ -208,6 +336,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Enable or disable the custom ACK payloads attached to auto-ack packets. + /// + /// > [!IMPORTANT] + /// > This feature requires dynamically sized payloads. + /// > Use {@link RF24.setDynamicPayloads | `RF24.setDynamicPayloads(true)`} + /// > to enable dynamically sized payloads. + /// + /// @group Configuration #[napi] pub fn allow_ack_payloads(&mut self, enable: bool) -> Result<()> { self.inner @@ -215,6 +351,13 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Enable or disable the auto-ack feature for all pipes. + /// + /// > [!NOTE] + /// > This feature requires CRC to be enabled. + /// > See {@link RF24.setCrcLength | `RF24.setCrcLength()`} for more detail. + /// + /// @group Configuration #[napi] pub fn set_auto_ack(&mut self, enable: bool) -> Result<()> { self.inner @@ -222,6 +365,9 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Enable or disable the auto-ack feature for a specified `pipe`. + /// + /// @group Configuration #[napi] pub fn set_auto_ack_pipe(&mut self, enable: bool, pipe: u8) -> Result<()> { self.inner @@ -229,6 +375,13 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Allow disabling the auto-ack feature for individual payloads. + /// + /// @param enable - Setting this to `true` will allow the `askNoAck` parameter to + /// take effect. See {@link RF24.send | `RF24.send()`} and + /// {@link WriteConfig.askNoAck | `WriteConfig.askNoAck`} for more detail. + /// + /// @group Configuration #[napi] pub fn allow_ask_no_ack(&mut self, enable: bool) -> Result<()> { self.inner @@ -236,6 +389,20 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Upload a given ACK packet's payload (`buf`) into the radio's TX FIFO. + /// + /// This feature requires {@link RF24.allowAckPayloads | `RF24.allowAckPayloads()`} + /// to be enabled. + /// + /// @param pipe - The pipe number that (when data is received) will be responded + /// with the given payload (`buf`). + /// @param buf - The payload to attach to the auto-ack packet when responding to + /// data received on specified `pipe`. + /// + /// @returns A boolean value that describes if the payload was successfully uploaded + /// to the TX FIFO. Remember, the TX FIFO only has 3 levels ("slots"). + /// + /// @group Advanced #[napi] pub fn write_ack_payload(&mut self, pipe: u8, buf: Buffer) -> Result { let buf = buf.to_vec(); @@ -244,6 +411,18 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Configure the automatic retry feature. + /// + /// This feature is part of the auto-ack feature, thus the auto-ack feature is + /// required for this function to have any effect. + /// + /// @param delay - This value is clamped to the range [0, 15]. This value is + /// translated to microseconds with the formula `250 + (delay * 250) = microseconds`. + /// Meaning, the effective range of `delay` is [250, 4000]. + /// @param count - The number of attempt to retransmit when no ACK packet was + /// received (after transmitting). This value is clamped to the range [0, 15]. + /// + /// @group Configuration #[napi] pub fn set_auto_retries(&mut self, delay: u8, count: u8) -> Result<()> { self.inner @@ -251,6 +430,13 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Set the channel (frequency) that the radio uses to transmit and receive. + /// + /// @param channel - The channel must be in range [0, 125], otherwise this + /// function does nothing. This value can be roughly translated into frequency + /// by adding its value to 2400 (`channel + 2400 = frequency in Hz`). + /// + /// @group Basic #[napi] pub fn set_channel(&mut self, channel: u8) -> Result<()> { self.inner @@ -258,6 +444,9 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the currently configured channel. + /// + /// @group Basic #[napi] pub fn get_channel(&mut self) -> Result { self.inner @@ -265,36 +454,64 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the {@link CrcLength | `CrcLength`} used for all outgoing and incoming + /// transmissions. + /// + /// > [!NOTE] + /// > If disabled (with {@link RF24.setCrcLength | `RF24.setCrcLength(CrcLength.Disabled)`}) + /// > while auto-ack feature is disabled, then this function's returned value does not reflect + /// > the fact that CRC is forcefully enabled by the radio's firmware (needed by the + /// > auto-ack feature). + /// + /// @group Configuration #[napi] - pub fn get_crc_length(&mut self) -> Result { + pub fn get_crc_length(&mut self) -> Result { self.inner .get_crc_length() .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) - .map(|e| NodeCrcLength::from_inner(e)) + .map(|e| CrcLength::from_inner(e)) } + /// Set the {@link CrcLength | `CrcLength`} used for all outgoing and incoming transmissions. + /// + /// > [!IMPORTANT] + /// > Because CRC is required for the auto-ack feature, the radio's firmware will forcefully + /// > enable CRC even if the user explicitly disables it (using this function). + /// + /// @group Configuration #[napi] - pub fn set_crc_length(&mut self, crc_length: NodeCrcLength) -> Result<()> { + pub fn set_crc_length(&mut self, crc_length: CrcLength) -> Result<()> { self.inner .set_crc_length(crc_length.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the {@link DataRate | `DataRate`} used for all incoming and outgoing transmissions. + /// + /// @group Configuration #[napi] - pub fn get_data_rate(&mut self) -> Result { + pub fn get_data_rate(&mut self) -> Result { self.inner .get_data_rate() .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) - .map(|e| NodeDataRate::from_inner(e)) + .map(|e| DataRate::from_inner(e)) } + /// Set the {@link DataRate | `DataRate`} used for all incoming and outgoing transmissions. + /// + /// @group Configuration #[napi] - pub fn set_data_rate(&mut self, data_rate: NodeDataRate) -> Result<()> { + pub fn set_data_rate(&mut self, data_rate: DataRate) -> Result<()> { self.inner .set_data_rate(data_rate.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Is there a payload available in the RX FIFO? + /// + /// Use {@link RF24.read | `RF24.read()`} to get the payload data. + /// + /// @group Basic #[napi] pub fn available(&mut self) -> Result { self.inner @@ -302,6 +519,10 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Similar to {@link RF24.available | `RF24.available()`} but also returns the + /// pipe that received the next available payload. + /// + /// @group Basic #[napi] pub fn available_pipe(&mut self) -> Result { let mut pipe = Some(0u8); @@ -315,7 +536,9 @@ impl NodeRF24 { }) } - /// Use this to discard all 3 layers in the radio's RX FIFO. + /// Discard all 3 levels of the radio's RX FIFO. + /// + /// @group Advanced #[napi] pub fn flush_rx(&mut self) -> Result<()> { self.inner @@ -323,7 +546,9 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } - /// Use this to discard all 3 layers in the radio's TX FIFO. + /// Discard all 3 levels of the radio's TX FIFO. + /// + /// @group Advanced #[napi] pub fn flush_tx(&mut self) -> Result<()> { self.inner @@ -331,29 +556,49 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the state of the specified FIFO. + /// + /// @param aboutTx - True returns data about the TX FIFO. + /// False returns data about the RX FIFO. + /// + /// @group Advanced #[napi] - pub fn get_fifo_state(&mut self, about_tx: bool) -> Result { + pub fn get_fifo_state(&mut self, about_tx: bool) -> Result { self.inner .get_fifo_state(about_tx) .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) - .map(|e| NodeFifoState::from_inner(e)) + .map(|e| FifoState::from_inner(e)) } + /// Get the currently configured Power Amplitude (PA) level. + /// + /// @group Configuration #[napi] - pub fn get_pa_level(&mut self) -> Result { + pub fn get_pa_level(&mut self) -> Result { self.inner .get_pa_level() .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) - .map(|e| NodePaLevel::from_inner(e)) + .map(|e| PaLevel::from_inner(e)) } + /// Set the Power Amplitude (PA) level used for all transmissions (including + /// auto ack packet). + /// + /// @param paLevel - The {@link PaLevel | `PaLevel`} to use. + /// + /// @group Configuration #[napi] - pub fn set_pa_level(&mut self, pa_level: NodePaLevel) -> Result<()> { + pub fn set_pa_level(&mut self, pa_level: PaLevel) -> Result<()> { self.inner .set_pa_level(pa_level.into_inner()) .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Set the statically sized payload length. + /// + /// This configuration is not used if dynamic payloads are enabled. + /// + /// @group Configuration #[napi] pub fn set_payload_length(&mut self, length: u8) -> Result<()> { self.inner @@ -361,6 +606,13 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the currently configured length of statically sized payloads. + /// + /// Use {@link RF24.getDynamicPayloadLength | `RF24.getDynamicPayloadLength()`} + /// instead if dynamically sized payloads are enabled (via + /// {@link RF24.setDynamicPayloads | `RF24.setDynamicPayloads()`}). + /// + /// @group Configuration #[napi] pub fn get_payload_length(&mut self) -> Result { self.inner @@ -368,6 +620,12 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Enable or disable the dynamically sized payloads feature. + /// + /// @param enable - If set to `true`, the statically sized payloads (set via + /// {@link RF24.setPayloadLength | `RF24.setPayloadLength()`}) are not used. + /// + /// @group Configuration #[napi] pub fn set_dynamic_payloads(&mut self, enable: bool) -> Result<()> { self.inner @@ -375,6 +633,13 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the length of the next available payload in the RX FIFO. + /// + /// If dynamically sized payloads are not enabled (via + /// {@link RF24.setDynamicPayloads | `RF24.setDynamicPayloads()`}), + /// then use {@link RF24.getPayloadLength | `RF24.getPayloadLength()`}. + /// + /// @group Advanced #[napi] pub fn get_dynamic_payload_length(&mut self) -> Result { self.inner @@ -382,6 +647,21 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Open a specific pipe for receiving from the given address. + /// + /// It is highly recommended to avoid using pip 0 to receive because it is also + /// used to transmit automatic acknowledgements. + /// + /// > [!NOTE] + /// > Only pipes 0 and 1 actually use up to 5 bytes of the given address. + /// > Pipes 2 - 5 only use the first byte of the given address and last 4 + /// > bytes of the address set to pipe 1. + /// + /// @param pipe - The pipe number to receive data. This must be in range [0, 5], + /// otherwise this function does nothing. + /// @param address - The address to receive data from. + /// + /// @group Basic #[napi] pub fn open_rx_pipe(&mut self, pipe: u8, address: Buffer) -> Result<()> { let address = address.to_vec(); @@ -390,6 +670,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Set the address used for transmitting on pipe 0. + /// + /// Only pipe 0 can be used for transmitting. It is highly recommended to + /// avoid using pipe 0 to receive because of this. + /// + /// @param address - The address to receive data from. + /// + /// @group Basic #[napi] pub fn open_tx_pipe(&mut self, address: Buffer) -> Result<()> { let address = address.to_vec(); @@ -398,7 +686,15 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } - /// If the given `pipe` number is not in range [0, 5], then this function does nothing. + /// Close the specified pipe from receiving transmissions. + /// + /// Use {@link RF24.openRxPipe | `RF24.openRxPipe()`} to set the address for a + /// specific pipe. + /// + /// @param pipe - The pipe to close. This must be in range [0, 5], otherwise this function + /// does nothing. + /// + /// @group Basic #[napi] pub fn close_rx_pipe(&mut self, pipe: u8) -> Result<()> { self.inner @@ -406,6 +702,11 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Set the address length (applied to all pipes). + /// + /// @param length - The address length is only allowed to be in range [2, 5]. + /// + /// @group Configuration #[napi] pub fn set_address_length(&mut self, length: u8) -> Result<()> { self.inner @@ -413,6 +714,9 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the current configured address length (applied to all pipes). + /// + /// @group Configuration #[napi] pub fn get_address_length(&mut self) -> Result { self.inner @@ -420,11 +724,22 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Is the radio powered up? + /// + /// Use {@link RF24.isListening | `RF24.isListening`} to determine if + /// the radio is in RX or TX mode. + /// + /// @group Configuration #[napi(getter)] pub fn is_powered(&self) -> bool { self.inner.is_powered() } + /// Power Down the radio. + /// + /// No transmissions can be received when the radio is powered down. + /// + /// @group Configuration #[napi] pub fn power_down(&mut self) -> Result<()> { self.inner @@ -432,6 +747,12 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Power up the radio. + /// + /// @param delay - The number of nanoseconds to wait for the radio to finish + /// powering up. If not specified, the default wait time defaults to 5 milliseconds. + /// + /// @group Configuration #[napi] pub fn power_up(&mut self, delay: Option) -> Result<()> { self.inner @@ -439,9 +760,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Configure the IRQ pin to reflect the specified {@link StatusFlags | `StatusFlags`}. + /// + /// If no parameter value is given, then all flags are are reflected by the IRQ pin. + /// + /// @group Configuration #[napi] - pub fn set_status_flags(&mut self, flags: Option) -> Result<()> { - let flags = flags.unwrap_or(NodeStatusFlags { + pub fn set_status_flags(&mut self, flags: Option) -> Result<()> { + let flags = flags.unwrap_or(StatusFlags { rx_dr: Some(true), tx_ds: Some(true), tx_df: Some(true), @@ -451,9 +777,14 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Reset the specified {@link StatusFlags | `StatusFlags`}. + /// + /// If no parameter value is given, then all flags are reset. + /// + /// @group Advanced #[napi] - pub fn clear_status_flags(&mut self, flags: Option) -> Result<()> { - let flags = flags.unwrap_or(NodeStatusFlags { + pub fn clear_status_flags(&mut self, flags: Option) -> Result<()> { + let flags = flags.unwrap_or(StatusFlags { rx_dr: Some(true), tx_ds: Some(true), tx_df: Some(true), @@ -463,6 +794,11 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Update the cached value of Status flags. + /// + /// Use {@link RF24.getStatusFlags | `RF24.getStatusFlags`} to get the updated values. + /// + /// @group Advanced #[napi] pub fn update(&mut self) -> Result<()> { self.inner @@ -470,13 +806,26 @@ impl NodeRF24 { .map_err(|e| Error::new(Status::GenericFailure, format!("{e:?}"))) } + /// Get the current state of the {@link StatusFlags | `StatusFlags`}. + /// + /// > [!NOTE] + /// > This function simply returns the value of the flags that was cached + /// > from the last SPI transaction. It does not actually update the values + /// > (from the radio) before returning them. + /// > + /// > Use {@link RF24.update | `RF24.update`} to update them first. + /// + /// @group Advanced #[napi] - pub fn get_status_flags(&mut self) -> NodeStatusFlags { - let mut flags = StatusFlags::default(); + pub fn get_status_flags(&mut self) -> StatusFlags { + let mut flags = rf24::StatusFlags::default(); self.inner.get_status_flags(&mut flags); - NodeStatusFlags::from_inner(flags) + StatusFlags::from_inner(flags) } + /// Print helpful debug information to stdout. + /// + /// @group Configuration #[napi] pub fn print_details(&mut self) -> Result<()> { self.inner diff --git a/bindings/node/src/types.rs b/bindings/node/src/types.rs index 6005ca4..222a0f9 100644 --- a/bindings/node/src/types.rs +++ b/bindings/node/src/types.rs @@ -1,26 +1,25 @@ -#[cfg(target_os = "linux")] -use rf24::{CrcLength, DataRate, FifoState, PaLevel, StatusFlags}; +//! This module defines thin wrappers around rust native types to be exposed in node.js -/// Optional configuration parameters to fine tune instantiating the RF24 object. -/// Pass this object as third parameter to RF24 constructor. +/// Optional configuration parameters to fine tune instantiating the {@link RF24} object. +/// Pass this object as third parameter to {@link RF24} constructor. #[napi(object)] pub struct HardwareConfig { /// The GPIO chip number: `/dev/gpiochipN` where `N` is this value. /// - /// Defaults to `0`, but needs to be `4` on RPi5 (or newer). + /// @defaultValue `0`, but needs to be `4` on RPi5 (or newer). /// This may also need to be specified for nVidia's hardware offerings. pub dev_gpio_chip: Option, /// The SPI bus number: `/dev/spidevX.Y` where `X` is this value - /// and `Y` is the `csPin` required parameter to RF24 constructor + /// and `Y` is the `csPin` required parameter to {@link RF24} constructor /// - /// Defaults to 0, but can be as high as 3 depending on the number of + /// @defaultValue `0`, but can be as high as `3` depending on the number of /// SPI buses available/exposed on the board. pub dev_spi_bus: Option, /// The SPI speed in Hz used to communicate with the nRF24L01 over SPI. /// - /// Defaults to 10 MHz (`10000000`) which is the radio's maximum + /// @defaultValue `10000000` (10 MHz) which is the radio's maximum /// supported speed. Lower this to 6 or 4 MHz when using long wires or /// if builtin pull-up resistors are weak. pub spi_speed: Option, @@ -36,14 +35,16 @@ impl Default for HardwareConfig { } } -/// The return type for `RF24.getStatusFlags()` and optional parameters for -/// `RF24.setStatusFlags()` and `RF24.clearStatusFlags()`. +/// The return type for {@link RF24.getStatusFlags | `RF24.getStatusFlags()`} +/// and optional parameters for {@link RF24.setStatusFlags | `RF24.setStatusFlags()`} +/// and {@link RF24.clearStatusFlags | `RF24.clearStatusFlags()`}. /// -/// These flags default to `true` if not specified for `RF24.setStatusFlags()` -/// or `RF24.clearStatusFlags()`. -#[napi(object, js_name = "StatusFlags")] +/// These flags default to `true` if not specified for +/// {@link RF24.setStatusFlags | `RF24.setStatusFlags()`} +/// or {@link RF24.clearStatusFlags | `RF24.clearStatusFlags()`}. +#[napi(object)] #[derive(Default)] -pub struct NodeStatusFlags { +pub struct StatusFlags { /// A flag to describe if RX Data Ready to read. pub rx_dr: Option, /// A flag to describe if TX Data Sent. @@ -53,16 +54,16 @@ pub struct NodeStatusFlags { } #[cfg(target_os = "linux")] -impl NodeStatusFlags { - pub fn into_inner(self) -> StatusFlags { - StatusFlags { +impl StatusFlags { + pub fn into_inner(self) -> rf24::StatusFlags { + rf24::StatusFlags { rx_dr: self.rx_dr.unwrap_or_default(), tx_ds: self.tx_ds.unwrap_or_default(), tx_df: self.tx_df.unwrap_or_default(), } } - pub fn from_inner(other: StatusFlags) -> Self { + pub fn from_inner(other: rf24::StatusFlags) -> Self { Self { rx_dr: Some(other.rx_dr), tx_ds: Some(other.tx_ds), @@ -71,21 +72,23 @@ impl NodeStatusFlags { } } -/// An optional configuration for `RF24.write()` +/// An optional configuration for {@link RF24.write | `RF24.write()`} #[napi(object)] pub struct WriteConfig { - /// Set to true if you want to disable auto-ACK feature for the individual - /// payload (required `buf` parameter to `RF24.write()`). + /// Set to `true` if you want to disable auto-ACK feature for the individual + /// payload (required `buf` parameter to {@link RF24.write | `RF24.write()`}). /// - /// Defaults to false. Be sure to invoke `RF24.allowAskNoAck(true)` at least once beforehand, - /// otherwise this option will have no affect at all. + /// @defaultValue `false`. Be sure to invoke {@link RF24.allowAskNoAck | `RF24.allowAskNoAck(true)`} + /// at least once beforehand, otherwise this option will have no affect at all. pub ask_no_ack: Option, - /// Set to true to assert the radio's CE pin (and begin active TX mode) after the payload is + /// Set to `true` to assert the radio's CE pin (and begin active TX mode) after the payload is /// uploaded to the TX FIFO. /// /// Only set this to false if filling the TX FIFO (maximum 3 level stack) before entering /// active TX mode. Setting this option to false does not deactivate the radio's CE pin. + /// + /// @defaultValue `true`. pub start_tx: Option, } @@ -98,7 +101,7 @@ impl Default for WriteConfig { } } -/// The return type for `RF24.availablePipe()` +/// The return type for {@link RF24.availablePipe | `RF24.availablePipe()`} #[napi(object)] pub struct AvailablePipe { /// Is RX data available in the RX FIFO? @@ -111,9 +114,9 @@ pub struct AvailablePipe { /// Power Amplifier level. The units dBm (decibel-milliwatts or dBmW) /// represents a logarithmic signal loss. -#[napi(js_name = "PaLevel")] +#[napi] #[derive(Debug, PartialEq)] -pub enum NodePaLevel { +pub enum PaLevel { /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | /// |:--------:|:--------------------------:|:---------------------------:| /// | -18 dBm | -6 dBm | -12 dBm | @@ -133,51 +136,51 @@ pub enum NodePaLevel { } #[cfg(target_os = "linux")] -impl NodePaLevel { - pub fn into_inner(self) -> PaLevel { +impl PaLevel { + pub fn into_inner(self) -> rf24::PaLevel { match self { - NodePaLevel::Min => PaLevel::Min, - NodePaLevel::Low => PaLevel::Low, - NodePaLevel::High => PaLevel::High, - NodePaLevel::Max => PaLevel::Max, + PaLevel::Min => rf24::PaLevel::Min, + PaLevel::Low => rf24::PaLevel::Low, + PaLevel::High => rf24::PaLevel::High, + PaLevel::Max => rf24::PaLevel::Max, } } - pub fn from_inner(other: PaLevel) -> NodePaLevel { + pub fn from_inner(other: rf24::PaLevel) -> PaLevel { match other { - PaLevel::Min => NodePaLevel::Min, - PaLevel::Low => NodePaLevel::Low, - PaLevel::High => NodePaLevel::High, - PaLevel::Max => NodePaLevel::Max, + rf24::PaLevel::Min => PaLevel::Min, + rf24::PaLevel::Low => PaLevel::Low, + rf24::PaLevel::High => PaLevel::High, + rf24::PaLevel::Max => PaLevel::Max, } } } /// How fast data moves through the air. Units are in bits per second (bps). -#[napi(js_name = "DataRate")] +#[napi] #[derive(Debug, PartialEq)] -pub enum NodeDataRate { - /// represents 1 Mbps +pub enum DataRate { + /// Represents 1 Mbps Mbps1, - /// represents 2 Mbps + /// Represents 2 Mbps Mbps2, - /// represents 250 Kbps + /// Represents 250 Kbps Kbps250, } #[cfg(target_os = "linux")] -impl NodeDataRate { - pub fn into_inner(self) -> DataRate { +impl DataRate { + pub fn into_inner(self) -> rf24::DataRate { match self { - NodeDataRate::Mbps1 => DataRate::Mbps1, - NodeDataRate::Mbps2 => DataRate::Mbps2, - NodeDataRate::Kbps250 => DataRate::Kbps250, + DataRate::Mbps1 => rf24::DataRate::Mbps1, + DataRate::Mbps2 => rf24::DataRate::Mbps2, + DataRate::Kbps250 => rf24::DataRate::Kbps250, } } - pub fn from_inner(other: DataRate) -> NodeDataRate { + pub fn from_inner(other: rf24::DataRate) -> DataRate { match other { - DataRate::Mbps1 => NodeDataRate::Mbps1, - DataRate::Mbps2 => NodeDataRate::Mbps2, - DataRate::Kbps250 => NodeDataRate::Kbps250, + rf24::DataRate::Mbps1 => DataRate::Mbps1, + rf24::DataRate::Mbps2 => DataRate::Mbps2, + rf24::DataRate::Kbps250 => DataRate::Kbps250, } } } @@ -185,39 +188,39 @@ impl NodeDataRate { /// The length of a CRC checksum that is used (if any). /// /// Cyclical Redundancy Checking (CRC) is commonly used to ensure data integrity. -#[napi(js_name = "CrcLength")] +#[napi] #[derive(Debug, PartialEq)] -pub enum NodeCrcLength { - /// represents no CRC checksum is used +pub enum CrcLength { + /// Represents no CRC checksum is used Disabled, - /// represents CRC 8 bit checksum is used + /// Represents CRC 8 bit checksum is used Bit8, - /// represents CRC 16 bit checksum is used + /// Represents CRC 16 bit checksum is used Bit16, } #[cfg(target_os = "linux")] -impl NodeCrcLength { - pub fn into_inner(self) -> CrcLength { +impl CrcLength { + pub fn into_inner(self) -> rf24::CrcLength { match self { - NodeCrcLength::Disabled => CrcLength::Disabled, - NodeCrcLength::Bit8 => CrcLength::Bit8, - NodeCrcLength::Bit16 => CrcLength::Bit16, + CrcLength::Disabled => rf24::CrcLength::Disabled, + CrcLength::Bit8 => rf24::CrcLength::Bit8, + CrcLength::Bit16 => rf24::CrcLength::Bit16, } } - pub fn from_inner(other: CrcLength) -> NodeCrcLength { + pub fn from_inner(other: rf24::CrcLength) -> CrcLength { match other { - CrcLength::Disabled => NodeCrcLength::Disabled, - CrcLength::Bit8 => NodeCrcLength::Bit8, - CrcLength::Bit16 => NodeCrcLength::Bit16, + rf24::CrcLength::Disabled => CrcLength::Disabled, + rf24::CrcLength::Bit8 => CrcLength::Bit8, + rf24::CrcLength::Bit16 => CrcLength::Bit16, } } } /// The possible states of a FIFO. -#[napi(js_name = "FifoState")] +#[napi] #[derive(Debug, PartialEq)] -pub enum NodeFifoState { +pub enum FifoState { /// Represent the state of a FIFO when it is full. Full, /// Represent the state of a FIFO when it is empty. @@ -227,19 +230,19 @@ pub enum NodeFifoState { } #[cfg(target_os = "linux")] -impl NodeFifoState { - pub fn into_inner(self) -> FifoState { +impl FifoState { + pub fn into_inner(self) -> rf24::FifoState { match self { - NodeFifoState::Full => FifoState::Full, - NodeFifoState::Empty => FifoState::Empty, - NodeFifoState::Occupied => FifoState::Occupied, + FifoState::Full => rf24::FifoState::Full, + FifoState::Empty => rf24::FifoState::Empty, + FifoState::Occupied => rf24::FifoState::Occupied, } } - pub fn from_inner(other: FifoState) -> NodeFifoState { + pub fn from_inner(other: rf24::FifoState) -> FifoState { match other { - FifoState::Full => NodeFifoState::Full, - FifoState::Empty => NodeFifoState::Empty, - FifoState::Occupied => NodeFifoState::Occupied, + rf24::FifoState::Full => FifoState::Full, + rf24::FifoState::Empty => FifoState::Empty, + rf24::FifoState::Occupied => FifoState::Occupied, } } } diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 059642f..7f10d90 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -13,7 +13,7 @@ name = "rf24_py" crate-type = ["cdylib"] [dependencies] -pyo3 = {version = "0.22.4", features = ["extension-module"]} +pyo3 = {version = "0.22.5", features = ["extension-module"]} [target.'cfg(target_os = "linux")'.dependencies] linux-embedded-hal = "0.4.0" diff --git a/bindings/python/README.md b/bindings/python/README.md index 5373561..b1aec6f 100644 --- a/bindings/python/README.md +++ b/bindings/python/README.md @@ -1,9 +1,33 @@ -# rf24-py +# `rf24-py` -A python binding to the rust library [rf24-rs]. +The python binding for the [rf24-rs] project (written in rust). [rf24-rs]: https://github.com/nRF24/rf24-rs This package is only functional on Linux machines. Although, installing this package in non-Linux environments will provide the typing information used on Linux. + +## Install + +To install from pypi.org: + +```text +pip install rf24-py +``` + +To build from source: + +```text +pip install maturin +maturin dev +``` + +## Examples + +The examples are located in the repository's root path "examples/python". +To run the examples, simply pass the example file's path to the python interpreter: + +```text +python examples/python/getting_started.py +``` diff --git a/bindings/python/src/lib.rs b/bindings/python/src/lib.rs index bcabc13..4c8e964 100644 --- a/bindings/python/src/lib.rs +++ b/bindings/python/src/lib.rs @@ -1,11 +1,11 @@ use pyo3::prelude::*; // #[cfg(target_os = "linux")] -mod types; mod radio; +mod types; #[cfg(target_os = "linux")] fn bind_radio_impl(m: &Bound<'_, PyModule>) -> PyResult<()> { - m.add_class::() + m.add_class::() } #[cfg(not(target_os = "linux"))] @@ -17,10 +17,10 @@ fn bind_radio_impl(_m: &Bound<'_, PyModule>) -> PyResult<()> { #[pymodule] fn rf24_py(m: &Bound<'_, PyModule>) -> PyResult<()> { bind_radio_impl(m)?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/bindings/python/src/radio.rs b/bindings/python/src/radio.rs index 6f1fda2..50b5352 100644 --- a/bindings/python/src/radio.rs +++ b/bindings/python/src/radio.rs @@ -1,7 +1,7 @@ #![cfg(target_os = "linux")] use std::borrow::Cow; -use crate::types::{PyCrcLength, PyDataRate, PyFifoState, PyPaLevel, PyStatusFlags}; +use crate::types::{CrcLength, DataRate, FifoState, PaLevel, StatusFlags}; use linux_embedded_hal::{ gpio_cdev::{chips, LineRequestFlags}, spidev::{SpiModeFlags, SpidevOptions}, @@ -11,17 +11,32 @@ use pyo3::{ exceptions::{PyOSError, PyRuntimeError, PyValueError}, prelude::*, }; -use rf24::radio::{prelude::*, RF24}; -use rf24::StatusFlags; - -#[pyclass(name = "RF24", module = "rf24_py")] -pub struct PyRF24 { - inner: RF24, +use rf24::radio::prelude::*; + +/// Construct an object to control the radio. +/// +/// Parameters: +/// ce_pin: The GPIO pin number connected to the radio's CE pin. +/// cs_pin: The identifying number for the SPI bus' CS pin; +/// also labeled as "CEx" (where "x" is this parameter's value) on many +/// Raspberry Pi pin diagrams. +/// +/// Other parameters: +/// dev_gpio_chip: The GPIO chip's identifying number. +/// Consider the path `/dev/gpiochipN` where `N` is this parameter's value. +/// dev_spi_bus: The SPI bus number. +/// Consider the path `/dev/spidevX.Y` where `X` is this parameter's value +/// and `Y` is the `cs_pin` parameter's value. +/// spi_speed: The SPI bus speed in Hz. Defaults to the radio's maximum supported +/// speed (10 MHz). +#[pyclass(module = "rf24_py")] +pub struct RF24 { + inner: rf24::radio::RF24, read_buf: [u8; 32], } #[pymethods] -impl PyRF24 { +impl RF24 { #[new] #[pyo3( text_signature = "(ce_pin: int, cs_pin: int, dev_gpio_chip: int = 0, dev_spi_bus: int = 0, spi_speed: int = 10000000) -> RF24", @@ -82,17 +97,28 @@ impl PyRF24 { .map_err(|e| PyOSError::new_err(format!("{e:?}")))?; Ok(Self { - inner: RF24::new(ce_pin, spi, Delay), + inner: rf24::radio::RF24::new(ce_pin, spi, Delay), read_buf: [0u8; 32], }) } + /// Initialize the radio on the configured hardware (as specified to + /// [`RF24`][rf24_py.RF24] constructor). + /// + /// Raises: + /// RuntimeError: If a hardware failure caused problems (includes a + /// message to describe what problem was detected). pub fn begin(&mut self) -> PyResult<()> { self.inner .init() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Controls the radio's primary role (RX or TX). + /// + /// See also: + /// - [`RF24.start_listening()`][rf24_py.RF24.start_listening] + /// - [`RF24.stop_listening()`][rf24_py.RF24.stop_listening] #[setter] pub fn set_listen(&mut self, enable: bool) -> PyResult<()> { if enable { @@ -107,18 +133,36 @@ impl PyRF24 { self.inner.is_listening() } + /// Put the radio into active RX mode. + /// + /// Warning: + /// Do not call [`RF24.send()`][rf24_py.RF24.send] while in active RX mode + /// because (internally in rust) that _will_ cause an infinite loop. pub fn start_listening(&mut self) -> PyResult<()> { self.inner .start_listening() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Deactivates active RX mode and puts the radio into an inactive TX mode. + /// + /// The datasheet recommends idling the radio in an inactive TX mode. pub fn stop_listening(&mut self) -> PyResult<()> { self.inner .stop_listening() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Blocking function that loads a given `buf` into the TX FIFO, waits for a response + /// (if auto-ack is enabled), then returns a Boolean describing success. + /// + /// Parameters: + /// buf: The buffer of bytes to transmit. + /// + /// Other parameters: + /// ask_no_ack: A flag to disable the auto-ack feature for the given payload in `buf`. + /// This has no effect if auto-ack is disabled or + /// [RF24.allow_ask_no_ack] is not enabled. #[pyo3( signature = (buf, ask_no_ack = false), text_signature = "(buf: bytes | bytearray, ask_no_ack = False) -> bool", @@ -129,6 +173,26 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// A non-blocking function that uploads a given `buf` to the radio's TX FIFO. + /// + /// This is a helper function to [`RF24.send()`][rf24_py.RF24.send]. + /// Use this in combination with [`RF24.update()`][rf24_py.RF24.update] and + /// [`RF24.get_status_flags()`][rf24_py.RF24.get_status_flags] + /// to determine if transmission was successful. + /// + /// Parameters: + /// buf: The buffer of bytes to load into the TX FIFO. + /// + /// Other parameters: + /// ask_no_ack: A flag to disable the auto-ack feature for the given payload in `buf`. + /// + /// This has no effect if auto-ack is disabled or [RF24.allow_ask_no_ack] is not + /// enabled. + /// start_tx: A flag to assert the radio's CE pin after the given `buf` is uploaded to + /// the RX FIFO. Setting this to false does not un-assert the radio's CE pin to LOW. + /// + /// Returns: + /// A Boolean that describes if the given `buf` was successfully loaded into the TX FIFO. #[pyo3( signature = (buf, ask_no_ack = false, start_tx = true), text_signature = "(buf: bytes | bytearray, ask_no_ack = False, start_tx = True) -> bool", @@ -139,6 +203,20 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Read data from the radio's RX FIFO. + /// + /// Use [`RF24.available()`][rf24_py.RF24.available] to determine if there is data ready + /// to read from the RX FIFO. + /// + /// Other parameters: + /// len: An optional number of bytes to read from the FIFO. This is capped at `32`. + /// If not specified, then the length of the next available payload is used (which + /// automatically respects if dynamic payloads are enabled). + /// + /// See also: + /// [`RF24.set_dynamic_payloads()`][rf24_py.RF24.set_dynamic_payloads] for dynamically + /// sized payload or [`RF24.payload_length`][rf24_py.RF24.payload_length] for + /// statically sized payloads. #[pyo3(signature = (len = None))] pub fn read(&mut self, len: Option) -> PyResult> { let len = self @@ -148,29 +226,53 @@ impl PyRF24 { Ok(Cow::from(&self.read_buf[0..len as usize])) } + /// A blocking function to resend a failed payload in the TX FIFO. + /// + /// This is similar to [`RF24.send()`][rf24_py.RF24.send] but specifically for + /// failed transmissions. pub fn resend(&mut self) -> PyResult { self.inner .resend() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// A non-blocking function to restart a failed transmission. + /// + /// This is a helper function to [`RF24.resend()`][rf24_py.RF24.resend]. + /// Use [`RF24.update()`][rf24_py.RF24.update] and + /// [`RF24.get_status_flags()`][rf24_py.RF24.get_status_flags] to determine if + /// retransmission was successful. pub fn rewrite(&mut self) -> PyResult<()> { self.inner .rewrite() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Get the Automatic Retry Count (ARC) of attempts made during the last transmission. + /// + /// This resets with every new transmission. The returned value is meaningless if the + /// auto-ack feature is disabled. + /// + /// See also: + /// Use [`RF24.set_auto_retries`][rf24_py.RF24.set_auto_retries] to configure the + /// automatic retries feature. pub fn get_last_arc(&mut self) -> PyResult { self.inner .get_last_arc() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// A property that describes if the radio is a nRF24L01+ or not. #[getter] pub fn is_plus_variant(&self) -> bool { self.inner.is_plus_variant() } + /// A property that describes the radio's Received Power Detection (RPD). + /// + /// This is reset upon entering RX mode and is only set if the radio detects a + /// signal if strength -64 dBm or greater (actual threshold may vary depending + /// on radio model). #[getter] pub fn get_rpd(&mut self) -> PyResult { self.inner @@ -178,60 +280,139 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - pub fn start_carrier_wave(&mut self, level: PyPaLevel, channel: u8) -> PyResult<()> { + /// Start a constant carrier wave on the given `channel` using the specified + /// power amplitude `level`. + /// + /// This functionality is only useful for testing the radio hardware works as a + /// transmitter. + /// + /// Parameters: + /// level: The Power Amplitude level to use when transmitting. + /// channel: The channel (radio's frequency) used to transmit. + /// The channel should not be changed while transmitting because it can + /// cause undefined behavior. + pub fn start_carrier_wave(&mut self, level: PaLevel, channel: u8) -> PyResult<()> { self.inner .start_carrier_wave(level.into_inner(), channel) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Stop transmitting the constant carrier wave. + /// + /// [`RF24.start_carrier_wave()`][rf24_py.RF24.start_carrier_wave] should be called + /// before this function. pub fn stop_carrier_wave(&mut self) -> PyResult<()> { self.inner .stop_carrier_wave() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Enable or disable the LNA feature. + /// + /// On nRF24L01+ modules with a builtin antenna, this feature is always enabled. + /// For clone's and module's with a separate PA/LNA circuit (external antenna), + /// this function may not behave exactly as expected. Consult the radio module's + /// manufacturer. pub fn set_lna(&mut self, enable: bool) -> PyResult<()> { self.inner .set_lna(enable) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Enable or disable the custom ACK payloads attached to auto-ack packets. + /// + /// > [!IMPORTANT] + /// > This feature requires dynamically sized payloads. + /// > Use [`RF24.set_dynamic_payloads(True)`][rf24_py.RF24.set_dynamic_payloads] + /// > to enable dynamically sized payloads. pub fn allow_ack_payloads(&mut self, enable: bool) -> PyResult<()> { self.inner .allow_ack_payloads(enable) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Enable or disable the auto-ack feature for all pipes. + /// + /// > [!NOTE] + /// > This feature requires CRC to be enabled. + /// > See [`RF24.crc_length`][rf24_py.RF24.crc_length] for more detail. + /// + /// Parameters: + /// enable: Pass true to enable the auto-ack feature for all pipes. pub fn set_auto_ack(&mut self, enable: bool) -> PyResult<()> { self.inner .set_auto_ack(enable) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Enable or disable the auto-ack feature for a specified `pipe`. + /// + /// Parameters: + /// enable: Pass true to enable the auto-ack feature for the specified `pipe`. + /// pipe: The pipe about which to control the auto-ack feature. pub fn set_auto_ack_pipe(&mut self, enable: bool, pipe: u8) -> PyResult<()> { self.inner .set_auto_ack_pipe(enable, pipe) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Allow disabling the auto-ack feature for individual payloads. + /// + /// Parameters: + /// enable: Setting this to `true` will allow the `ask_no_ack` parameter to + /// take effect. See [`RF24.send()`][rf24_py.RF24.send] and + /// [`RF24.write()`][rf24_py.RF24.write] for more detail. pub fn allow_ask_no_ack(&mut self, enable: bool) -> PyResult<()> { self.inner .allow_ask_no_ack(enable) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Upload a given ACK packet's payload (`buf`) into the radio's TX FIFO. + /// + /// This feature requires + /// [`RF24.allow_ack_payloads()`][rf24_py.RF24.allow_ack_payloads] to be enabled. + /// + /// Parameters: + /// pipe: The pipe number that (when data is received) will be responded + /// with the given payload (`buf`). + /// buf: The payload to attach to the auto-ack packet when responding to + /// data received on specified `pipe`. + /// + /// Returns: + /// A boolean value that describes if the payload was successfully uploaded + /// to the TX FIFO. Remember, the TX FIFO only has 3 levels ("slots"). pub fn write_ack_payload(&mut self, pipe: u8, buf: &[u8]) -> PyResult { self.inner .write_ack_payload(pipe, buf) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Configure the automatic retry feature. + /// + /// This feature is part of the auto-ack feature, thus the auto-ack feature is + /// required for this function to have any effect. + /// + /// Parameters: + /// delay: This value is clamped to the range [0, 15]. This value is + /// translated to microseconds with the formula + /// + /// 250 + (delay * 250) = microseconds + /// + /// Meaning, the effective range of `delay` is [250, 4000]. + /// count: The number of attempt to retransmit when no ACK packet was + /// received (after transmitting). This value is clamped to the range [0, 15]. pub fn set_auto_retries(&mut self, delay: u8, count: u8) -> PyResult<()> { self.inner .set_auto_retries(delay, count) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Set the channel (frequency) that the radio uses to transmit and receive. + /// + /// The channel must be in range [0, 125], otherwise this + /// function does nothing. This value can be roughly translated into frequency + /// by adding its value to 2400 (`channel + 2400 = frequency in Hz`). #[setter] pub fn set_channel(&mut self, channel: u8) -> PyResult<()> { self.inner @@ -246,42 +427,55 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - #[getter] - pub fn get_crc_length(&mut self) -> PyResult { - self.inner - .get_crc_length() - .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) - .map(|e| PyCrcLength::from_inner(e)) - } - + /// Set/get the [`CrcLength`][rf24_py.CrcLength] used for all outgoing and incoming + /// transmissions. + /// + /// > [!IMPORTANT] + /// > Because CRC is required for the auto-ack feature, the radio's firmware will + /// > forcefully enable CRC even if the user explicitly disables it. #[setter] - pub fn set_crc_length(&mut self, crc_length: PyCrcLength) -> PyResult<()> { + pub fn set_crc_length(&mut self, crc_length: CrcLength) -> PyResult<()> { self.inner .set_crc_length(crc_length.into_inner()) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } #[getter] - pub fn get_data_rate(&mut self) -> PyResult { + pub fn get_crc_length(&mut self) -> PyResult { self.inner - .get_data_rate() + .get_crc_length() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) - .map(|e| PyDataRate::from_inner(e)) + .map(|e| CrcLength::from_inner(e)) } + /// Set the [`DataRate`][rf24_py.DataRate] used for all incoming and outgoing + /// transmissions. #[setter] - pub fn set_data_rate(&mut self, data_rate: PyDataRate) -> PyResult<()> { + pub fn set_data_rate(&mut self, data_rate: DataRate) -> PyResult<()> { self.inner .set_data_rate(data_rate.into_inner()) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + #[getter] + pub fn get_data_rate(&mut self) -> PyResult { + self.inner + .get_data_rate() + .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) + .map(|e| DataRate::from_inner(e)) + } + + /// Is there a payload available in the RX FIFO? + /// + /// Use [`RF24.read()`][rf24_py.RF24.read] to get the payload data. pub fn available(&mut self) -> PyResult { self.inner .available() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Similar to [`RF24.available()`][rf24_py.RF24.available] but also returns the + /// pipe that received the next available payload. pub fn available_pipe(&mut self) -> PyResult<(bool, u8)> { let mut pipe = Some(0u8); let result = self @@ -291,42 +485,55 @@ impl PyRF24 { Ok((result, pipe.expect("`pipe` should be a number"))) } - /// Use this to discard all 3 layers in the radio's RX FIFO. + /// Discard all 3 layers in the radio's RX FIFO. pub fn flush_rx(&mut self) -> PyResult<()> { self.inner .flush_rx() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - /// Use this to discard all 3 layers in the radio's TX FIFO. + /// Discard all 3 layers in the radio's TX FIFO. pub fn flush_tx(&mut self) -> PyResult<()> { self.inner .flush_tx() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - pub fn get_fifo_state(&mut self, about_tx: bool) -> PyResult { + /// Get the state of the specified FIFO. + /// + /// Parameters: + /// about_tx: True returns data about the TX FIFO. + /// False returns data about the RX FIFO. + pub fn get_fifo_state(&mut self, about_tx: bool) -> PyResult { self.inner .get_fifo_state(about_tx) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) - .map(|e| PyFifoState::from_inner(e)) + .map(|e| FifoState::from_inner(e)) } - #[getter] - pub fn get_pa_level(&mut self) -> PyResult { + /// Set/get the Power Amplitude (PA) level used for all transmissions (including + /// auto ack packet). + #[setter] + pub fn set_pa_level(&mut self, pa_level: PaLevel) -> PyResult<()> { self.inner - .get_pa_level() + .set_pa_level(pa_level.into_inner()) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) - .map(|e| PyPaLevel::from_inner(e)) } - #[setter] - pub fn set_pa_level(&mut self, pa_level: PyPaLevel) -> PyResult<()> { + #[getter] + pub fn get_pa_level(&mut self) -> PyResult { self.inner - .set_pa_level(pa_level.into_inner()) + .get_pa_level() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) + .map(|e| PaLevel::from_inner(e)) } + /// Set/get the statically sized payload length. + /// + /// This configuration is not used if dynamic payloads are enabled. + /// Use [`RF24.get_dynamic_payload_length()`][rf24_py.RF24.get_dynamic_payload_length] + /// instead if dynamically sized payloads are enabled (via + /// [`RF24.set_dynamic_payloads()`][rf24_py.RF24.set_dynamic_payloads]). #[setter] pub fn set_payload_length(&mut self, length: u8) -> PyResult<()> { self.inner @@ -341,37 +548,79 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Enable or disable the dynamically sized payloads feature. + /// + /// Parameters: + /// enable: If set to `true`, the statically sized payloads (set via + /// [`RF24.payload_length`][rf24_py.RF24.payload_length]) are not + /// used. pub fn set_dynamic_payloads(&mut self, enable: bool) -> PyResult<()> { self.inner .set_dynamic_payloads(enable) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Get the length of the next available payload in the RX FIFO. + /// + /// If dynamically sized payloads are not enabled (via + /// [`RF24.set_dynamic_payloads()`][rf24_py.RF24.set_dynamic_payloads]), + /// then use [`RF24.payload_length`][rf24_py.RF24.payload_length]. pub fn get_dynamic_payload_length(&mut self) -> PyResult { self.inner .get_dynamic_payload_length() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Open a specific pipe for receiving from the given address. + /// + /// It is highly recommended to avoid using pip 0 to receive because it is also + /// used to transmit automatic acknowledgements. + /// + /// > [!NOTE] + /// > Only pipes 0 and 1 actually use up to 5 bytes of the given address. + /// > Pipes 2 - 5 only use the first byte of the given address and last 4 + /// > bytes of the address set to pipe 1. + /// + /// Parameters: + /// pipe: The pipe number to receive data. This must be in range [0, 5], + /// otherwise this function does nothing. + /// address: The address to receive data from. pub fn open_rx_pipe(&mut self, pipe: u8, address: &[u8]) -> PyResult<()> { self.inner .open_rx_pipe(pipe, address) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Set the address used for transmitting on pipe 0. + /// + /// Only pipe 0 can be used for transmitting. It is highly recommended to + /// avoid using pipe 0 to receive because of this. + /// + /// Parameters: + /// address: The address to receive data from. pub fn open_tx_pipe(&mut self, address: &[u8]) -> PyResult<()> { self.inner .open_tx_pipe(address) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - /// If the given `pipe` number is not in range [0, 5], then this function does nothing. + /// Close the specified pipe from receiving transmissions. + /// + /// Use [`RF24.open_rx_pipe()`][rf24_py.RF24.open_rx_pipe] to set the address for a + /// specific pipe. + /// + /// Parameters: + /// pipe: The pipe to close. This must be in range [0, 5], otherwise this function + /// does nothing. pub fn close_rx_pipe(&mut self, pipe: u8) -> PyResult<()> { self.inner .close_rx_pipe(pipe) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Set/get the address length (applied to all pipes). + /// + /// The address length is only allowed to be in range [2, 5]. #[setter] pub fn set_address_length(&mut self, length: u8) -> PyResult<()> { self.inner @@ -386,6 +635,13 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Power Up/Down the radio. + /// + /// No transmissions can be received when the radio is powered down. + /// + /// See also: + /// Setting this attribute to `True` is equivalent to calling + /// [`power_up()`][rf24_py.RF24.power_up] (using default delay). #[setter] pub fn set_power(&mut self, enable: bool) -> PyResult<()> { if enable { @@ -400,12 +656,21 @@ impl PyRF24 { self.inner.is_powered() } + /// Power Down the radio. + /// + /// No transmissions can be received when the radio is powered down. pub fn power_down(&mut self) -> PyResult<()> { self.inner .power_down() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Power up the radio. + /// + /// Parameters: + /// delay: The number of nanoseconds to wait for the radio to finish + /// powering up. If not specified, the default wait time defaults + /// to 5 milliseconds. #[pyo3( text_signature = "(delay: int | None = None) -> None", signature = (delay = None), @@ -416,34 +681,52 @@ impl PyRF24 { .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Configure the IRQ pin to reflect the specified [`StatusFlags`][rf24_py.StatusFlags]. + /// + /// If no parameter value is given, then all flags are are reflected by the IRQ pin. #[pyo3(signature = (flags = None))] - pub fn set_status_flags(&mut self, flags: Option) -> PyResult<()> { + pub fn set_status_flags(&mut self, flags: Option) -> PyResult<()> { let flags = flags.map(|f| f.into_inner()); self.inner .set_status_flags(flags) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Reset the specified [`StatusFlags`][rf24_py.StatusFlags]. + /// + /// If no parameter value is given, then all flags are reset. #[pyo3(signature = (flags = None))] - pub fn clear_status_flags(&mut self, flags: Option) -> PyResult<()> { + pub fn clear_status_flags(&mut self, flags: Option) -> PyResult<()> { let flags = flags.map(|f| f.into_inner()); self.inner .clear_status_flags(flags) .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } + /// Update the cached value of Status flags. + /// + /// Use [`RF24.get_status_flags()`][rf24_py.RF24.get_status_flags] to get the updated values. pub fn update(&mut self) -> PyResult<()> { self.inner .update() .map_err(|e| PyRuntimeError::new_err(format!("{e:?}"))) } - pub fn get_status_flags(&mut self) -> PyStatusFlags { - let mut flags = StatusFlags::default(); + /// Get the current state of the [`StatusFlags`][rf24_py.StatusFlags]. + /// + /// > [!NOTE] + /// > This function simply returns the value of the flags that was cached + /// > from the last SPI transaction. It does not actually update the values + /// > (from the radio) before returning them. + /// > + /// > Use [`RF24.update`][rf24_py.RF24.update] to update them first. + pub fn get_status_flags(&mut self) -> StatusFlags { + let mut flags = rf24::StatusFlags::default(); self.inner.get_status_flags(&mut flags); - PyStatusFlags::from_inner(flags) + StatusFlags::from_inner(flags) } + /// Print helpful debug information to stdout. pub fn print_details(&mut self) -> PyResult<()> { self.inner .print_details() diff --git a/bindings/python/src/types.rs b/bindings/python/src/types.rs index 12442ae..ce037dd 100644 --- a/bindings/python/src/types.rs +++ b/bindings/python/src/types.rs @@ -1,11 +1,15 @@ use pyo3::prelude::*; -#[cfg(target_os = "linux")] -use rf24::{CrcLength, DataRate, FifoState, PaLevel, StatusFlags}; - -#[pyclass(name = "StatusFlags", frozen, get_all, module = "rf24_py")] +/// The radio's status flags that correspond to interrupt events. +/// +/// See: +/// - [`RF24.get_status_flags()`][rf24_py.RF24.get_status_flags] +/// - [`RF24.set_status_flags()`][rf24_py.RF24.set_status_flags] +/// - [`RF24.clear_status_flags()`][rf24_py.RF24.clear_status_flags] +/// - [`RF24.update()`][rf24_py.RF24.update] +#[pyclass(frozen, get_all, module = "rf24_py")] #[derive(Default, Clone)] -pub struct PyStatusFlags { +pub struct StatusFlags { /// A flag to describe if RX Data Ready to read. pub rx_dr: bool, /// A flag to describe if TX Data Sent. @@ -15,7 +19,7 @@ pub struct PyStatusFlags { } #[pymethods] -impl PyStatusFlags { +impl StatusFlags { #[new] #[pyo3(signature = (rx_dr = false, tx_ds = false, tx_df = false))] fn new(rx_dr: bool, tx_ds: bool, tx_df: bool) -> Self { @@ -35,16 +39,16 @@ impl PyStatusFlags { } #[cfg(target_os = "linux")] -impl PyStatusFlags { - pub fn into_inner(self) -> StatusFlags { - StatusFlags { +impl StatusFlags { + pub fn into_inner(self) -> rf24::StatusFlags { + rf24::StatusFlags { rx_dr: self.rx_dr, tx_ds: self.tx_ds, tx_df: self.tx_df, } } - pub fn from_inner(other: StatusFlags) -> Self { + pub fn from_inner(other: rf24::StatusFlags) -> Self { Self { rx_dr: other.rx_dr, tx_ds: other.tx_ds, @@ -55,73 +59,81 @@ impl PyStatusFlags { /// Power Amplifier level. The units dBm (decibel-milliwatts or dBmW) /// represents a logarithmic signal loss. -#[pyclass(name = "PaLevel", eq, eq_int, module = "rf24_py")] +/// +/// Attributes: +/// Min: +/// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | +/// | :-------:|:--------------------------:|:---------------------------:| +/// | -18 dBm | -6 dBm | -12 dBm | +/// Low: +/// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | +/// | :-------:|:--------------------------:|:---------------------------:| +/// | -12 dBm | 0 dBm | -4 dBm | +/// High: +/// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | +/// | :-------:|:--------------------------:|:---------------------------:| +/// | -6 dBm | 3 dBm | 1 dBm | +/// Max: +/// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | +/// | :-------:|:--------------------------:|:---------------------------:| +/// | 0 dBm | 7 dBm | 4 dBm | +#[pyclass(eq, eq_int, module = "rf24_py")] #[derive(Clone, Copy, Debug, PartialEq)] -pub enum PyPaLevel { - /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | - /// | :-------:|:--------------------------:|:---------------------------:| - /// | -18 dBm | -6 dBm | -12 dBm | +pub enum PaLevel { Min, - /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | - /// | :-------:|:--------------------------:|:---------------------------:| - /// | -12 dBm | 0 dBm | -4 dBm | Low, - /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | - /// | :-------:|:--------------------------:|:---------------------------:| - /// | -6 dBm | 3 dBm | 1 dBm | High, - /// | nRF24L01 | Si24R1 with
LNA Enabled | Si24R1 with
LNA Disabled | - /// | :-------:|:--------------------------:|:---------------------------:| - /// | 0 dBm | 7 dBm | 4 dBm | Max, } #[cfg(target_os = "linux")] -impl PyPaLevel { - pub fn into_inner(self) -> PaLevel { +impl PaLevel { + pub fn into_inner(self) -> rf24::PaLevel { match self { - PyPaLevel::Min => PaLevel::Min, - PyPaLevel::Low => PaLevel::Low, - PyPaLevel::High => PaLevel::High, - PyPaLevel::Max => PaLevel::Max, + PaLevel::Min => rf24::PaLevel::Min, + PaLevel::Low => rf24::PaLevel::Low, + PaLevel::High => rf24::PaLevel::High, + PaLevel::Max => rf24::PaLevel::Max, } } - pub fn from_inner(other: PaLevel) -> PyPaLevel { + pub fn from_inner(other: rf24::PaLevel) -> PaLevel { match other { - PaLevel::Min => PyPaLevel::Min, - PaLevel::Low => PyPaLevel::Low, - PaLevel::High => PyPaLevel::High, - PaLevel::Max => PyPaLevel::Max, + rf24::PaLevel::Min => PaLevel::Min, + rf24::PaLevel::Low => PaLevel::Low, + rf24::PaLevel::High => PaLevel::High, + rf24::PaLevel::Max => PaLevel::Max, } } } -/// How fast data moves through the air. Units are in bits per second (bps). -#[pyclass(name = "DataRate", eq, eq_int, module = "rf24_py")] +#[pyclass(eq, eq_int, module = "rf24_py")] #[derive(Clone, Copy, Debug, PartialEq)] -pub enum PyDataRate { - /// represents 1 Mbps +pub enum DataRate { Mbps1, - /// represents 2 Mbps Mbps2, - /// represents 250 Kbps Kbps250, } +/// How fast data moves through the air. Units are in bits per second (bps). +/// +/// Attributes: +/// Mbps1: Represents 1 Mbps +/// Mbps2: Represents 2 Mbps +/// Kbps250: Represents 250 Kbps #[cfg(target_os = "linux")] -impl PyDataRate { - pub fn into_inner(self) -> DataRate { +impl DataRate { + pub fn into_inner(self) -> rf24::DataRate { match self { - PyDataRate::Mbps1 => DataRate::Mbps1, - PyDataRate::Mbps2 => DataRate::Mbps2, - PyDataRate::Kbps250 => DataRate::Kbps250, + DataRate::Mbps1 => rf24::DataRate::Mbps1, + DataRate::Mbps2 => rf24::DataRate::Mbps2, + DataRate::Kbps250 => rf24::DataRate::Kbps250, } } - pub fn from_inner(other: DataRate) -> PyDataRate { + pub fn from_inner(other: rf24::DataRate) -> DataRate { match other { - DataRate::Mbps1 => PyDataRate::Mbps1, - DataRate::Mbps2 => PyDataRate::Mbps2, - DataRate::Kbps250 => PyDataRate::Kbps250, + rf24::DataRate::Mbps1 => DataRate::Mbps1, + rf24::DataRate::Mbps2 => DataRate::Mbps2, + rf24::DataRate::Kbps250 => DataRate::Kbps250, } } } @@ -129,61 +141,68 @@ impl PyDataRate { /// The length of a CRC checksum that is used (if any). /// /// Cyclical Redundancy Checking (CRC) is commonly used to ensure data integrity. +/// +/// Attributes: +/// Disabled: Represents no CRC checksum is used. +/// Bit8: Represents CRC 8 bit checksum is used. +/// Bit16: Represents CRC 16 bit checksum is used. #[pyclass(name = "CrcLength", eq, eq_int, module = "rf24_py")] #[derive(Clone, Copy, Debug, PartialEq)] -pub enum PyCrcLength { - /// represents no CRC checksum is used +pub enum CrcLength { Disabled, - /// represents CRC 8 bit checksum is used Bit8, - /// represents CRC 16 bit checksum is used Bit16, } #[cfg(target_os = "linux")] -impl PyCrcLength { - pub fn into_inner(self) -> CrcLength { +impl CrcLength { + pub fn into_inner(self) -> rf24::CrcLength { match self { - PyCrcLength::Disabled => CrcLength::Disabled, - PyCrcLength::Bit8 => CrcLength::Bit8, - PyCrcLength::Bit16 => CrcLength::Bit16, + CrcLength::Disabled => rf24::CrcLength::Disabled, + CrcLength::Bit8 => rf24::CrcLength::Bit8, + CrcLength::Bit16 => rf24::CrcLength::Bit16, } } - pub fn from_inner(other: CrcLength) -> PyCrcLength { + pub fn from_inner(other: rf24::CrcLength) -> CrcLength { match other { - CrcLength::Disabled => PyCrcLength::Disabled, - CrcLength::Bit8 => PyCrcLength::Bit8, - CrcLength::Bit16 => PyCrcLength::Bit16, + rf24::CrcLength::Disabled => CrcLength::Disabled, + rf24::CrcLength::Bit8 => CrcLength::Bit8, + rf24::CrcLength::Bit16 => CrcLength::Bit16, } } } -/// The possible states of a FIFO. -#[pyclass(name = "FifoState", eq, eq_int, module = "rf24_py")] +/// Enumerations to describe the possible states of a FIFO. +/// +/// See also: +/// - [`RF24.get_fifo_state()`][rf24_py.RF24.get_fifo_state] +/// +/// Attributes: +/// Full: Represent the state of a FIFO when it is full. +/// Empty: Represent the state of a FIFO when it is empty. +/// Occupied: Represent the state of a FIFO when it is not full but not empty either. +#[pyclass(eq, eq_int, module = "rf24_py")] #[derive(Clone, Copy, Debug, PartialEq)] -pub enum PyFifoState { - /// Represent the state of a FIFO when it is full. +pub enum FifoState { Full, - /// Represent the state of a FIFO when it is empty. Empty, - /// Represent the state of a FIFO when it is not full but not empty either. Occupied, } #[cfg(target_os = "linux")] -impl PyFifoState { - pub fn into_inner(self) -> FifoState { +impl FifoState { + pub fn into_inner(self) -> rf24::FifoState { match self { - PyFifoState::Full => FifoState::Full, - PyFifoState::Empty => FifoState::Empty, - PyFifoState::Occupied => FifoState::Occupied, + FifoState::Full => rf24::FifoState::Full, + FifoState::Empty => rf24::FifoState::Empty, + FifoState::Occupied => rf24::FifoState::Occupied, } } - pub fn from_inner(other: FifoState) -> PyFifoState { + pub fn from_inner(other: rf24::FifoState) -> FifoState { match other { - FifoState::Full => PyFifoState::Full, - FifoState::Empty => PyFifoState::Empty, - FifoState::Occupied => PyFifoState::Occupied, + rf24::FifoState::Full => FifoState::Full, + rf24::FifoState::Empty => FifoState::Empty, + rf24::FifoState::Occupied => FifoState::Occupied, } } } diff --git a/cspell.config.yml b/cspell.config.yml index e0c84b5..2fd211e 100644 --- a/cspell.config.yml +++ b/cspell.config.yml @@ -3,16 +3,19 @@ words: - aarch - androideabi - armv + - autorefs - bindgen - bytearray - calcsize - Cdev + - codecov - datasheet - defmt - Doherty - DYNPD - eabi - endl + - endlineno - fontawesome - gnueabihf - gpio @@ -21,9 +24,11 @@ words: - inlinehilite - Kbps - linenums + - maturin - Mbps - milliwatts - mkdocs + - mkdocstrings - mosi - msvc - musleabihf @@ -41,3 +46,4 @@ words: - struct - superfences - tasklist + - twemoji diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..88773a7 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +site/ +src/node-api/ +node-api.json diff --git a/docs/README.md b/docs/README.md index 1c97d2e..ae017de 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,13 @@ To build these docs install mkdocs and relevant plugins: ```shell pip install -r docs/requirements.txt +yarn install +``` + +Generate the Node.js binding's API docs: + +```shell +yarn docs ``` Then build and view the docs using: diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a035906..9aacc50 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -9,6 +9,32 @@ nav: - index.md - api-diff.md - changelog.md + - node.js binding: + - node-api/README.md + - Classes: + - node-api/classes/RF24.md + - Enumerations: + - node-api/enumerations/CrcLength.md + - node-api/enumerations/DataRate.md + - node-api/enumerations/FifoState.md + - node-api/enumerations/PaLevel.md + - Interfaces: + - node-api/interfaces/AvailablePipe.md + - node-api/interfaces/HardwareConfig.md + - node-api/interfaces/StatusFlags.md + - node-api/interfaces/WriteConfig.md + - Type Aliases: + - node-api/type-aliases/NodeRF24.md + - python binding: + - python-api/README.md + - Classes: + - python-api/classes/RF24.md + - python-api/classes/status-flags.md + - Enumerations: + - python-api/enumerations/crc-length.md + - python-api/enumerations/data-rate.md + - python-api/enumerations/pa-level.md + - python-api/enumerations/fifo-state.md theme: name: material @@ -63,9 +89,31 @@ extra: extra_css: - stylesheets/extra.css +hooks: + - scripts/html_sanitizer.py + plugins: - search - include-markdown + - mkdocstrings: + handlers: + python: + paths: ['../'] + import: [https://docs.python.org/3/objects.inv] + options: + extensions: + - scripts/py_native_docstring.py + allow_inspection: false + show_if_no_docstring: true + show_signature_annotations: true + separate_signature: true + signature_crossrefs: true + show_source: false + show_symbol_type_toc: true + docstring_section_style: list + show_root_heading: true + members_order: source + merge_init_into_class: true markdown_extensions: - pymdownx.superfences: diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..bdf7e03 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,13 @@ +{ + "name": "@rf24/docs", + "private": true, + "version": "0.1.0", + "devDependencies": { + "typedoc": "^0.26.10", + "typedoc-plugin-markdown": "^4.2.9" + }, + "license": "MIT", + "scripts": { + "build": "npx typedoc ../bindings/node/index.d.ts --out ./src/node-api --json node-api.json" + } +} diff --git a/docs/requirements.txt b/docs/requirements.txt index b76dad4..0c91148 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,6 @@ +black==24.10.0 markdown-gfm-admonition==0.1.1 mkdocs==1.6.1 mkdocs-include-markdown-plugin==6.2.2 mkdocs-material==9.5.39 +mkdocstrings-python==1.12.2 diff --git a/docs/scripts/html_sanitizer.py b/docs/scripts/html_sanitizer.py new file mode 100644 index 0000000..c11bb97 --- /dev/null +++ b/docs/scripts/html_sanitizer.py @@ -0,0 +1,40 @@ +""" +This script is a locally maintained MkDocs plugin that + +1. Transforms the MarkDown output from TypeDoc + because the options for customization are rather opinionated. +2. Removes the copy button from mkdocstrings HTML output's code + blocks (for signatures only). +""" + +import re +from mkdocs.structure.pages import Page +from mkdocs.structure.files import Files +from mkdocs.config.defaults import MkDocsConfig + +DEFINED_IN_PATTERN = re.compile(r"#### Defined in\n\nindex\.d\.ts\:\d+") +SECTIONS_PATTERN = re.compile(r"#### (Parameters|Returns|Throws)") +LIST_MARKER_PATTERN = re.compile("^• ", re.MULTILINE) + + +def on_page_markdown( + markdown: str, page: Page, config: MkDocsConfig, files: Files +) -> str: + if "node-api" not in page.file.src_path: + return markdown + # change edit_uri metadata since these files are generated. + page.edit_url = f"{config.repo_url}/{config.edit_uri}typedoc.json" + # remove all "Defined in" sections + markdown = DEFINED_IN_PATTERN.sub("", markdown) + # replace repeated section headers with elements + markdown = SECTIONS_PATTERN.sub("**\\1**", markdown) + # remove copy button from all signatures + markdown = markdown.replace("```ts", "``` { .ts .no-copy }") + markdown = LIST_MARKER_PATTERN.sub("- ", markdown) + return markdown + + +def on_page_content(html: str, page: Page, config: MkDocsConfig, files: Files) -> str: + if "python-api" not in page.file.src_path: + return html + return html.replace("doc-signature highlight", "doc-signature highlight no-copy") diff --git a/docs/scripts/py_native_docstring.py b/docs/scripts/py_native_docstring.py new file mode 100644 index 0000000..d950568 --- /dev/null +++ b/docs/scripts/py_native_docstring.py @@ -0,0 +1,108 @@ +""" +Merge docstring from native module (`rf24_py.rf24_py`) +into objects discovered in type stubs (`rf24_py.pyi`). + +Without this, mkdocstrings only uses the type stubs. +The type stubs don't include any doc strings because +they are embedded in the native binary for convenience +with Python REPL's `help()`. + +NOTE: This must be run from a linux env. +The native binary does not include the RF24 class implementation +which requires a Linux to compile. +""" + +import ast +import griffe +import importlib +import logging +from mkdocs.utils import log + +LOGGER = logging.getLogger("pyo3_merge_native_docs") +LOGGER.setLevel(log.getEffectiveLevel()) + + +def elide_signature_from_docstring(docstring: str) -> str: + lines = docstring.splitlines() + start = 0 + for index, line in enumerate(lines): + # pyo3 delimits the signature with a `\n--\n` + # pybind11 delimits the signature(s) with a blank line + if line.startswith("--"): + start = index + 1 + break + return "\n".join(lines[start:]) + + +def inject_docstring(node: ast.AST, native_doc: str | None): + """Inject a given `native_docstring` into the AST node's body. + + Tested only with ClassDef and FunctionDef AST nodes. + """ + if native_doc.startswith(f"{node.name}("): + native_doc = elide_signature_from_docstring(native_doc) + docstring = ast.get_docstring(node) + if docstring is None: + new_node = ast.Constant(native_doc) + ast.copy_location(new_node, node) + wrapper_node = ast.Expr(new_node) + ast.copy_location(wrapper_node, node) + node.body.insert(0, wrapper_node) + elif node.body[0].value.value != native_doc: + node.body[0].value.value = native_doc + docstring + + +class NativeDocstring(griffe.Extension): + def __init__(self): + self.native = importlib.import_module("rf24_py") + + def on_class_node( + self, + node: ast.ClassDef | griffe.ObjectNode, + agent: griffe.Visitor | griffe.Inspector, + ) -> None: + """Prepend a docstring from the native module""" + if isinstance(node, griffe.ObjectNode): + return # any docstring fetched from pure python should be adequate + try: + native_doc: str | None = getattr(self.native, node.name).__doc__ + except AttributeError: + print( + "The", node.name, "class was not found! Are you running this in Linux?" + ) + return + if not native_doc: + return + # print(f"Amending docstring for rf24_py.{node.name}") + inject_docstring(node, native_doc) + + def on_function_node( + self, + node: ast.FunctionDef | griffe.ObjectNode, + agent: griffe.Visitor | griffe.Inspector, + ) -> None: + """Prepend a docstring from the native module""" + if isinstance(node, griffe.ObjectNode): + return # any docstring fetched from pure python should be adequate + if not isinstance(node.parent, ast.ClassDef): + return # we're only concerned with class methods here + func_parent = node.parent + native_cls = getattr(self.native, func_parent.name) + native_obj = getattr(native_cls, node.name) + native_doc: str | None = native_obj.__doc__ + if node.decorator_list: + for dec in node.decorator_list: + if isinstance(dec, ast.Name) and dec.id == "property": + break + else: + return # class property setters are not used for the docstring + if node.name == "__init__": + # remove the default docstring from pyo3 (intended for `help()`) + native_doc = native_doc.replace( + "Initialize self. See help(type(self)) for accurate signature.", + "", + ) + if not native_doc: + return + # print(f"Amending docstring for rf24_py.{func_parent.name}.{node.name}") + inject_docstring(node, native_doc) diff --git a/docs/src/index.md b/docs/src/index.md index 2c52f77..0893a89 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -3,6 +3,10 @@ include-markdown "../../README.md" %} -## Docs.rs +## API Docs -The API documentation is hosted at [docs.rs](https://docs.rs/). +The Rust API documentation is hosted at [docs.rs](https://docs.rs/rf24). + +Here, you will find the API for FFI (Foreign Function Interface) bindings: + +- [Node.js bindings](node-api/README.md) diff --git a/docs/src/python-api/README.md b/docs/src/python-api/README.md new file mode 100644 index 0000000..b963b8d --- /dev/null +++ b/docs/src/python-api/README.md @@ -0,0 +1,8 @@ +--- +title: rf24-py +--- + + +{% + include-markdown "../../../bindings/python/README.md" +%} diff --git a/docs/src/python-api/classes/RF24.md b/docs/src/python-api/classes/RF24.md new file mode 100644 index 0000000..a68dfb0 --- /dev/null +++ b/docs/src/python-api/classes/RF24.md @@ -0,0 +1,149 @@ +# RF24 class + + + +::: rf24_py.RF24 + options: + members: + - __init__ + +## Basic API + +::: rf24_py.RF24.begin + options: + heading_level: 3 +::: rf24_py.RF24.listen + options: + heading_level: 3 +::: rf24_py.RF24.start_listening + options: + heading_level: 3 +::: rf24_py.RF24.stop_listening + options: + heading_level: 3 +::: rf24_py.RF24.open_tx_pipe + options: + heading_level: 3 +::: rf24_py.RF24.open_rx_pipe + options: + heading_level: 3 +::: rf24_py.RF24.close_rx_pipe + options: + heading_level: 3 +::: rf24_py.RF24.available + options: + heading_level: 3 +::: rf24_py.RF24.available_pipe + options: + heading_level: 3 +::: rf24_py.RF24.read + options: + heading_level: 3 +::: rf24_py.RF24.send + options: + heading_level: 3 +::: rf24_py.RF24.resend + options: + heading_level: 3 +::: rf24_py.RF24.channel + options: + heading_level: 3 + +## Advanced API + +::: rf24_py.RF24.write_ack_payload + options: + heading_level: 3 +::: rf24_py.RF24.write + options: + heading_level: 3 +::: rf24_py.RF24.rewrite + options: + heading_level: 3 +::: rf24_py.RF24.get_fifo_state + options: + heading_level: 3 +::: rf24_py.RF24.clear_status_flags + options: + heading_level: 3 +::: rf24_py.RF24.update + options: + heading_level: 3 +::: rf24_py.RF24.get_status_flags + options: + heading_level: 3 +::: rf24_py.RF24.flush_rx + options: + heading_level: 3 +::: rf24_py.RF24.flush_tx + options: + heading_level: 3 +::: rf24_py.RF24.start_carrier_wave + options: + heading_level: 3 +::: rf24_py.RF24.stop_carrier_wave + options: + heading_level: 3 +::: rf24_py.RF24.rpd + options: + heading_level: 3 +::: rf24_py.RF24.get_last_arc + options: + heading_level: 3 +::: rf24_py.RF24.get_dynamic_payload_length + options: + heading_level: 3 + +## Configuration API + +::: rf24_py.RF24.set_status_flags + options: + heading_level: 3 +::: rf24_py.RF24.set_auto_ack + options: + heading_level: 3 +::: rf24_py.RF24.set_auto_ack_pipe + options: + heading_level: 3 +::: rf24_py.RF24.set_auto_retries + options: + heading_level: 3 +::: rf24_py.RF24.set_dynamic_payloads + options: + heading_level: 3 +::: rf24_py.RF24.allow_ask_no_ack + options: + heading_level: 3 +::: rf24_py.RF24.allow_ack_payloads + options: + heading_level: 3 +::: rf24_py.RF24.address_length + options: + heading_level: 3 +::: rf24_py.RF24.payload_length + options: + heading_level: 3 +::: rf24_py.RF24.data_rate + options: + heading_level: 3 +::: rf24_py.RF24.pa_level + options: + heading_level: 3 +::: rf24_py.RF24.set_lna + options: + heading_level: 3 +::: rf24_py.RF24.crc_length + options: + heading_level: 3 +::: rf24_py.RF24.power + options: + heading_level: 3 +::: rf24_py.RF24.power_up + options: + heading_level: 3 +::: rf24_py.RF24.power_down + options: + heading_level: 3 +::: rf24_py.RF24.is_plus_variant + options: + heading_level: 3 diff --git a/docs/src/python-api/classes/status-flags.md b/docs/src/python-api/classes/status-flags.md new file mode 100644 index 0000000..9618c73 --- /dev/null +++ b/docs/src/python-api/classes/status-flags.md @@ -0,0 +1,3 @@ +# `StatusFlags` + +::: rf24_py.StatusFlags diff --git a/docs/src/python-api/enumerations/crc-length.md b/docs/src/python-api/enumerations/crc-length.md new file mode 100644 index 0000000..44dd273 --- /dev/null +++ b/docs/src/python-api/enumerations/crc-length.md @@ -0,0 +1,5 @@ +# `CrcLength` + +::: rf24_py.CrcLength + options: + separate_signature: false diff --git a/docs/src/python-api/enumerations/data-rate.md b/docs/src/python-api/enumerations/data-rate.md new file mode 100644 index 0000000..3145615 --- /dev/null +++ b/docs/src/python-api/enumerations/data-rate.md @@ -0,0 +1,5 @@ +# `DataRate` + +::: rf24_py.DataRate + options: + separate_signature: false diff --git a/docs/src/python-api/enumerations/fifo-state.md b/docs/src/python-api/enumerations/fifo-state.md new file mode 100644 index 0000000..0513ab1 --- /dev/null +++ b/docs/src/python-api/enumerations/fifo-state.md @@ -0,0 +1,5 @@ +# `FifoState` + +::: rf24_py.FifoState + options: + separate_signature: false diff --git a/docs/src/python-api/enumerations/pa-level.md b/docs/src/python-api/enumerations/pa-level.md new file mode 100644 index 0000000..91ac666 --- /dev/null +++ b/docs/src/python-api/enumerations/pa-level.md @@ -0,0 +1,5 @@ +# `PaLevel` + +::: rf24_py.PaLevel + options: + separate_signature: false diff --git a/docs/src/stylesheets/extra.css b/docs/src/stylesheets/extra.css index c1397bc..4d5cffe 100644 --- a/docs/src/stylesheets/extra.css +++ b/docs/src/stylesheets/extra.css @@ -1,3 +1,76 @@ th { background-color: var(--md-default-fg-color--lightest); } + +/* Fancier color for operators such as * and |. */ +.doc-signature .o { + color: var(--md-code-hl-special-color); +} + +/* Fancier color for constants such as None, True, and False. */ +.doc-signature .kc { + color: var(--md-code-hl-constant-color); +} + +/* Fancier color for built-in types (only useful when cross-references are used). */ +.doc-signature .n>a.autorefs { + color: var(--md-primary-fg-color); +} + +.doc-signature .n>a.autorefs:hover { + color: var(--md-accent-fg-color); +} + +.doc.doc-contents.first { + margin-left: 2em; +} + +.doc.doc-label>code { + background-color: var(--md-accent-fg-color--transparent); + color: var(--md-accent-fg-color); + outline: solid var(--md-accent-fg-color) 1px; + border-radius: 2em; + padding: 0.25em 0.5em; +} + +.doc.doc-label { + float: right; +} + +.doc-symbol-toc.doc-symbol-parameter::after { + content: "P"; +} + +.doc-symbol-toc.doc-symbol-attribute::after { + content: "A"; +} + +.doc-symbol-toc.doc-symbol-function::after { + content: "F"; +} + +.doc-symbol-toc.doc-symbol-method::after { + content: "M"; +} + +.doc-symbol-toc.doc-symbol-class::after { + content: "C"; +} + +.doc-symbol-toc.doc-symbol-module::after { + content: "M"; +} + +.admonition.important { + border-color: #00b8d4; +} + +.admonition.important>.admonition-title::before { + -webkit-mask-image: var(--md-admonition-icon--info); + mask-image: var(--md-admonition-icon--info); + background-color: #00b8d4; +} + +.admonition.important>.admonition-title { + background-color: #00b8d41a; +} \ No newline at end of file diff --git a/docs/typedoc.json b/docs/typedoc.json new file mode 100644 index 0000000..9a191ee --- /dev/null +++ b/docs/typedoc.json @@ -0,0 +1,10 @@ +{ + "plugin": ["typedoc-plugin-markdown"], + "mergeReadme": true, + "useCodeBlocks": true, + "hidePageHeader": true, + "hideBreadcrumbs": true, + "hidePageTitle": true, + "expandParameters": true, + "parametersFormat": "table", +} \ No newline at end of file diff --git a/examples/node/yarn.lock b/examples/node/yarn.lock deleted file mode 100644 index 9fcf879..0000000 --- a/examples/node/yarn.lock +++ /dev/null @@ -1,1004 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@mole-inc/bin-wrapper@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@mole-inc/bin-wrapper/-/bin-wrapper-8.0.1.tgz#d7fd0ceb1cfa8a855293a3ed9d7d135f4d442f0e" - integrity sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA== - dependencies: - bin-check "^4.1.0" - bin-version-check "^5.0.0" - content-disposition "^0.5.4" - ext-name "^5.0.0" - file-type "^17.1.6" - filenamify "^5.0.2" - got "^11.8.5" - os-filter-obj "^2.0.0" - -"@napi-rs/nice-android-arm-eabi@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.0.1.tgz#9a0cba12706ff56500df127d6f4caf28ddb94936" - integrity sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w== - -"@napi-rs/nice-android-arm64@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.0.1.tgz#32fc32e9649bd759d2a39ad745e95766f6759d2f" - integrity sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA== - -"@napi-rs/nice-darwin-arm64@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.1.tgz#d3c44c51b94b25a82d45803e2255891e833e787b" - integrity sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA== - -"@napi-rs/nice-darwin-x64@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.0.1.tgz#f1b1365a8370c6a6957e90085a9b4873d0e6a957" - integrity sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ== - -"@napi-rs/nice-freebsd-x64@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.0.1.tgz#4280f081efbe0b46c5165fdaea8b286e55a8f89e" - integrity sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw== - -"@napi-rs/nice-linux-arm-gnueabihf@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.0.1.tgz#07aec23a9467ed35eb7602af5e63d42c5d7bd473" - integrity sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q== - -"@napi-rs/nice-linux-arm64-gnu@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.0.1.tgz#038a77134cc6df3c48059d5a5e199d6f50fb9a90" - integrity sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA== - -"@napi-rs/nice-linux-arm64-musl@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.0.1.tgz#715d0906582ba0cff025109f42e5b84ea68c2bcc" - integrity sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw== - -"@napi-rs/nice-linux-ppc64-gnu@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.0.1.tgz#ac1c8f781c67b0559fa7a1cd4ae3ca2299dc3d06" - integrity sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q== - -"@napi-rs/nice-linux-riscv64-gnu@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.0.1.tgz#b0a430549acfd3920ffd28ce544e2fe17833d263" - integrity sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig== - -"@napi-rs/nice-linux-s390x-gnu@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.0.1.tgz#5b95caf411ad72a965885217db378c4d09733e97" - integrity sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg== - -"@napi-rs/nice-linux-x64-gnu@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.0.1.tgz#a98cdef517549f8c17a83f0236a69418a90e77b7" - integrity sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA== - -"@napi-rs/nice-linux-x64-musl@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.0.1.tgz#5e26843eafa940138aed437c870cca751c8a8957" - integrity sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ== - -"@napi-rs/nice-win32-arm64-msvc@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.0.1.tgz#bd62617d02f04aa30ab1e9081363856715f84cd8" - integrity sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg== - -"@napi-rs/nice-win32-ia32-msvc@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.0.1.tgz#b8b7aad552a24836027473d9b9f16edaeabecf18" - integrity sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw== - -"@napi-rs/nice-win32-x64-msvc@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.0.1.tgz#37d8718b8f722f49067713e9f1e85540c9a3dd09" - integrity sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg== - -"@napi-rs/nice@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@napi-rs/nice/-/nice-1.0.1.tgz#483d3ff31e5661829a1efb4825591a135c3bfa7d" - integrity sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ== - optionalDependencies: - "@napi-rs/nice-android-arm-eabi" "1.0.1" - "@napi-rs/nice-android-arm64" "1.0.1" - "@napi-rs/nice-darwin-arm64" "1.0.1" - "@napi-rs/nice-darwin-x64" "1.0.1" - "@napi-rs/nice-freebsd-x64" "1.0.1" - "@napi-rs/nice-linux-arm-gnueabihf" "1.0.1" - "@napi-rs/nice-linux-arm64-gnu" "1.0.1" - "@napi-rs/nice-linux-arm64-musl" "1.0.1" - "@napi-rs/nice-linux-ppc64-gnu" "1.0.1" - "@napi-rs/nice-linux-riscv64-gnu" "1.0.1" - "@napi-rs/nice-linux-s390x-gnu" "1.0.1" - "@napi-rs/nice-linux-x64-gnu" "1.0.1" - "@napi-rs/nice-linux-x64-musl" "1.0.1" - "@napi-rs/nice-win32-arm64-msvc" "1.0.1" - "@napi-rs/nice-win32-ia32-msvc" "1.0.1" - "@napi-rs/nice-win32-x64-msvc" "1.0.1" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@sindresorhus/is@^4.0.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - -"@swc/cli@^0.4.1-nightly.20240914": - version "0.4.1-nightly.20240914" - resolved "https://registry.yarnpkg.com/@swc/cli/-/cli-0.4.1-nightly.20240914.tgz#c20a5f60a5af26976683fc69997c42e2edad1b5f" - integrity sha512-mpsF0+pq40uu9nZnhkzaA0gdivORTZnJNUFfuUGEzC1DgEEgmKDgisRWpBgA3p7xQPCpYlhkH5cTbsOkqar2Mg== - dependencies: - "@mole-inc/bin-wrapper" "^8.0.1" - "@swc/counter" "^0.1.3" - commander "^8.3.0" - fast-glob "^3.2.5" - minimatch "^9.0.3" - piscina "^4.3.0" - semver "^7.3.8" - slash "3.0.0" - source-map "^0.7.3" - -"@swc/core-darwin-arm64@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.35.tgz#695fe6cff7b429513f0e942f242156ab1f69bc7b" - integrity sha512-BQSSozVxjxS+SVQz6e3GC/+OBWGIK3jfe52pWdANmycdjF3ch7lrCKTHTU7eHwyoJ96mofszPf5AsiVJF34Fwg== - -"@swc/core-darwin-x64@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.7.35.tgz#c15c0fb11fb44e748d86d949911a6e416c7d36c9" - integrity sha512-44TYdKN/EWtkU88foXR7IGki9JzhEJzaFOoPevfi9Xe7hjAD/x2+AJOWWqQNzDPMz9+QewLdUVLyR6s5okRgtg== - -"@swc/core-linux-arm-gnueabihf@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.35.tgz#e40a31cbbef31b4ec0fa294eae4c51bf28f1622b" - integrity sha512-ccfA5h3zxwioD+/z/AmYtkwtKz9m4rWTV7RoHq6Jfsb0cXHrd6tbcvgqRWXra1kASlE+cDWsMtEZygs9dJRtUQ== - -"@swc/core-linux-arm64-gnu@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.35.tgz#538d367d06d7f2cbee05b9e1357583574eb57601" - integrity sha512-hx65Qz+G4iG/IVtxJKewC5SJdki8PAPFGl6gC/57Jb0+jA4BIoGLD/J3Q3rCPeoHfdqpkCYpahtyUq8CKx41Jg== - -"@swc/core-linux-arm64-musl@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.35.tgz#752e6b74c10113e1759e418906f48138dfd01a9f" - integrity sha512-kL6tQL9No7UEoEvDRuPxzPTpxrvbwYteNRbdChSSP74j13/55G2/2hLmult5yFFaWuyoyU/2lvzjRL/i8OLZxg== - -"@swc/core-linux-x64-gnu@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.35.tgz#0cbade76e5abce7d13802d6c55dc0c21213f5d3d" - integrity sha512-Ke4rcLQSwCQ2LHdJX1FtnqmYNQ3IX6BddKlUtS7mcK13IHkQzZWp0Dcu6MgNA3twzb/dBpKX5GLy07XdGgfmyw== - -"@swc/core-linux-x64-musl@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.35.tgz#ac60b88972cdbd2856cbe7b5b5ef1a1f54d906f6" - integrity sha512-T30tlLnz0kYyDFyO5RQF5EQ4ENjW9+b56hEGgFUYmfhFhGA4E4V67iEx7KIG4u0whdPG7oy3qjyyIeTb7nElEw== - -"@swc/core-win32-arm64-msvc@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.35.tgz#366f3e8cc387c539579e91a4ccf8a2b9a0083889" - integrity sha512-CfM/k8mvtuMyX+okRhemfLt784PLS0KF7Q9djA8/Dtavk0L5Ghnq+XsGltO3d8B8+XZ7YOITsB14CrjehzeHsg== - -"@swc/core-win32-ia32-msvc@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.35.tgz#07fbda3ca8ac58f28cd441aa9ba082a3ea6d84fb" - integrity sha512-ATB3uuH8j/RmS64EXQZJSbo2WXfRNpTnQszHME/sGaexsuxeijrp3DTYSFAA3R2Bu6HbIIX6jempe1Au8I3j+A== - -"@swc/core-win32-x64-msvc@1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.35.tgz#043a54aaeb9b24f4f2405ac2cfa48891508ff1a6" - integrity sha512-iDGfQO1571NqWUXtLYDhwIELA/wadH42ioGn+J9R336nWx40YICzy9UQyslWRhqzhQ5kT+QXAW/MoCWc058N6Q== - -"@swc/core@^1.7.35": - version "1.7.35" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.7.35.tgz#8a24041c8ef96477dd91aef9287d5fff79276e79" - integrity sha512-3cUteCTbr2r5jqfgx0r091sfq5Mgh6F1SQh8XAOnSvtKzwv2bC31mvBHVAieD1uPa2kHJhLav20DQgXOhpEitw== - dependencies: - "@swc/counter" "^0.1.3" - "@swc/types" "^0.1.13" - optionalDependencies: - "@swc/core-darwin-arm64" "1.7.35" - "@swc/core-darwin-x64" "1.7.35" - "@swc/core-linux-arm-gnueabihf" "1.7.35" - "@swc/core-linux-arm64-gnu" "1.7.35" - "@swc/core-linux-arm64-musl" "1.7.35" - "@swc/core-linux-x64-gnu" "1.7.35" - "@swc/core-linux-x64-musl" "1.7.35" - "@swc/core-win32-arm64-msvc" "1.7.35" - "@swc/core-win32-ia32-msvc" "1.7.35" - "@swc/core-win32-x64-msvc" "1.7.35" - -"@swc/counter@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" - integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== - -"@swc/types@^0.1.13": - version "0.1.13" - resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.13.tgz#441734f8bfa6e9e738f1c68e98be6da282ecc7db" - integrity sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q== - dependencies: - "@swc/counter" "^0.1.3" - -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - -"@tokenizer/token@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" - integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== - -"@types/cacheable-request@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" - integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "^3.1.4" - "@types/node" "*" - "@types/responselike" "^1.0.0" - -"@types/http-cache-semantics@*": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" - integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== - -"@types/keyv@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" - integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== - dependencies: - "@types/node" "*" - -"@types/node@*": - version "22.7.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" - integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== - dependencies: - undici-types "~6.19.2" - -"@types/responselike@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50" - integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== - dependencies: - "@types/node" "*" - -arch@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -bin-check@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" - integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== - dependencies: - execa "^0.7.0" - executable "^4.1.0" - -bin-version-check@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-5.1.0.tgz#788e80e036a87313f8be7908bc20e5abe43f0837" - integrity sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g== - dependencies: - bin-version "^6.0.0" - semver "^7.5.3" - semver-truncate "^3.0.0" - -bin-version@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-6.0.0.tgz#08ecbe5fc87898b441425e145f9e105064d00315" - integrity sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw== - dependencies: - execa "^5.0.0" - find-versions "^5.0.0" - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -cacheable-lookup@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" - integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== - -cacheable-request@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" - integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^6.0.1" - responselike "^2.0.0" - -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -content-disposition@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - -defer-to-connect@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -escape-string-regexp@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw== - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -executable@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" - integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== - dependencies: - pify "^2.2.0" - -ext-list@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" - integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== - dependencies: - mime-db "^1.28.0" - -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - -fast-glob@^3.2.5: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -file-type@^17.1.6: - version "17.1.6" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-17.1.6.tgz#18669e0577a4849ef6e73a41f8bdf1ab5ae21023" - integrity sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw== - dependencies: - readable-web-to-node-stream "^3.0.2" - strtok3 "^7.0.0-alpha.9" - token-types "^5.0.0-alpha.2" - -filename-reserved-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz#3d5dd6d4e2d73a3fed2ebc4cd0b3448869a081f7" - integrity sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw== - -filenamify@^5.0.2: - version "5.1.1" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-5.1.1.tgz#a1ccc5ae678a5e34f578afcb9b72898264d166d2" - integrity sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA== - dependencies: - filename-reserved-regex "^3.0.0" - strip-outer "^2.0.0" - trim-repeated "^2.0.0" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-versions@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-5.1.0.tgz#973f6739ce20f5e439a27eba8542a4b236c8e685" - integrity sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg== - dependencies: - semver-regex "^4.0.5" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -got@^11.8.5: - version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" - integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== - dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.2" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - -http-cache-semantics@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" - integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== - -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" - integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - -keyv@^4.0.0: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mime-db@^1.28.0: - version "1.53.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" - integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -minimatch@^9.0.3: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== - dependencies: - path-key "^2.0.0" - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -os-filter-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" - integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== - dependencies: - arch "^2.1.0" - -p-cancelable@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" - integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== - -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -peek-readable@^5.1.3: - version "5.3.1" - resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.3.1.tgz#9cc2c275cceda9f3d07a988f4f664c2080387dff" - integrity sha512-GVlENSDW6KHaXcd9zkZltB7tCLosKB/4Hg0fqBJkAoBgYG2Tn1xtMgXtSUuMU9AK/gCm/tTdT8mgAeF4YNeeqw== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -piscina@^4.3.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/piscina/-/piscina-4.7.0.tgz#68936fc77128db00541366531330138e366dc851" - integrity sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw== - optionalDependencies: - "@napi-rs/nice" "^1.0.1" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - -pump@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" - integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -readable-stream@^3.6.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-web-to-node-stream@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" - integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== - dependencies: - readable-stream "^3.6.0" - -resolve-alpn@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - -responselike@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" - integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== - dependencies: - lowercase-keys "^2.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@5.2.1, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -semver-regex@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-4.0.5.tgz#fbfa36c7ba70461311f5debcb3928821eb4f9180" - integrity sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw== - -semver-truncate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-3.0.0.tgz#0e3b4825d4a4225d8ae6e7c72231182b42edba40" - integrity sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg== - dependencies: - semver "^7.3.5" - -semver@^7.3.5, semver@^7.3.8, semver@^7.5.3: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -signal-exit@^3.0.0, signal-exit@^3.0.3: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -slash@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -sort-keys-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" - integrity sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw== - dependencies: - sort-keys "^1.0.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg== - dependencies: - is-plain-obj "^1.0.0" - -source-map@^0.7.3: - version "0.7.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" - integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-outer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-2.0.0.tgz#c45c724ed9b1ff6be5f660503791404f4714084b" - integrity sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg== - -strtok3@^7.0.0-alpha.9: - version "7.1.1" - resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.1.1.tgz#f548fd9dc59d0a76d5567ff8c16be31221f29dfc" - integrity sha512-mKX8HA/cdBqMKUr0MMZAFssCkIGoZeSCMXgnt79yKxNFguMLVFgRe6wB+fsL0NmoHDbeyZXczy7vEPSoo3rkzg== - dependencies: - "@tokenizer/token" "^0.3.0" - peek-readable "^5.1.3" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -token-types@^5.0.0-alpha.2: - version "5.0.1" - resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.1.tgz#aa9d9e6b23c420a675e55413b180635b86a093b4" - integrity sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg== - dependencies: - "@tokenizer/token" "^0.3.0" - ieee754 "^1.2.1" - -trim-repeated@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-2.0.0.tgz#5d60556d6d40d9461b7c7e06c3ac20b6b1d50090" - integrity sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg== - dependencies: - escape-string-regexp "^5.0.0" - -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== - -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== diff --git a/examples/rust/src/rp2040.rs b/examples/rust/src/rp2040.rs index 03d91b6..336ce51 100644 --- a/examples/rust/src/rp2040.rs +++ b/examples/rust/src/rp2040.rs @@ -20,7 +20,7 @@ impl BoardHardware<'_> { let ce = peri.PIN_9; let ce_pin = Output::new(ce, Level::Low); - + let clk = peri.PIN_10; let mosi = peri.PIN_11; let miso = peri.PIN_12; diff --git a/library/src/radio/mod.rs b/library/src/radio/mod.rs index 9750740..e97bed0 100644 --- a/library/src/radio/mod.rs +++ b/library/src/radio/mod.rs @@ -4,10 +4,10 @@ pub use rf24::{Nrf24Error, RF24}; /// This module defines the generic traits that may /// need to imported to use radio implementations. -/// +/// /// Since rustc only compiles objects that are used, /// it is convenient to import these traits with the `*` syntax. -/// +/// /// ``` /// use rf24::radio::prelude::*; /// ``` @@ -446,11 +446,10 @@ pub mod prelude { } /// A trait to represent manipulation of an ESB capable transceiver. - /// + /// /// Although the name is rather generic, this trait describes the /// behavior of a radio's rudimentary roles (RX and TX). - pub trait EsbRadio - { + pub trait EsbRadio { type RadioErrorType; /// Initialize the radio's hardware diff --git a/library/src/radio/rf24/mod.rs b/library/src/radio/rf24/mod.rs index 1ac8c62..a85039e 100644 --- a/library/src/radio/rf24/mod.rs +++ b/library/src/radio/rf24/mod.rs @@ -31,7 +31,7 @@ pub enum Nrf24Error { /// This struct implements the [`Esb*` traits](mod@crate::radio::prelude) /// for the nRF24L01 transceiver. -/// +/// /// Additionally, there are some functions implemented that are specific to the nRF24L01. pub struct RF24 { // private attributes diff --git a/library/src/radio/rf24/radio.rs b/library/src/radio/rf24/radio.rs index 9398047..d15cfe3 100644 --- a/library/src/radio/rf24/radio.rs +++ b/library/src/radio/rf24/radio.rs @@ -136,6 +136,10 @@ where /// This function calls [`RF24::flush_tx()`] upon entry, but it does not /// deactivate the radio's CE pin upon exit. fn send(&mut self, buf: &[u8], ask_no_ack: bool) -> Result { + if self.is_listening() { + // check if in RX mode to prevent an infinite below + return Ok(false); + } self._ce_pin.set_low().map_err(Nrf24Error::Gpo)?; // this function only handles 1 payload at a time self.flush_tx()?; // flush the TX FIFO to ensure we are sending the given buf diff --git a/library/src/radio/rf24/status.rs b/library/src/radio/rf24/status.rs index 887fac7..9e1f206 100644 --- a/library/src/radio/rf24/status.rs +++ b/library/src/radio/rf24/status.rs @@ -1,8 +1,8 @@ use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiDevice}; use crate::{ - types::StatusFlags, radio::{prelude::EsbStatus, Nrf24Error, RF24}, + types::StatusFlags, }; use super::{commands, mnemonics, registers}; @@ -69,10 +69,10 @@ where #[cfg(test)] mod test { extern crate std; - use crate::types::StatusFlags; use crate::radio::prelude::EsbStatus; use crate::radio::rf24::commands; use crate::spi_test_expects; + use crate::types::StatusFlags; use super::{registers, RF24}; use embedded_hal_mock::eh1::delay::NoopDelay; diff --git a/package.json b/package.json index 7fddde0..c3cd2c8 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,11 @@ "private": true, "workspaces": [ "bindings/node", + "docs", "examples/node" ], "scripts": { + "docs": "cd docs && yarn build", "examples-build": "cd examples/node && yarn build", "examples-lint": "cd examples/node && yarn lint", "artifacts": "cd bindings/node && yarn artifacts", diff --git a/rf24_py.pyi b/rf24_py.pyi index e6908b7..21dab7d 100644 --- a/rf24_py.pyi +++ b/rf24_py.pyi @@ -1,40 +1,45 @@ -from dataclasses import dataclass -from enum import Enum, auto +from enum import Enum class PaLevel(Enum): - Min = auto() - Low = auto() - High = auto() - Max = auto() + Min: "PaLevel" = ... + Low: "PaLevel" = ... + High: "PaLevel" = ... + Max: "PaLevel" = ... class CrcLength(Enum): - Disabled = auto() - Bit8 = auto() - Bit16 = auto() + Disabled: "CrcLength" = ... + Bit8: "CrcLength" = ... + Bit16: "CrcLength" = ... class FifoState(Enum): - Full = auto() - Empty = auto() - Occupied = auto() + Full: "FifoState" = ... + Empty: "FifoState" = ... + Occupied: "FifoState" = ... class DataRate(Enum): - Mbps1 = auto() - Mbps2 = auto() - Kbps250 = auto() + Mbps1: "DataRate" = ... + Mbps2: "DataRate" = ... + Kbps250: "DataRate" = ... -@dataclass(frozen=True) class StatusFlags: - rx_dr: bool - tx_ds: bool - tx_df: bool - def __init__( self, rx_dr: bool = False, tx_ds: bool = False, tx_df: bool = False ): ... + @property + def rx_dr(self) -> bool: ... + @property + def tx_ds(self) -> bool: ... + @property + def tx_df(self) -> bool: ... class RF24: def __init__( - self, ce_pin: int, cs_pin: int, dev_gpio_chip: int = 0, dev_spi_bus: int = 0 + self, + ce_pin: int, + cs_pin: int, + dev_gpio_chip: int = 0, + dev_spi_bus: int = 0, + spi_speed: int = 10000000, ) -> None: ... def begin(self) -> None: ... @property diff --git a/yarn.lock b/yarn.lock index 53544da..6102eec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -109,16 +109,72 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@shikijs/core@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-1.22.0.tgz#74e5d4485e5f7afa85109e322b42e400686f92bb" + integrity sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q== + dependencies: + "@shikijs/engine-javascript" "1.22.0" + "@shikijs/engine-oniguruma" "1.22.0" + "@shikijs/types" "1.22.0" + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.3" + +"@shikijs/engine-javascript@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz#2e5db29f0421755492f5279f8224ef7a7f907a29" + integrity sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw== + dependencies: + "@shikijs/types" "1.22.0" + "@shikijs/vscode-textmate" "^9.3.0" + oniguruma-to-js "0.4.3" + +"@shikijs/engine-oniguruma@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz#74c661fac4cd1f08f2c09b5d6e2fd2a6720d0401" + integrity sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw== + dependencies: + "@shikijs/types" "1.22.0" + "@shikijs/vscode-textmate" "^9.3.0" + +"@shikijs/types@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.22.0.tgz#d2a572381395c9308b472c8199b8e0289753b9ad" + integrity sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww== + dependencies: + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + +"@shikijs/vscode-textmate@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-9.3.0.tgz#b2f1776e488c1d6c2b6cd129bab62f71bbc9c7ab" + integrity sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA== + "@types/estree@^1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== +"@types/hast@^3.0.0", "@types/hast@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" + integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== + dependencies: + "@types/unist" "*" + "@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/mdast@^4.0.0": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-4.0.4.tgz#7ccf72edd2f1aa7dd3437e180c64373585804dd6" + integrity sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA== + dependencies: + "@types/unist" "*" + "@types/node@^22.7.5": version "22.7.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" @@ -126,6 +182,11 @@ dependencies: undici-types "~6.19.2" +"@types/unist@*", "@types/unist@^3.0.0": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" + integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== + "@typescript-eslint/eslint-plugin@8.9.0": version "8.9.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.9.0.tgz#bf0b25305b0bf014b4b194a6919103d7ac2a7907" @@ -207,6 +268,11 @@ "@typescript-eslint/types" "8.9.0" eslint-visitor-keys "^3.4.3" +"@ungap/structured-clone@^1.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -271,6 +337,11 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +ccount@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" + integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== + chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -279,6 +350,16 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +character-entities-html4@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" + integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== + +character-entities-legacy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" + integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -291,6 +372,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +comma-separated-tokens@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -317,6 +403,23 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +devlop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/devlop/-/devlop-1.1.0.tgz#4db7c2ca4dc6e0e834c30be70c94bbc976dc7018" + integrity sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA== + dependencies: + dequal "^2.0.0" + +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -516,6 +619,35 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +hast-util-to-html@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz#a9999a0ba6b4919576a9105129fead85d37f302b" + integrity sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg== + dependencies: + "@types/hast" "^3.0.0" + "@types/unist" "^3.0.0" + ccount "^2.0.0" + comma-separated-tokens "^2.0.0" + hast-util-whitespace "^3.0.0" + html-void-elements "^3.0.0" + mdast-util-to-hast "^13.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + stringify-entities "^4.0.0" + zwitch "^2.0.4" + +hast-util-whitespace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz#7778ed9d3c92dd9e8c5c8f648a49c21fc51cb621" + integrity sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw== + dependencies: + "@types/hast" "^3.0.0" + +html-void-elements@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" + integrity sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg== + ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -593,6 +725,13 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +linkify-it@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== + dependencies: + uc.micro "^2.0.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -605,11 +744,80 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +markdown-it@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== + dependencies: + argparse "^2.0.1" + entities "^4.4.0" + linkify-it "^5.0.0" + mdurl "^2.0.0" + punycode.js "^2.3.1" + uc.micro "^2.1.0" + +mdast-util-to-hast@^13.0.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" + integrity sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA== + dependencies: + "@types/hast" "^3.0.0" + "@types/mdast" "^4.0.0" + "@ungap/structured-clone" "^1.0.0" + devlop "^1.0.0" + micromark-util-sanitize-uri "^2.0.0" + trim-lines "^3.0.0" + unist-util-position "^5.0.0" + unist-util-visit "^5.0.0" + vfile "^6.0.0" + +mdurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== + merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micromark-util-character@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz#31320ace16b4644316f6bf057531689c71e2aee1" + integrity sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ== + dependencies: + micromark-util-symbol "^2.0.0" + micromark-util-types "^2.0.0" + +micromark-util-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz#0921ac7953dc3f1fd281e3d1932decfdb9382ab1" + integrity sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA== + +micromark-util-sanitize-uri@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz#ec8fbf0258e9e6d8f13d9e4770f9be64342673de" + integrity sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw== + dependencies: + micromark-util-character "^2.0.0" + micromark-util-encode "^2.0.0" + micromark-util-symbol "^2.0.0" + +micromark-util-symbol@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz#12225c8f95edf8b17254e47080ce0862d5db8044" + integrity sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw== + +micromark-util-types@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz#63b4b7ffeb35d3ecf50d1ca20e68fc7caa36d95e" + integrity sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w== + micromatch@^4.0.4: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -625,7 +833,7 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.4: +minimatch@^9.0.4, minimatch@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== @@ -642,6 +850,13 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +oniguruma-to-js@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz#8d899714c21f5c7d59a3c0008ca50e848086d740" + integrity sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ== + dependencies: + regex "^4.3.2" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -700,6 +915,16 @@ prettier@3.3.3: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== +property-information@^6.0.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== + +punycode.js@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -710,6 +935,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +regex@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/regex/-/regex-4.3.3.tgz#8cda73ccbdfa7c5691881d02f9bb142dba9daa6a" + integrity sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -744,6 +974,31 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shiki@^1.16.2: + version "1.22.0" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-1.22.0.tgz#45d1dfff0e03a598af70e2ec8592f14ef07827b4" + integrity sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw== + dependencies: + "@shikijs/core" "1.22.0" + "@shikijs/engine-javascript" "1.22.0" + "@shikijs/engine-oniguruma" "1.22.0" + "@shikijs/types" "1.22.0" + "@shikijs/vscode-textmate" "^9.3.0" + "@types/hast" "^3.0.4" + +space-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== + +stringify-entities@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" + integrity sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg== + dependencies: + character-entities-html4 "^2.0.0" + character-entities-legacy "^3.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -768,6 +1023,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -780,6 +1040,22 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +typedoc-plugin-markdown@^4.2.9: + version "4.2.9" + resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.9.tgz#c94c227d2adefb9b2d3725b3e2df7bf8032a0ac2" + integrity sha512-Wqmx+7ezKFgtTklEq/iUhQ5uFeBDhAT6wiS2na9cFLidIpl9jpDHJy/COYh8jUZXgIRIZVQ/bPNjyrnPFoDwzg== + +typedoc@^0.26.10: + version "0.26.10" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.26.10.tgz#d372f171dc2c4458cbac6c473be9591042ab781d" + integrity sha512-xLmVKJ8S21t+JeuQLNueebEuTVphx6IrP06CdV7+0WVflUSW3SPmR+h1fnWVdAR/FQePEgsSWCUHXqKKjzuUAw== + dependencies: + lunr "^2.3.9" + markdown-it "^14.1.0" + minimatch "^9.0.5" + shiki "^1.16.2" + yaml "^2.5.1" + typescript-eslint@^8.9.0: version "8.9.0" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.9.0.tgz#20a9b8125c57f3de962080ebebf366697f75bf79" @@ -794,11 +1070,54 @@ typescript@^5.6.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== +uc.micro@^2.0.0, uc.micro@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== + undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +unist-util-is@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-6.0.0.tgz#b775956486aff107a9ded971d996c173374be424" + integrity sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-position@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-5.0.0.tgz#678f20ab5ca1207a97d7ea8a388373c9cf896be4" + integrity sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-stringify-position@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz#449c6e21a880e0855bf5aabadeb3a740314abac2" + integrity sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ== + dependencies: + "@types/unist" "^3.0.0" + +unist-util-visit-parents@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz#4d5f85755c3b8f0dc69e21eca5d6d82d22162815" + integrity sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + +unist-util-visit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz#a7de1f31f72ffd3519ea71814cccf5fd6a9217d6" + integrity sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg== + dependencies: + "@types/unist" "^3.0.0" + unist-util-is "^6.0.0" + unist-util-visit-parents "^6.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -806,6 +1125,22 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +vfile-message@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181" + integrity sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw== + dependencies: + "@types/unist" "^3.0.0" + unist-util-stringify-position "^4.0.0" + +vfile@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-6.0.3.tgz#3652ab1c496531852bf55a6bac57af981ebc38ab" + integrity sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q== + dependencies: + "@types/unist" "^3.0.0" + vfile-message "^4.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -818,7 +1153,17 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +yaml@^2.5.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.0.tgz#14059ad9d0b1680d0f04d3a60fe00f3a857303c3" + integrity sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zwitch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==