From e2233d2923c314073a6021a03fbd37c04fbaee14 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 12:23:32 -0700 Subject: [PATCH 01/22] refactor: replace dynamic xdr construction with static classes --- src/.eslintrc.js | 117 --------------- src/array.js | 63 -------- src/bigint-encoder.js | 171 --------------------- src/bool.js | 36 ----- src/browser.js | 4 - src/config.js | 239 ------------------------------ src/core/error.ts | 6 + src/core/helpers.ts | 75 ++++++++++ src/core/reader.ts | 102 +++++++++++++ src/core/writer.ts | 55 +++++++ src/core/xdr-type.ts | 55 +++++++ src/double.js | 27 ---- src/enum.js | 94 ------------ src/errors.js | 25 ---- src/float.js | 27 ---- src/hyper.js | 38 ----- src/index.js | 5 - src/index.ts | 27 ++++ src/int.js | 39 ----- src/large-int.js | 143 ------------------ src/opaque.js | 35 ----- src/option.js | 44 ------ src/quadruple.js | 16 -- src/reference.js | 11 -- src/serialization/xdr-reader.js | 168 --------------------- src/serialization/xdr-writer.js | 179 ---------------------- src/string.js | 58 -------- src/struct.js | 91 ------------ src/types.js | 26 ---- src/types/array.ts | 77 ++++++++++ src/types/bool.ts | 28 ++++ src/types/double.ts | 21 +++ src/types/enum.ts | 77 ++++++++++ src/types/fixed-array.ts | 45 ++++++ src/types/float.ts | 21 +++ src/types/int32.ts | 21 +++ src/types/int64.ts | 21 +++ src/types/lazy.ts | 32 ++++ src/types/opaque.ts | 35 +++++ src/types/option.ts | 37 +++++ src/types/string.ts | 56 +++++++ src/types/struct.ts | 70 +++++++++ src/types/uint32.ts | 21 +++ src/types/uint64.ts | 21 +++ src/types/union.ts | 246 +++++++++++++++++++++++++++++++ src/types/var-opaque.ts | 45 ++++++ src/types/void.ts | 23 +++ src/union.js | 179 ---------------------- src/unsigned-hyper.js | 38 ----- src/unsigned-int.js | 42 ------ src/var-array.js | 72 --------- src/var-opaque.js | 43 ------ src/void.js | 19 --- src/xdr-type.js | 253 -------------------------------- 54 files changed, 1217 insertions(+), 2302 deletions(-) delete mode 100644 src/.eslintrc.js delete mode 100644 src/array.js delete mode 100644 src/bigint-encoder.js delete mode 100644 src/bool.js delete mode 100644 src/browser.js delete mode 100644 src/config.js create mode 100644 src/core/error.ts create mode 100644 src/core/helpers.ts create mode 100644 src/core/reader.ts create mode 100644 src/core/writer.ts create mode 100644 src/core/xdr-type.ts delete mode 100644 src/double.js delete mode 100644 src/enum.js delete mode 100644 src/errors.js delete mode 100644 src/float.js delete mode 100644 src/hyper.js delete mode 100644 src/index.js create mode 100644 src/index.ts delete mode 100644 src/int.js delete mode 100644 src/large-int.js delete mode 100644 src/opaque.js delete mode 100644 src/option.js delete mode 100644 src/quadruple.js delete mode 100644 src/reference.js delete mode 100644 src/serialization/xdr-reader.js delete mode 100644 src/serialization/xdr-writer.js delete mode 100644 src/string.js delete mode 100644 src/struct.js delete mode 100644 src/types.js create mode 100644 src/types/array.ts create mode 100644 src/types/bool.ts create mode 100644 src/types/double.ts create mode 100644 src/types/enum.ts create mode 100644 src/types/fixed-array.ts create mode 100644 src/types/float.ts create mode 100644 src/types/int32.ts create mode 100644 src/types/int64.ts create mode 100644 src/types/lazy.ts create mode 100644 src/types/opaque.ts create mode 100644 src/types/option.ts create mode 100644 src/types/string.ts create mode 100644 src/types/struct.ts create mode 100644 src/types/uint32.ts create mode 100644 src/types/uint64.ts create mode 100644 src/types/union.ts create mode 100644 src/types/var-opaque.ts create mode 100644 src/types/void.ts delete mode 100644 src/union.js delete mode 100644 src/unsigned-hyper.js delete mode 100644 src/unsigned-int.js delete mode 100644 src/var-array.js delete mode 100644 src/var-opaque.js delete mode 100644 src/void.js delete mode 100644 src/xdr-type.js diff --git a/src/.eslintrc.js b/src/.eslintrc.js deleted file mode 100644 index 6a5046d..0000000 --- a/src/.eslintrc.js +++ /dev/null @@ -1,117 +0,0 @@ -module.exports = { - env: { - es6: true, - es2017: true, - es2020: true, - es2022: true - }, - parserOptions: { ecmaVersion: 13 }, - extends: ['airbnb-base', 'prettier'], - plugins: ['prettier', 'prefer-import'], - rules: { - // OFF - 'import/prefer-default-export': 0, - 'node/no-unsupported-features/es-syntax': 0, - 'node/no-unsupported-features/es-builtins': 0, - camelcase: 0, - 'class-methods-use-this': 0, - 'linebreak-style': 0, - 'new-cap': 0, - 'no-param-reassign': 0, - 'no-underscore-dangle': 0, - 'no-use-before-define': 0, - 'prefer-destructuring': 0, - 'lines-between-class-members': 0, - 'no-plusplus': 0, // allow ++ for iterators - 'no-bitwise': 0, // allow high-performant bitwise operations - - // WARN - 'prefer-import/prefer-import-over-require': [1], - 'no-console': ['warn', { allow: ['assert'] }], - 'no-debugger': 1, - 'no-unused-vars': 1, - 'arrow-body-style': 1, - 'valid-jsdoc': [ - 1, - { - requireReturnDescription: false - } - ], - 'prefer-const': 1, - 'object-shorthand': 1, - 'require-await': 1, - 'max-classes-per-file': ['warn', 3], // do not block imports from other classes - - // ERROR - 'no-unused-expressions': [2, { allowTaggedTemplates: true }], - - // we're redefining this without the Math.pow restriction - // (since we don't want to manually add support for it) - // copied from https://github.com/airbnb/javascript/blob/070e6200bb6c70fa31470ed7a6294f2497468b44/packages/eslint-config-airbnb-base/rules/best-practices.js#L200 - 'no-restricted-properties': [ - 'error', - { - object: 'arguments', - property: 'callee', - message: 'arguments.callee is deprecated' - }, - { - object: 'global', - property: 'isFinite', - message: 'Please use Number.isFinite instead' - }, - { - object: 'self', - property: 'isFinite', - message: 'Please use Number.isFinite instead' - }, - { - object: 'window', - property: 'isFinite', - message: 'Please use Number.isFinite instead' - }, - { - object: 'global', - property: 'isNaN', - message: 'Please use Number.isNaN instead' - }, - { - object: 'self', - property: 'isNaN', - message: 'Please use Number.isNaN instead' - }, - { - object: 'window', - property: 'isNaN', - message: 'Please use Number.isNaN instead' - }, - { - property: '__defineGetter__', - message: 'Please use Object.defineProperty instead.' - }, - { - property: '__defineSetter__', - message: 'Please use Object.defineProperty instead.' - } - ], - 'no-restricted-syntax': [ - // override basic rule to allow ForOfStatement - 'error', - { - selector: 'ForInStatement', - message: - 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.' - }, - { - selector: 'LabeledStatement', - message: - 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.' - }, - { - selector: 'WithStatement', - message: - '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.' - } - ] - } -}; diff --git a/src/array.js b/src/array.js deleted file mode 100644 index 55cf092..0000000 --- a/src/array.js +++ /dev/null @@ -1,63 +0,0 @@ -import { NestedXdrType } from './xdr-type'; -import { XdrWriterError, XdrReaderError } from './errors'; - -export class Array extends NestedXdrType { - constructor(childType, length, maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH) { - super(maxDepth); - this._childType = childType; - this._length = length; - } - - /** - * @inheritDoc - */ - read(reader, remainingDepth = this._maxDepth) { - // Upper-bound fast-fail: remaining bytes is a loose capacity check since - // each XDR element typically consumes more than 1 byte (e.g., 4+ bytes). - if (this._length > reader.remainingBytes()) { - throw new XdrReaderError( - `Array length ${ - this._length - } exceeds remaining ${reader.remainingBytes()} bytes` - ); - } - NestedXdrType.checkDepth(remainingDepth); - const result = []; - // read values - for (let i = 0; i < this._length; i++) { - result.push(this._childType.read(reader, remainingDepth - 1)); - } - return result; - } - - /** - * @inheritDoc - */ - write(value, writer) { - if (!global.Array.isArray(value)) - throw new XdrWriterError(`value is not array`); - - if (value.length !== this._length) - throw new XdrWriterError( - `got array of size ${value.length}, expected ${this._length}` - ); - - for (const child of value) { - this._childType.write(child, writer); - } - } - - /** - * @inheritDoc - */ - isValid(value) { - if (!(value instanceof global.Array) || value.length !== this._length) { - return false; - } - - for (const child of value) { - if (!this._childType.isValid(child)) return false; - } - return true; - } -} diff --git a/src/bigint-encoder.js b/src/bigint-encoder.js deleted file mode 100644 index 62053b4..0000000 --- a/src/bigint-encoder.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Encode a native `bigint` value from a list of arbitrary integer-like values. - * - * @param {Array} parts - Slices to encode in big-endian - * format (i.e. earlier elements are higher bits) - * @param {64|128|256} size - Number of bits in the target integer type - * @param {boolean} unsigned - Whether it's an unsigned integer - * - * @returns {bigint} - */ -export function encodeBigIntFromBits(parts, size, unsigned) { - if (!(parts instanceof Array)) { - // allow a single parameter instead of an array - parts = [parts]; - } else if (parts.length && parts[0] instanceof Array) { - // unpack nested array param - parts = parts[0]; - } - - const total = parts.length; - const sliceSize = size / total; - switch (sliceSize) { - case 32: - case 64: - case 128: - case 256: - break; - - default: - throw new RangeError( - `expected slices to fit in 32/64/128/256 bits, got ${parts}` - ); - } - - // normalize all inputs to bigint - try { - for (let i = 0; i < parts.length; i++) { - if (typeof parts[i] !== 'bigint') { - parts[i] = BigInt(parts[i].valueOf()); - } - } - } catch (e) { - throw new TypeError(`expected bigint-like values, got: ${parts} (${e})`); - } - - // fast path: single value — validate and return directly without assembly - if (parts.length === 1) { - const value = parts[0]; - if (unsigned && value < 0n) { - throw new RangeError(`expected a positive value, got: ${parts}`); - } - const [min, max] = calculateBigIntBoundaries(size, unsigned); - if (value < min || value > max) { - throw new RangeError( - `bigint value ${value} for ${formatIntName( - size, - unsigned - )} out of range [${min}, ${max}]` - ); - } - return value; - } - - // multi-part assembly: encode in big-endian fashion, shifting each slice - let result = 0n; - - for (let i = 0; i < parts.length; i++) { - assertSliceFits(parts[i], sliceSize); - result |= BigInt.asUintN(sliceSize, parts[i]) << BigInt(i * sliceSize); - } - - if (!unsigned) { - result = BigInt.asIntN(size, result); - } - - // check boundaries - const [min, max] = calculateBigIntBoundaries(size, unsigned); - if (result >= min && result <= max) { - return result; - } - - // failed to encode - throw new RangeError( - `bigint values [${parts}] for ${formatIntName( - size, - unsigned - )} out of range [${min}, ${max}]: ${result}` - ); -} - -/** - * Transforms a single bigint value that's supposed to represent a `size`-bit - * integer into a list of `sliceSize`d chunks. - * - * @param {bigint} value - Single bigint value to decompose - * @param {64|128|256} iSize - Number of bits represented by `value` - * @param {32|64|128} sliceSize - Number of chunks to decompose into - * @return {bigint[]} List of signed bigint chunks in big-endian order (i.e. earlier elements are higher bits) - */ -export function sliceBigInt(value, iSize, sliceSize) { - if (typeof value !== 'bigint') { - throw new TypeError(`Expected bigint 'value', got ${typeof value}`); - } - - const total = iSize / sliceSize; - if (total === 1) { - return [value]; - } - - if ( - sliceSize < 32 || - sliceSize > 128 || - (total !== 2 && total !== 4 && total !== 8) - ) { - throw new TypeError( - `invalid bigint (${value}) and slice size (${iSize} -> ${sliceSize}) combination` - ); - } - - const shift = BigInt(sliceSize); - - // iterate shift and mask application - const result = new Array(total); - for (let i = 0; i < total; i++) { - // we force a signed interpretation to preserve sign in each slice value, - // but downstream can convert to unsigned if it's appropriate - result[i] = BigInt.asIntN(sliceSize, value); // clamps to size - - // move on to the next chunk - value >>= shift; - } - - return result; -} - -export function formatIntName(precision, unsigned) { - return `${unsigned ? 'u' : 'i'}${precision}`; -} - -/** - * Get min|max boundaries for an integer with a specified bits size - * @param {64|128|256} size - Number of bits in the source integer type - * @param {Boolean} unsigned - Whether it's an unsigned integer - * @return {BigInt[]} - */ -export function calculateBigIntBoundaries(size, unsigned) { - if (unsigned) { - return [0n, (1n << BigInt(size)) - 1n]; - } - - const boundary = 1n << BigInt(size - 1); - return [0n - boundary, boundary - 1n]; -} - -/** - * Asserts that a given part fits within the specified slice size. - * @param {bigint | number | string} part - The part to check. - * @param {number} sliceSize - The size of the slice in bits (e.g., 32, 64, 128) - * @returns {void} - * @throws {RangeError} If the part does not fit within the slice size. - */ -function assertSliceFits(part, sliceSize) { - const fitsSigned = BigInt.asIntN(sliceSize, part) === part; - const fitsUnsigned = BigInt.asUintN(sliceSize, part) === part; - - if (!fitsSigned && !fitsUnsigned) { - throw new RangeError( - `slice value ${part} does not fit in ${sliceSize} bits` - ); - } -} diff --git a/src/bool.js b/src/bool.js deleted file mode 100644 index 7909cb9..0000000 --- a/src/bool.js +++ /dev/null @@ -1,36 +0,0 @@ -import { Int } from './int'; -import { XdrPrimitiveType } from './xdr-type'; -import { XdrReaderError } from './errors'; - -export class Bool extends XdrPrimitiveType { - /** - * @inheritDoc - */ - static read(reader) { - const value = Int.read(reader); - - switch (value) { - case 0: - return false; - case 1: - return true; - default: - throw new XdrReaderError(`got ${value} when trying to read a bool`); - } - } - - /** - * @inheritDoc - */ - static write(value, writer) { - const intVal = value ? 1 : 0; - Int.write(intVal, writer); - } - - /** - * @inheritDoc - */ - static isValid(value) { - return typeof value === 'boolean'; - } -} diff --git a/src/browser.js b/src/browser.js deleted file mode 100644 index 8551bbe..0000000 --- a/src/browser.js +++ /dev/null @@ -1,4 +0,0 @@ -// eslint-disable-next-line prefer-import/prefer-import-over-require -const exports = require('./index'); - -module.exports = exports; diff --git a/src/config.js b/src/config.js deleted file mode 100644 index 151a06d..0000000 --- a/src/config.js +++ /dev/null @@ -1,239 +0,0 @@ -// eslint-disable-next-line max-classes-per-file -import * as XDRTypes from './types'; -import { Reference } from './reference'; -import { XdrDefinitionError } from './errors'; - -export * from './reference'; - -class SimpleReference extends Reference { - constructor(name) { - super(); - this.name = name; - } - - resolve(context) { - const defn = context.definitions[this.name]; - return defn.resolve(context); - } -} - -class ArrayReference extends Reference { - constructor(childReference, length, variable = false) { - super(); - this.childReference = childReference; - this.length = length; - this.variable = variable; - } - - resolve(context) { - let resolvedChild = this.childReference; - let length = this.length; - - if (resolvedChild instanceof Reference) { - resolvedChild = resolvedChild.resolve(context); - } - - if (length instanceof Reference) { - length = length.resolve(context); - } - - if (this.variable) { - return new XDRTypes.VarArray(resolvedChild, length); - } - return new XDRTypes.Array(resolvedChild, length); - } -} - -class OptionReference extends Reference { - constructor(childReference) { - super(); - this.childReference = childReference; - this.name = childReference.name; - } - - resolve(context) { - let resolvedChild = this.childReference; - - if (resolvedChild instanceof Reference) { - resolvedChild = resolvedChild.resolve(context); - } - - return new XDRTypes.Option(resolvedChild); - } -} - -class SizedReference extends Reference { - constructor(sizedType, length) { - super(); - this.sizedType = sizedType; - this.length = length; - } - - resolve(context) { - let length = this.length; - - if (length instanceof Reference) { - length = length.resolve(context); - } - - return new this.sizedType(length); - } -} - -class Definition { - constructor(constructor, name, cfg) { - this.constructor = constructor; - this.name = name; - this.config = cfg; - } - - // resolve calls the constructor of this definition with the provided context - // and this definitions config values. The definitions constructor should - // populate the final type on `context.results`, and may refer to other - // definitions through `context.definitions` - resolve(context) { - if (this.name in context.results) { - return context.results[this.name]; - } - - return this.constructor(context, this.name, this.config); - } -} - -// let the reference resolution system do its thing -// the "constructor" for a typedef just returns the resolved value -function createTypedef(context, typeName, value) { - if (value instanceof Reference) { - value = value.resolve(context); - } - context.results[typeName] = value; - return value; -} - -function createConst(context, name, value) { - context.results[name] = value; - return value; -} - -class TypeBuilder { - constructor(destination) { - this._destination = destination; - this._definitions = {}; - } - - enum(name, members) { - const result = new Definition(XDRTypes.Enum.create, name, members); - this.define(name, result); - } - - struct(name, members) { - const result = new Definition(XDRTypes.Struct.create, name, members); - this.define(name, result); - } - - union(name, cfg) { - const result = new Definition(XDRTypes.Union.create, name, cfg); - this.define(name, result); - } - - typedef(name, cfg) { - const result = new Definition(createTypedef, name, cfg); - this.define(name, result); - } - - const(name, cfg) { - const result = new Definition(createConst, name, cfg); - this.define(name, result); - } - - void() { - return XDRTypes.Void; - } - - bool() { - return XDRTypes.Bool; - } - - int() { - return XDRTypes.Int; - } - - hyper() { - return XDRTypes.Hyper; - } - - uint() { - return XDRTypes.UnsignedInt; - } - - uhyper() { - return XDRTypes.UnsignedHyper; - } - - float() { - return XDRTypes.Float; - } - - double() { - return XDRTypes.Double; - } - - quadruple() { - return XDRTypes.Quadruple; - } - - string(length) { - return new SizedReference(XDRTypes.String, length); - } - - opaque(length) { - return new SizedReference(XDRTypes.Opaque, length); - } - - varOpaque(length) { - return new SizedReference(XDRTypes.VarOpaque, length); - } - - array(childType, length) { - return new ArrayReference(childType, length); - } - - varArray(childType, maxLength) { - return new ArrayReference(childType, maxLength, true); - } - - option(childType) { - return new OptionReference(childType); - } - - define(name, definition) { - if (this._destination[name] === undefined) { - this._definitions[name] = definition; - } else { - throw new XdrDefinitionError(`${name} is already defined`); - } - } - - lookup(name) { - return new SimpleReference(name); - } - - resolve() { - for (const defn of Object.values(this._definitions)) { - defn.resolve({ - definitions: this._definitions, - results: this._destination - }); - } - } -} - -export function config(fn, types = {}) { - if (fn) { - const builder = new TypeBuilder(types); - fn(builder); - builder.resolve(); - } - - return types; -} diff --git a/src/core/error.ts b/src/core/error.ts new file mode 100644 index 0000000..7cdfe58 --- /dev/null +++ b/src/core/error.ts @@ -0,0 +1,6 @@ +export class XdrError extends Error { + constructor(message: string) { + super(message); + this.name = 'XdrError'; + } +} diff --git a/src/core/helpers.ts b/src/core/helpers.ts new file mode 100644 index 0000000..63e4d10 --- /dev/null +++ b/src/core/helpers.ts @@ -0,0 +1,75 @@ +import { XdrError } from './error.js'; + +export function viewFor(bytes: Uint8Array): DataView { + return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); +} + +export function paddingLength(length: number): number { + return (4 - (length % 4)) % 4; +} + +export function isPlainObject( + value: unknown +): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +export function assertLength(value: number, name: string): void { + if (!Number.isInteger(value) || value < 0 || value > 4294967295) { + throw new XdrError(`${name}: expected uint32 length`); + } +} + +export function assertIntRange( + value: unknown, + min: number, + max: number, + path: string +): asserts value is number { + if ( + typeof value !== 'number' || + !Number.isInteger(value) || + value < min || + value > max + ) { + throw new XdrError(`${path}: expected integer in range ${min}..${max}`); + } +} + +export function assertBigIntRange( + value: unknown, + min: bigint, + max: bigint, + path: string +): asserts value is bigint { + if (typeof value !== 'bigint' || value < min || value > max) { + throw new XdrError(`${path}: expected bigint in range ${min}..${max}`); + } +} + +export function assertFiniteNumber( + value: unknown, + path: string +): asserts value is number { + if (typeof value !== 'number' || !Number.isFinite(value)) { + throw new XdrError(`${path}: expected finite number`); + } +} + +export function assertUint8Array( + value: unknown, + path: string +): asserts value is Uint8Array { + if (!(value instanceof Uint8Array)) { + throw new XdrError(`${path}: expected Uint8Array`); + } +} + +export function assertArray( + value: unknown, + path: string +): asserts value is unknown[] { + if (!Array.isArray(value)) { + throw new XdrError(`${path}: expected array`); + } +} diff --git a/src/core/reader.ts b/src/core/reader.ts new file mode 100644 index 0000000..4175c9e --- /dev/null +++ b/src/core/reader.ts @@ -0,0 +1,102 @@ +import { XdrError } from './error.js'; +import { paddingLength, viewFor } from './helpers.js'; + +export const DEFAULT_MAX_DEPTH = 200; + +export class Reader { + #offset = 0; + #depth = 0; + readonly #maxDepth: number; + + constructor( + private readonly bytes: Uint8Array, + maxDepth: number = DEFAULT_MAX_DEPTH + ) { + this.#maxDepth = maxDepth; + } + + get offset(): number { + return this.#offset; + } + + get remaining(): number { + return this.bytes.length - this.#offset; + } + + enter(path: string): void { + this.#depth += 1; + if (this.#depth > this.#maxDepth) { + throw new XdrError( + `${path}: max recursion depth ${this.#maxDepth} exceeded` + ); + } + } + + exit(): void { + this.#depth -= 1; + } + + done(path: string): void { + if (this.remaining !== 0) { + throw new XdrError( + `${path}: trailing ${this.remaining} byte(s) after XDR value` + ); + } + } + + readBytes(length: number, path: string): Uint8Array { + if (length < 0 || !Number.isInteger(length)) { + throw new XdrError(`${path}: invalid byte length ${length}`); + } + if (this.remaining < length) { + throw new XdrError( + `${path}: incomplete XDR data at offset ${ + this.#offset + }, expected ${length} byte(s)` + ); + } + const result = this.bytes.slice(this.#offset, this.#offset + length); + this.#offset += length; + return result; + } + + skipPadding(length: number, path: string): void { + const padding = paddingLength(length); + const bytes = this.readBytes(padding, path); + for (const byte of bytes) { + if (byte !== 0) { + throw new XdrError(`${path}: non-zero XDR padding`); + } + } + } + + readInt32(path: string): number { + const view = viewFor(this.readBytes(4, path)); + return view.getInt32(0, false); + } + + readUint32(path: string): number { + const view = viewFor(this.readBytes(4, path)); + return view.getUint32(0, false); + } + + readBigInt64(path: string): bigint { + const view = viewFor(this.readBytes(8, path)); + return view.getBigInt64(0, false); + } + + readBigUint64(path: string): bigint { + const view = viewFor(this.readBytes(8, path)); + return view.getBigUint64(0, false); + } + + readFloat32(path: string): number { + const view = viewFor(this.readBytes(4, path)); + return view.getFloat32(0, false); + } + + readFloat64(path: string): number { + const view = viewFor(this.readBytes(8, path)); + return view.getFloat64(0, false); + } +} diff --git a/src/core/writer.ts b/src/core/writer.ts new file mode 100644 index 0000000..73a18cb --- /dev/null +++ b/src/core/writer.ts @@ -0,0 +1,55 @@ +import { paddingLength, viewFor } from './helpers.js'; + +export class Writer { + readonly #chunks: number[] = []; + + writeBytes(bytes: Uint8Array): void { + this.#chunks.push(...bytes); + } + + writePadding(length: number): void { + for (let i = 0; i < paddingLength(length); i += 1) { + this.#chunks.push(0); + } + } + + writeInt32(value: number): void { + const bytes = new Uint8Array(4); + viewFor(bytes).setInt32(0, value, false); + this.writeBytes(bytes); + } + + writeUint32(value: number): void { + const bytes = new Uint8Array(4); + viewFor(bytes).setUint32(0, value, false); + this.writeBytes(bytes); + } + + writeBigInt64(value: bigint): void { + const bytes = new Uint8Array(8); + viewFor(bytes).setBigInt64(0, value, false); + this.writeBytes(bytes); + } + + writeBigUint64(value: bigint): void { + const bytes = new Uint8Array(8); + viewFor(bytes).setBigUint64(0, value, false); + this.writeBytes(bytes); + } + + writeFloat32(value: number): void { + const bytes = new Uint8Array(4); + viewFor(bytes).setFloat32(0, value, false); + this.writeBytes(bytes); + } + + writeFloat64(value: number): void { + const bytes = new Uint8Array(8); + viewFor(bytes).setFloat64(0, value, false); + this.writeBytes(bytes); + } + + toUint8Array(): Uint8Array { + return Uint8Array.from(this.#chunks); + } +} diff --git a/src/core/xdr-type.ts b/src/core/xdr-type.ts new file mode 100644 index 0000000..4890f10 --- /dev/null +++ b/src/core/xdr-type.ts @@ -0,0 +1,55 @@ +import { Reader } from './reader.js'; +import { Writer } from './writer.js'; + +export const UNBOUNDED_MAX_LENGTH = 4294967295; + +export interface DecodeOptions { + readonly maxDepth?: number; +} + +export interface XdrType { + readonly name: string | undefined; + readonly kind: string; + encode(value: T): Uint8Array; + decode(input: Uint8Array, options?: DecodeOptions): T; + validate(value: unknown): value is T; + _read(reader: Reader, path: string): T; + _write(value: T, writer: Writer, path: string): void; +} + +export type Infer = T extends XdrType ? V : never; + +export abstract class BaseType implements XdrType { + abstract readonly kind: string; + readonly name: string | undefined; + + constructor(name: string | undefined = undefined) { + this.name = name; + } + + encode(value: T): Uint8Array { + const writer = new Writer(); + this._write(value, writer, this.name ?? this.kind); + return writer.toUint8Array(); + } + + decode(input: Uint8Array, options?: DecodeOptions): T { + const reader = new Reader(input, options?.maxDepth); + const value = this._read(reader, this.name ?? this.kind); + reader.done(this.name ?? this.kind); + return value; + } + + validate(value: unknown): value is T { + try { + const writer = new Writer(); + this._write(value as T, writer, this.name ?? this.kind); + return true; + } catch { + return false; + } + } + + abstract _read(reader: Reader, path: string): T; + abstract _write(value: T, writer: Writer, path: string): void; +} diff --git a/src/double.js b/src/double.js deleted file mode 100644 index 963617f..0000000 --- a/src/double.js +++ /dev/null @@ -1,27 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Double extends XdrPrimitiveType { - /** - * @inheritDoc - */ - static read(reader) { - return reader.readDoubleBE(); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (typeof value !== 'number') throw new XdrWriterError('not a number'); - - writer.writeDoubleBE(value); - } - - /** - * @inheritDoc - */ - static isValid(value) { - return typeof value === 'number'; - } -} diff --git a/src/enum.js b/src/enum.js deleted file mode 100644 index ec949f1..0000000 --- a/src/enum.js +++ /dev/null @@ -1,94 +0,0 @@ -import { Int } from './int'; -import { XdrPrimitiveType, isSerializableIsh } from './xdr-type'; -import { XdrReaderError, XdrWriterError } from './errors'; - -export class Enum extends XdrPrimitiveType { - constructor(name, value) { - super(); - this.name = name; - this.value = value; - } - - /** - * @inheritDoc - */ - static read(reader) { - const intVal = Int.read(reader); - const res = this._byValue[intVal]; - if (res === undefined) - throw new XdrReaderError( - `unknown ${this.enumName} member for value ${intVal}` - ); - return res; - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (!this.isValid(value)) { - throw new XdrWriterError( - `${value} has enum name ${value?.enumName}, not ${ - this.enumName - }: ${JSON.stringify(value)}` - ); - } - - Int.write(value.value, writer); - } - - /** - * @inheritDoc - */ - static isValid(value) { - return ( - value?.constructor?.enumName === this.enumName || - isSerializableIsh(value, this) - ); - } - - static members() { - return this._members; - } - - static values() { - return Object.values(this._members); - } - - static fromName(name) { - const result = this._members[name]; - - if (!result) - throw new TypeError(`${name} is not a member of ${this.enumName}`); - - return result; - } - - static fromValue(value) { - const result = this._byValue[value]; - if (result === undefined) - throw new TypeError( - `${value} is not a value of any member of ${this.enumName}` - ); - return result; - } - - static create(context, name, members) { - const ChildEnum = class extends Enum {}; - - ChildEnum.enumName = name; - context.results[name] = ChildEnum; - - ChildEnum._members = {}; - ChildEnum._byValue = {}; - - for (const [key, value] of Object.entries(members)) { - const inst = new ChildEnum(key, value); - ChildEnum._members[key] = inst; - ChildEnum._byValue[value] = inst; - ChildEnum[key] = () => inst; - } - - return ChildEnum; - } -} diff --git a/src/errors.js b/src/errors.js deleted file mode 100644 index 9786e64..0000000 --- a/src/errors.js +++ /dev/null @@ -1,25 +0,0 @@ -export class XdrWriterError extends TypeError { - constructor(message) { - super(`XDR Write Error: ${message}`); - } -} - -export class XdrReaderError extends TypeError { - constructor(message) { - super(`XDR Read Error: ${message}`); - } -} - -export class XdrDefinitionError extends TypeError { - constructor(message) { - super(`XDR Type Definition Error: ${message}`); - } -} - -export class XdrNotImplementedDefinitionError extends XdrDefinitionError { - constructor() { - super( - `method not implemented, it should be overloaded in the descendant class.` - ); - } -} diff --git a/src/float.js b/src/float.js deleted file mode 100644 index 706db16..0000000 --- a/src/float.js +++ /dev/null @@ -1,27 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Float extends XdrPrimitiveType { - /** - * @inheritDoc - */ - static read(reader) { - return reader.readFloatBE(); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (typeof value !== 'number') throw new XdrWriterError('not a number'); - - writer.writeFloatBE(value); - } - - /** - * @inheritDoc - */ - static isValid(value) { - return typeof value === 'number'; - } -} diff --git a/src/hyper.js b/src/hyper.js deleted file mode 100644 index dbe7da2..0000000 --- a/src/hyper.js +++ /dev/null @@ -1,38 +0,0 @@ -import { LargeInt } from './large-int'; - -export class Hyper extends LargeInt { - /** - * @param {Array} parts - Slices to encode - */ - constructor(...args) { - super(args); - } - - get low() { - return Number(this._value & 0xffffffffn) << 0; - } - - get high() { - return Number(this._value >> 32n) >> 0; - } - - get size() { - return 64; - } - - get unsigned() { - return false; - } - - /** - * Create Hyper instance from two [high][low] i32 values - * @param {Number} low - Low part of i64 number - * @param {Number} high - High part of i64 number - * @return {LargeInt} - */ - static fromBits(low, high) { - return new this(low, high); - } -} - -Hyper.defineIntBoundaries(); diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 7bfaaa8..0000000 --- a/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export * from './types'; -export * from './config'; - -export { XdrReader } from './serialization/xdr-reader'; -export { XdrWriter } from './serialization/xdr-writer'; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..6546bbb --- /dev/null +++ b/src/index.ts @@ -0,0 +1,27 @@ +// Bases (XdrValue, BytesValue, …) and the schema-builder primitives. +export { XdrError } from './core/error.js'; + +export { Writer } from './core/writer.js'; +export { Reader } from './core/reader.js'; + +export type { XdrType } from './core/xdr-type.js'; +export { BaseType } from './core/xdr-type.js'; + +export { array } from './types/array.js'; +export { bool } from './types/bool.js'; +export { double } from './types/double.js'; +export { enumType } from './types/enum.js'; +export { fixedArray } from './types/fixed-array.js'; +export { float } from './types/float.js'; +export { int32 } from './types/int32.js'; +export { int64 } from './types/int64.js'; +export { lazy } from './types/lazy.js'; +export { opaque } from './types/opaque.js'; +export { option } from './types/option.js'; +export { string } from './types/string.js'; +export { struct } from './types/struct.js'; +export { uint32 } from './types/uint32.js'; +export { uint64 } from './types/uint64.js'; +export { union } from './types/union.js'; +export { varOpaque } from './types/var-opaque.js'; +export { void } from './types/void.js'; diff --git a/src/int.js b/src/int.js deleted file mode 100644 index 3990f14..0000000 --- a/src/int.js +++ /dev/null @@ -1,39 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -const MAX_VALUE = 2147483647; -const MIN_VALUE = -2147483648; - -export class Int extends XdrPrimitiveType { - /** - * @inheritDoc - */ - static read(reader) { - return reader.readInt32BE(); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (typeof value !== 'number') throw new XdrWriterError('not a number'); - - if ((value | 0) !== value) throw new XdrWriterError('invalid i32 value'); - - writer.writeInt32BE(value); - } - - /** - * @inheritDoc - */ - static isValid(value) { - if (typeof value !== 'number' || (value | 0) !== value) { - return false; - } - - return value >= MIN_VALUE && value <= MAX_VALUE; - } -} - -Int.MAX_VALUE = MAX_VALUE; -Int.MIN_VALUE = -MIN_VALUE; diff --git a/src/large-int.js b/src/large-int.js deleted file mode 100644 index ef5d61c..0000000 --- a/src/large-int.js +++ /dev/null @@ -1,143 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { - calculateBigIntBoundaries, - encodeBigIntFromBits, - sliceBigInt -} from './bigint-encoder'; -import { XdrNotImplementedDefinitionError, XdrWriterError } from './errors'; - -export class LargeInt extends XdrPrimitiveType { - /** - * @param {Array} parts - Slices to encode - */ - constructor(args) { - super(); - this._value = encodeBigIntFromBits(args, this.size, this.unsigned); - } - - /** - * Signed/unsigned representation - * @type {Boolean} - * @abstract - */ - get unsigned() { - throw new XdrNotImplementedDefinitionError(); - } - - /** - * Size of the integer in bits - * @type {Number} - * @abstract - */ - get size() { - throw new XdrNotImplementedDefinitionError(); - } - - /** - * Slice integer to parts with smaller bit size - * @param {32|64|128} sliceSize - Size of each part in bits - * @return {BigInt[]} - */ - slice(sliceSize) { - return sliceBigInt(this._value, this.size, sliceSize); - } - - toString() { - return this._value.toString(); - } - - toJSON() { - return { _value: this._value.toString() }; - } - - toBigInt() { - return BigInt(this._value); - } - - /** - * @inheritDoc - */ - static read(reader) { - const { size, unsigned } = this.prototype; - if (size === 64) { - return new this( - unsigned ? reader.readBigUInt64BE() : reader.readBigInt64BE() - ); - } - return new this( - ...Array.from({ length: size / 64 }, () => - reader.readBigUInt64BE() - ).reverse() - ); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (value instanceof this) { - value = value._value; - } else if ( - typeof value !== 'bigint' || - value > this.MAX_VALUE || - value < this.MIN_VALUE - ) - throw new XdrWriterError(`${value} is not a ${this.name}`); - - const { unsigned, size } = this.prototype; - if (size === 64) { - if (unsigned) { - writer.writeBigUInt64BE(value); - } else { - writer.writeBigInt64BE(value); - } - } else { - // extract 64-bit chunks directly from bigint, big-endian order - // This does not use sliceBigint since it returns slices as signed values, - // which is not what we want for encoding - const uvalue = unsigned ? value : BigInt.asUintN(size, value); - for (let i = size / 64 - 1; i >= 0; i--) { - writer.writeBigUInt64BE( - (uvalue >> BigInt(i * 64)) & 0xffffffffffffffffn // 2^64-1 - ); - } - } - } - - /** - * @inheritDoc - */ - static isValid(value) { - if (value instanceof this) return true; - if (typeof value === 'bigint') { - return value >= this.MIN_VALUE && value <= this.MAX_VALUE; - } - return false; - } - - /** - * Create instance from string - * @param {String} string - Numeric representation - * @return {LargeInt} - */ - static fromString(string) { - return new this(string); - } - - static MAX_VALUE = 0n; - - static MIN_VALUE = 0n; - - /** - * @internal - * @return {void} - */ - static defineIntBoundaries() { - const [min, max] = calculateBigIntBoundaries( - this.prototype.size, - this.prototype.unsigned - ); - this.MIN_VALUE = min; - this.MAX_VALUE = max; - } -} diff --git a/src/opaque.js b/src/opaque.js deleted file mode 100644 index ae5f744..0000000 --- a/src/opaque.js +++ /dev/null @@ -1,35 +0,0 @@ -import { XdrCompositeType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Opaque extends XdrCompositeType { - constructor(length) { - super(); - this._length = length; - } - - /** - * @inheritDoc - */ - read(reader) { - return reader.read(this._length); - } - - /** - * @inheritDoc - */ - write(value, writer) { - const { length } = value; - if (length !== this._length) - throw new XdrWriterError( - `got ${value.length} bytes, expected ${this._length}` - ); - writer.write(value, length); - } - - /** - * @inheritDoc - */ - isValid(value) { - return Buffer.isBuffer(value) && value.length === this._length; - } -} diff --git a/src/option.js b/src/option.js deleted file mode 100644 index 8e4db0f..0000000 --- a/src/option.js +++ /dev/null @@ -1,44 +0,0 @@ -import { Bool } from './bool'; -import { NestedXdrType } from './xdr-type'; - -export class Option extends NestedXdrType { - constructor(childType, maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH) { - super(maxDepth); - this._childType = childType; - } - - /** - * @inheritDoc - */ - read(reader, remainingDepth = this._maxDepth) { - NestedXdrType.checkDepth(remainingDepth); - if (Bool.read(reader)) { - return this._childType.read(reader, remainingDepth - 1); - } - - return undefined; - } - - /** - * @inheritDoc - */ - write(value, writer) { - const isPresent = value !== null && value !== undefined; - - Bool.write(isPresent, writer); - - if (isPresent) { - this._childType.write(value, writer); - } - } - - /** - * @inheritDoc - */ - isValid(value) { - if (value === null || value === undefined) { - return true; - } - return this._childType.isValid(value); - } -} diff --git a/src/quadruple.js b/src/quadruple.js deleted file mode 100644 index ccf2f55..0000000 --- a/src/quadruple.js +++ /dev/null @@ -1,16 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrDefinitionError } from './errors'; - -export class Quadruple extends XdrPrimitiveType { - static read() { - throw new XdrDefinitionError('quadruple not supported'); - } - - static write() { - throw new XdrDefinitionError('quadruple not supported'); - } - - static isValid() { - return false; - } -} diff --git a/src/reference.js b/src/reference.js deleted file mode 100644 index e210b43..0000000 --- a/src/reference.js +++ /dev/null @@ -1,11 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrDefinitionError } from './errors'; - -export class Reference extends XdrPrimitiveType { - /* jshint unused: false */ - resolve() { - throw new XdrDefinitionError( - '"resolve" method should be implemented in the descendant class' - ); - } -} diff --git a/src/serialization/xdr-reader.js b/src/serialization/xdr-reader.js deleted file mode 100644 index 4a57817..0000000 --- a/src/serialization/xdr-reader.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @internal - */ -import { XdrReaderError } from '../errors'; - -export class XdrReader { - /** - * @constructor - * @param {Buffer} source - Buffer containing serialized data - */ - constructor(source) { - if (!Buffer.isBuffer(source)) { - if ( - source instanceof Array || - Array.isArray(source) || - ArrayBuffer.isView(source) - ) { - source = Buffer.from(source); - } else { - throw new XdrReaderError(`source invalid: ${source}`); - } - } - - this._buffer = source; - this._length = source.length; - this._index = 0; - } - - /** - * @type {Buffer} - * @private - * @readonly - */ - _buffer; - /** - * @type {Number} - * @private - * @readonly - */ - _length; - /** - * @type {Number} - * @private - * @readonly - */ - _index; - - /** - * Check if the reader reached the end of the input buffer - * @return {Boolean} - */ - get eof() { - return this._index === this._length; - } - - /** - * Advance reader position, check padding and overflow - * @param {Number} size - Bytes to read - * @return {Number} Position to read from - * @private - */ - advance(size) { - const from = this._index; - // advance cursor position - this._index += size; - // check buffer boundaries - if (this._length < this._index) - throw new XdrReaderError( - 'attempt to read outside the boundary of the buffer' - ); - // check that padding is correct for Opaque and String - const padding = 4 - (size % 4 || 4); - if (padding > 0) { - for (let i = 0; i < padding; i++) - if (this._buffer[this._index + i] !== 0) - // all bytes in the padding should be zeros - throw new XdrReaderError('invalid padding'); - this._index += padding; - } - return from; - } - - /** - * Reset reader position - * @return {void} - */ - rewind() { - this._index = 0; - } - - /** - * Remaining unread bytes in the source buffer - * @return {Number} - */ - remainingBytes() { - return this._length - this._index; - } - - /** - * Read byte array from the buffer - * @param {Number} size - Bytes to read - * @return {Buffer} - Sliced portion of the underlying buffer - */ - read(size) { - const from = this.advance(size); - return this._buffer.subarray(from, from + size); - } - - /** - * Read i32 from buffer - * @return {Number} - */ - readInt32BE() { - return this._buffer.readInt32BE(this.advance(4)); - } - - /** - * Read u32 from buffer - * @return {Number} - */ - readUInt32BE() { - return this._buffer.readUInt32BE(this.advance(4)); - } - - /** - * Read i64 from buffer - * @return {BigInt} - */ - readBigInt64BE() { - return this._buffer.readBigInt64BE(this.advance(8)); - } - - /** - * Read u64 from buffer - * @return {BigInt} - */ - readBigUInt64BE() { - return this._buffer.readBigUInt64BE(this.advance(8)); - } - - /** - * Read float from buffer - * @return {Number} - */ - readFloatBE() { - return this._buffer.readFloatBE(this.advance(4)); - } - - /** - * Read double from buffer - * @return {Number} - */ - readDoubleBE() { - return this._buffer.readDoubleBE(this.advance(8)); - } - - /** - * Ensure that input buffer has been consumed in full, otherwise it's a type mismatch - * @return {void} - * @throws {XdrReaderError} - */ - ensureInputConsumed() { - if (this._index !== this._length) - throw new XdrReaderError( - `invalid XDR contract typecast - source buffer not entirely consumed` - ); - } -} diff --git a/src/serialization/xdr-writer.js b/src/serialization/xdr-writer.js deleted file mode 100644 index aad2245..0000000 --- a/src/serialization/xdr-writer.js +++ /dev/null @@ -1,179 +0,0 @@ -const BUFFER_CHUNK = 8192; // 8 KB chunk size increment - -/** - * @internal - */ -export class XdrWriter { - /** - * @param {Buffer|Number} [buffer] - Optional destination buffer - */ - constructor(buffer) { - if (typeof buffer === 'number') { - buffer = Buffer.allocUnsafe(buffer); - } else if (!(buffer instanceof Buffer)) { - buffer = Buffer.allocUnsafe(BUFFER_CHUNK); - } - this._buffer = buffer; - this._length = buffer.length; - } - - /** - * @type {Buffer} - * @private - * @readonly - */ - _buffer; - /** - * @type {Number} - * @private - * @readonly - */ - _length; - /** - * @type {Number} - * @private - * @readonly - */ - _index = 0; - - /** - * Advance writer position, write padding if needed, auto-resize the buffer - * @param {Number} size - Bytes to write - * @return {Number} Position to read from - * @private - */ - alloc(size) { - const from = this._index; - // advance cursor position - this._index += size; - // ensure sufficient buffer size - if (this._length < this._index) { - this.resize(this._index); - } - return from; - } - - /** - * Increase size of the underlying buffer - * @param {Number} minRequiredSize - Minimum required buffer size - * @return {void} - * @private - */ - resize(minRequiredSize) { - // calculate new length, align new buffer length by chunk size - const newLength = Math.ceil(minRequiredSize / BUFFER_CHUNK) * BUFFER_CHUNK; - // create new buffer and copy previous data - const newBuffer = Buffer.allocUnsafe(newLength); - this._buffer.copy(newBuffer, 0, 0, this._length); - // update references - this._buffer = newBuffer; - this._length = newLength; - } - - /** - * Return XDR-serialized value - * @return {Buffer} - */ - finalize() { - // clip underlying buffer to the actually written value - return this._buffer.subarray(0, this._index); - } - - /** - * Return XDR-serialized value as byte array - * @return {Number[]} - */ - toArray() { - return [...this.finalize()]; - } - - /** - * Write byte array from the buffer - * @param {Buffer|String} value - Bytes/string to write - * @param {Number} size - Size in bytes - * @return {XdrReader} - XdrReader wrapper on top of a subarray - */ - write(value, size) { - if (typeof value === 'string') { - // serialize string directly to the output buffer - const offset = this.alloc(size); - this._buffer.write(value, offset, 'utf8'); - } else { - // copy data to the output buffer - if (!(value instanceof Buffer)) { - value = Buffer.from(value); - } - const offset = this.alloc(size); - value.copy(this._buffer, offset, 0, size); - } - - // add padding for 4-byte XDR alignment - const padding = 4 - (size % 4 || 4); - if (padding > 0) { - const offset = this.alloc(padding); - this._buffer.fill(0, offset, this._index); - } - } - - /** - * Write i32 from buffer - * @param {Number} value - Value to serialize - * @return {void} - */ - writeInt32BE(value) { - const offset = this.alloc(4); - this._buffer.writeInt32BE(value, offset); - } - - /** - * Write u32 from buffer - * @param {Number} value - Value to serialize - * @return {void} - */ - writeUInt32BE(value) { - const offset = this.alloc(4); - this._buffer.writeUInt32BE(value, offset); - } - - /** - * Write i64 from buffer - * @param {BigInt} value - Value to serialize - * @return {void} - */ - writeBigInt64BE(value) { - const offset = this.alloc(8); - this._buffer.writeBigInt64BE(value, offset); - } - - /** - * Write u64 from buffer - * @param {BigInt} value - Value to serialize - * @return {void} - */ - writeBigUInt64BE(value) { - const offset = this.alloc(8); - this._buffer.writeBigUInt64BE(value, offset); - } - - /** - * Write float from buffer - * @param {Number} value - Value to serialize - * @return {void} - */ - writeFloatBE(value) { - const offset = this.alloc(4); - this._buffer.writeFloatBE(value, offset); - } - - /** - * Write double from buffer - * @param {Number} value - Value to serialize - * @return {void} - */ - writeDoubleBE(value) { - const offset = this.alloc(8); - this._buffer.writeDoubleBE(value, offset); - } - - static bufferChunkSize = BUFFER_CHUNK; -} diff --git a/src/string.js b/src/string.js deleted file mode 100644 index fec9d4a..0000000 --- a/src/string.js +++ /dev/null @@ -1,58 +0,0 @@ -import { UnsignedInt } from './unsigned-int'; -import { XdrCompositeType } from './xdr-type'; -import { XdrReaderError, XdrWriterError } from './errors'; - -export class String extends XdrCompositeType { - constructor(maxLength = UnsignedInt.MAX_VALUE) { - super(); - this._maxLength = maxLength; - } - - /** - * @inheritDoc - */ - read(reader) { - const size = UnsignedInt.read(reader); - if (size > this._maxLength) - throw new XdrReaderError( - `saw ${size} length String, max allowed is ${this._maxLength}` - ); - - return reader.read(size); - } - - readString(reader) { - return this.read(reader).toString('utf8'); - } - - /** - * @inheritDoc - */ - write(value, writer) { - // calculate string byte size before writing - const size = - typeof value === 'string' - ? Buffer.byteLength(value, 'utf8') - : value.length; - if (size > this._maxLength) - throw new XdrWriterError( - `got ${value.length} bytes, max allowed is ${this._maxLength}` - ); - // write size info - UnsignedInt.write(size, writer); - writer.write(value, size); - } - - /** - * @inheritDoc - */ - isValid(value) { - if (typeof value === 'string') { - return Buffer.byteLength(value, 'utf8') <= this._maxLength; - } - if (value instanceof Array || Buffer.isBuffer(value)) { - return value.length <= this._maxLength; - } - return false; - } -} diff --git a/src/struct.js b/src/struct.js deleted file mode 100644 index ec482a2..0000000 --- a/src/struct.js +++ /dev/null @@ -1,91 +0,0 @@ -import { Reference } from './reference'; -import { NestedXdrType, isSerializableIsh } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Struct extends NestedXdrType { - constructor(attributes, maxDepth) { - const resolvedMaxDepth = maxDepth ?? new.target?._maxDepth; - super(resolvedMaxDepth); - this._attributes = attributes || {}; - } - - /** - * @inheritDoc - */ - static read(reader, remainingDepth = this._maxDepth) { - NestedXdrType.checkDepth(remainingDepth); - - const attributes = {}; - for (const [fieldName, type] of this._fields) { - attributes[fieldName] = type.read(reader, remainingDepth - 1); - } - return new this(attributes, this._maxDepth); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (!this.isValid(value)) { - throw new XdrWriterError( - `${value} has struct name ${value?.constructor?.structName}, not ${ - this.structName - }: ${JSON.stringify(value)}` - ); - } - - for (const [fieldName, type] of this._fields) { - const attribute = value._attributes[fieldName]; - type.write(attribute, writer); - } - } - - /** - * @inheritDoc - */ - static isValid(value) { - return ( - value?.constructor?.structName === this.structName || - isSerializableIsh(value, this) - ); - } - - static create( - context, - name, - fields, - maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH - ) { - const ChildStruct = class extends Struct {}; - - ChildStruct.structName = name; - ChildStruct._maxDepth = maxDepth; - context.results[name] = ChildStruct; - - const mappedFields = new Array(fields.length); - for (let i = 0; i < fields.length; i++) { - const fieldDescriptor = fields[i]; - const fieldName = fieldDescriptor[0]; - let field = fieldDescriptor[1]; - if (field instanceof Reference) { - field = field.resolve(context); - } - mappedFields[i] = [fieldName, field]; - // create accessors - ChildStruct.prototype[fieldName] = createAccessorMethod(fieldName); - } - - ChildStruct._fields = mappedFields; - - return ChildStruct; - } -} - -function createAccessorMethod(name) { - return function readOrWriteAttribute(value) { - if (value !== undefined) { - this._attributes[name] = value; - } - return this._attributes[name]; - }; -} diff --git a/src/types.js b/src/types.js deleted file mode 100644 index f1785f8..0000000 --- a/src/types.js +++ /dev/null @@ -1,26 +0,0 @@ -export * from './int'; -export * from './hyper'; -export * from './unsigned-int'; -export * from './unsigned-hyper'; -export * from './large-int'; - -export * from './float'; -export * from './double'; -export * from './quadruple'; - -export * from './bool'; - -export * from './string'; - -export * from './opaque'; -export * from './var-opaque'; - -export * from './array'; -export * from './var-array'; - -export * from './option'; -export * from './void'; - -export * from './enum'; -export * from './struct'; -export * from './union'; diff --git a/src/types/array.ts b/src/types/array.ts new file mode 100644 index 0000000..d49010f --- /dev/null +++ b/src/types/array.ts @@ -0,0 +1,77 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +import { assertArray, assertLength } from '../core/helpers.js'; + +class ArrayType extends BaseType { + readonly kind = 'array'; + readonly element: XdrType; + readonly maxLength: number; + + constructor(element: XdrType, maxLength: number) { + super(); + assertLength(maxLength, 'array maxLength'); + this.element = element; + this.maxLength = maxLength; + } + + _read(reader: Reader, path: string): T[] { + reader.enter(path); + try { + const length = reader.readUint32(path); + if (length > this.maxLength) { + throw new XdrError( + `${path}: array length ${length} exceeds maximum ${this.maxLength}` + ); + } + return readArray(reader, length, this.element, path); + } finally { + reader.exit(); + } + } + + _write(value: T[], writer: Writer, path: string): void { + assertArray(value, path); + if (value.length > this.maxLength) { + throw new XdrError( + `${path}: array length ${value.length} exceeds maximum ${this.maxLength}` + ); + } + writer.writeUint32(value.length); + writeArray(value, writer, this.element, path); + } +} + +export function array>( + element: T, + maxLength: number +): XdrType[]> { + return new ArrayType(element, maxLength) as XdrType[]>; +} + +export function readArray( + reader: Reader, + length: number, + element: XdrType, + path: string +): T[] { + const values: T[] = []; + for (let i = 0; i < length; i += 1) { + values.push(element._read(reader, `${path}[${i}]`)); + } + return values; +} + +export function writeArray( + values: T[], + writer: Writer, + element: XdrType, + path: string +): void { + let i = 0; + for (const value of values) { + element._write(value, writer, `${path}[${i}]`); + i += 1; + } +} diff --git a/src/types/bool.ts b/src/types/bool.ts new file mode 100644 index 0000000..01adab7 --- /dev/null +++ b/src/types/bool.ts @@ -0,0 +1,28 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; + +class BoolType extends BaseType { + readonly kind = 'bool'; + + _read(reader: Reader, path: string): boolean { + const value = reader.readUint32(path); + if (value === 0) return false; + if (value === 1) return true; + throw new XdrError(`${path}: invalid bool discriminant ${value}`); + } + + _write(value: boolean, writer: Writer, path: string): void { + if (typeof value !== 'boolean') { + throw new XdrError(`${path}: expected boolean`); + } + writer.writeUint32(value ? 1 : 0); + } +} + +export const BOOL_TYPE = new BoolType(); + +export function bool(): XdrType { + return BOOL_TYPE; +} diff --git a/src/types/double.ts b/src/types/double.ts new file mode 100644 index 0000000..17cf450 --- /dev/null +++ b/src/types/double.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertFiniteNumber } from '../core/helpers.js'; + +class DoubleType extends BaseType { + readonly kind = 'double'; + + _read(reader: Reader, path: string): number { + return reader.readFloat64(path); + } + + _write(value: number, writer: Writer, path: string): void { + assertFiniteNumber(value, path); + writer.writeFloat64(value); + } +} + +export function double(): XdrType { + return new DoubleType(); +} diff --git a/src/types/enum.ts b/src/types/enum.ts new file mode 100644 index 0000000..4d7846a --- /dev/null +++ b/src/types/enum.ts @@ -0,0 +1,77 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; + +export type EnumMember> = + Values[keyof Values]; + +export type EnumSchema< + Name extends string, + Values extends Record +> = XdrType> & { + readonly name: Name; +} & Values; + +const RESERVED_ENUM_MEMBER_NAMES = new Set([ + 'name', + 'kind', + 'encode', + 'decode', + 'validate', + '_read', + '_write' +]); + +export class EnumType> extends BaseType< + EnumMember +> { + readonly kind = 'enum'; + // Maps wire value → declared member name. Public so the generic toJson + // walker can render numeric enums as their string names. + readonly nameByValue: ReadonlyMap; + readonly #valuesSet = new Set(); + + constructor(name: string, values: Values) { + super(name); + const nameByValue = new Map(); + for (const [memberName, memberValue] of Object.entries(values)) { + if (this.#valuesSet.has(memberValue)) { + throw new XdrError(`${name}: duplicate enum value ${memberValue}`); + } + this.#valuesSet.add(memberValue); + nameByValue.set(memberValue, memberName); + } + this.nameByValue = nameByValue; + } + + _read(reader: Reader, path: string): EnumMember { + const value = reader.readInt32(path); + if (!this.#valuesSet.has(value)) { + throw new XdrError(`${path}: unknown enum value ${value}`); + } + return value as EnumMember; + } + + _write(value: EnumMember, writer: Writer, path: string): void { + if (typeof value !== 'number' || !this.#valuesSet.has(value)) { + throw new XdrError(`${path}: unknown enum value ${String(value)}`); + } + writer.writeInt32(value); + } +} + +export function enumType< + Name extends string, + Values extends Record +>(name: Name, values: Values): EnumSchema { + for (const memberName of Object.keys(values)) { + if (RESERVED_ENUM_MEMBER_NAMES.has(memberName)) { + throw new XdrError( + `${name}: enum member name ${memberName} collides with reserved property` + ); + } + } + const schema = new EnumType(name, values); + return Object.assign(schema, values) as unknown as EnumSchema; +} diff --git a/src/types/fixed-array.ts b/src/types/fixed-array.ts new file mode 100644 index 0000000..b435ff2 --- /dev/null +++ b/src/types/fixed-array.ts @@ -0,0 +1,45 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +import { assertArray, assertLength } from '../core/helpers.js'; +import { readArray, writeArray } from './array.js'; + +class FixedArrayType extends BaseType { + readonly kind = 'fixedArray'; + readonly element: XdrType; + readonly length: number; + + constructor(element: XdrType, length: number) { + super(); + assertLength(length, 'fixedArray length'); + this.element = element; + this.length = length; + } + + _read(reader: Reader, path: string): T[] { + reader.enter(path); + try { + return readArray(reader, this.length, this.element, path); + } finally { + reader.exit(); + } + } + + _write(value: T[], writer: Writer, path: string): void { + assertArray(value, path); + if (value.length !== this.length) { + throw new XdrError( + `${path}: expected array length ${this.length}, got ${value.length}` + ); + } + writeArray(value, writer, this.element, path); + } +} + +export function fixedArray>( + element: T, + length: number +): XdrType[]> { + return new FixedArrayType(element, length) as XdrType[]>; +} diff --git a/src/types/float.ts b/src/types/float.ts new file mode 100644 index 0000000..32bb71e --- /dev/null +++ b/src/types/float.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertFiniteNumber } from '../core/helpers.js'; + +class FloatType extends BaseType { + readonly kind = 'float'; + + _read(reader: Reader, path: string): number { + return reader.readFloat32(path); + } + + _write(value: number, writer: Writer, path: string): void { + assertFiniteNumber(value, path); + writer.writeFloat32(value); + } +} + +export function float(): XdrType { + return new FloatType(); +} diff --git a/src/types/int32.ts b/src/types/int32.ts new file mode 100644 index 0000000..6a04d51 --- /dev/null +++ b/src/types/int32.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertIntRange } from '../core/helpers.js'; + +class IntType extends BaseType { + readonly kind = 'int32'; + + _read(reader: Reader, path: string): number { + return reader.readInt32(path); + } + + _write(value: number, writer: Writer, path: string): void { + assertIntRange(value, -2147483648, 2147483647, path); + writer.writeInt32(value); + } +} + +export function int32(): XdrType { + return new IntType(); +} diff --git a/src/types/int64.ts b/src/types/int64.ts new file mode 100644 index 0000000..fbbb604 --- /dev/null +++ b/src/types/int64.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertBigIntRange } from '../core/helpers.js'; + +class HyperType extends BaseType { + readonly kind = 'int64'; + + _read(reader: Reader, path: string): bigint { + return reader.readBigInt64(path); + } + + _write(value: bigint, writer: Writer, path: string): void { + assertBigIntRange(value, -(1n << 63n), (1n << 63n) - 1n, path); + writer.writeBigInt64(value); + } +} + +export function int64(): XdrType { + return new HyperType(); +} diff --git a/src/types/lazy.ts b/src/types/lazy.ts new file mode 100644 index 0000000..fa3c00d --- /dev/null +++ b/src/types/lazy.ts @@ -0,0 +1,32 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; + +class LazyType extends BaseType { + readonly kind = 'lazy'; + readonly getSchema: () => XdrType; + + constructor(getSchema: () => XdrType) { + super(); + this.getSchema = getSchema; + } + + _read(reader: Reader, path: string): T { + reader.enter(path); + try { + return this.getSchema()._read(reader, path); + } finally { + reader.exit(); + } + } + + _write(value: T, writer: Writer, path: string): void { + this.getSchema()._write(value, writer, path); + } +} + +export function lazy>( + getSchema: () => T +): XdrType> { + return new LazyType(() => getSchema()) as XdrType>; +} diff --git a/src/types/opaque.ts b/src/types/opaque.ts new file mode 100644 index 0000000..ae93a87 --- /dev/null +++ b/src/types/opaque.ts @@ -0,0 +1,35 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertLength, assertUint8Array } from '../core/helpers.js'; + +class OpaqueType extends BaseType { + readonly kind = 'opaque'; + + constructor(private readonly length: number, name?: string) { + super(name); + assertLength(length, 'opaque length'); + } + + _read(reader: Reader, path: string): Uint8Array { + const bytes = reader.readBytes(this.length, path); + reader.skipPadding(this.length, path); + return bytes; + } + + _write(value: Uint8Array, writer: Writer, path: string): void { + assertUint8Array(value, path); + if (value.length !== this.length) { + throw new XdrError( + `${path}: expected ${this.length} byte(s), got ${value.length}` + ); + } + writer.writeBytes(value); + writer.writePadding(value.length); + } +} + +export function opaque(length: number, name?: string): XdrType { + return new OpaqueType(length, name); +} diff --git a/src/types/option.ts b/src/types/option.ts new file mode 100644 index 0000000..3bc88e8 --- /dev/null +++ b/src/types/option.ts @@ -0,0 +1,37 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +import { BOOL_TYPE } from './bool.js'; + +class OptionType extends BaseType { + readonly kind = 'option'; + readonly element: XdrType; + + constructor(element: XdrType) { + super(); + this.element = element; + } + + _read(reader: Reader, path: string): T | null { + reader.enter(path); + try { + const present = BOOL_TYPE._read(reader, `${path}.present`); + return present ? this.element._read(reader, `${path}.value`) : null; + } finally { + reader.exit(); + } + } + + _write(value: T | null, writer: Writer, path: string): void { + BOOL_TYPE._write(value !== null, writer, `${path}.present`); + if (value !== null) { + this.element._write(value, writer, `${path}.value`); + } + } +} + +export function option>( + element: T +): XdrType | null> { + return new OptionType(element) as XdrType | null>; +} diff --git a/src/types/string.ts b/src/types/string.ts new file mode 100644 index 0000000..55f8d23 --- /dev/null +++ b/src/types/string.ts @@ -0,0 +1,56 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertLength } from '../core/helpers.js'; + +/** + * XDR `string` — length-prefixed bytes, 4-byte padded. + * + * Schema primitive: reads/writes raw `Uint8Array`. Charset handling is a + * higher-layer concern (see e.g. `values/xdr-string.ts` for a wrapper that + * exposes ergonomic string semantics on top of these bytes). Keeping this + * layer charset-free means the `types/` schema primitives have no dependency + * on the consumer-facing `values/` classes — the runtime can be lifted out + * of this repo into a standalone XDR library without modification. + */ +class StringType extends BaseType { + readonly kind = 'string'; + + constructor(private readonly maxLength: number) { + super(); + assertLength(maxLength, 'string maxLength'); + } + + _read(reader: Reader, path: string): Uint8Array { + const length = reader.readUint32(path); + if (length > this.maxLength) { + throw new XdrError( + `${path}: string byte length ${length} exceeds maximum ${this.maxLength}` + ); + } + const bytes = reader.readBytes(length, path); + reader.skipPadding(length, path); + return bytes; + } + + _write(value: Uint8Array, writer: Writer, path: string): void { + if (!(value instanceof Uint8Array)) { + throw new XdrError(`${path}: expected Uint8Array`); + } + if (value.length > this.maxLength) { + throw new XdrError( + `${path}: string byte length ${value.length} exceeds maximum ${this.maxLength}` + ); + } + writer.writeUint32(value.length); + writer.writeBytes(value); + writer.writePadding(value.length); + } +} + +function string_(maxLength: number): XdrType { + return new StringType(maxLength); +} + +export { string_ as string }; diff --git a/src/types/struct.ts b/src/types/struct.ts new file mode 100644 index 0000000..4351274 --- /dev/null +++ b/src/types/struct.ts @@ -0,0 +1,70 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +import { isPlainObject } from '../core/helpers.js'; + +class StructType< + Shape extends Record> +> extends BaseType<{ + readonly [K in keyof Shape]: Infer; +}> { + readonly kind = 'struct'; + // Ordered [fieldName, schema] pairs. Public so the generic toJson/fromJson + // walker can introspect struct shape without going through internals. + readonly entries: ReadonlyArray]>; + + constructor(name: string, fields: Shape) { + super(name); + this.entries = Object.entries(fields) as [string, XdrType][]; + } + + _read( + reader: Reader, + path: string + ): { readonly [K in keyof Shape]: Infer } { + reader.enter(path); + try { + const value: Record = {}; + for (const [key, schema] of this.entries) { + value[key] = schema._read(reader, `${path}.${key}`); + } + return value as { readonly [K in keyof Shape]: Infer }; + } finally { + reader.exit(); + } + } + + _write( + value: { readonly [K in keyof Shape]: Infer }, + writer: Writer, + path: string + ): void { + if (!isPlainObject(value)) { + throw new XdrError(`${path}: expected plain object`); + } + const record = value as Record; + for (const [key, schema] of this.entries) { + if (!(key in record)) { + throw new XdrError(`${path}.${key}: missing struct field`); + } + schema._write(record[key], writer, `${path}.${key}`); + } + } +} + +export function struct< + Name extends string, + Shape extends Record> +>( + name: Name, + fields: Shape +): XdrType<{ readonly [K in keyof Shape]: Infer }> & { + readonly name: Name; +} { + return new StructType(name, fields) as unknown as XdrType<{ + readonly [K in keyof Shape]: Infer; + }> & { + readonly name: Name; + }; +} diff --git a/src/types/uint32.ts b/src/types/uint32.ts new file mode 100644 index 0000000..0d342cf --- /dev/null +++ b/src/types/uint32.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertIntRange } from '../core/helpers.js'; + +class UIntType extends BaseType { + readonly kind = 'uint32'; + + _read(reader: Reader, path: string): number { + return reader.readUint32(path); + } + + _write(value: number, writer: Writer, path: string): void { + assertIntRange(value, 0, 4294967295, path); + writer.writeUint32(value); + } +} + +export function uint32(): XdrType { + return new UIntType(); +} diff --git a/src/types/uint64.ts b/src/types/uint64.ts new file mode 100644 index 0000000..f16eeeb --- /dev/null +++ b/src/types/uint64.ts @@ -0,0 +1,21 @@ +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertBigIntRange } from '../core/helpers.js'; + +class UHyperType extends BaseType { + readonly kind = 'uint64'; + + _read(reader: Reader, path: string): bigint { + return reader.readBigUint64(path); + } + + _write(value: bigint, writer: Writer, path: string): void { + assertBigIntRange(value, 0n, (1n << 64n) - 1n, path); + writer.writeBigUint64(value); + } +} + +export function uint64(): XdrType { + return new UHyperType(); +} diff --git a/src/types/union.ts b/src/types/union.ts new file mode 100644 index 0000000..065a87a --- /dev/null +++ b/src/types/union.ts @@ -0,0 +1,246 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +import { isPlainObject } from '../core/helpers.js'; + +export type Field> = { + readonly kind: 'field'; + readonly name: Name; + readonly schema: T; +}; +type VoidArm = XdrType; +export type UnionArm = VoidArm | Field>; +export type UnionCase = { + readonly name: Name; + readonly discriminant: Disc; + readonly arm: Arm; +}; +type ArmValue = Arm extends Field + ? { readonly [K in Name]: Infer } + : {}; +type CaseValue = C extends UnionCase< + string, + infer Disc, + infer Arm +> + ? { readonly [K in SwitchKey]: Disc } & ArmValue + : never; +type DefaultValue = Arm extends UnionArm + ? { readonly [K in SwitchKey]: Infer } & ArmValue + : never; +type UnionValue< + Switch extends XdrType, + Cases extends readonly UnionCase[], + DefaultArm, + SwitchKey extends string +> = + | CaseValue + | DefaultValue; + +const DEFAULT_CASE_NAME = 'default'; + +class UnionType< + Switch extends XdrType, + Cases extends readonly UnionCase, UnionArm>[], + DefaultArm extends UnionArm | undefined, + SwitchKey extends string +> extends BaseType> { + readonly kind = 'union'; + // Exposed publicly so the generic toJson/fromJson walker can introspect + // union shape (discriminator schema, case list, default arm, switch field). + readonly switchOn: Switch; + readonly cases: Cases; + readonly defaultArm: DefaultArm; + readonly switchKey: SwitchKey; + readonly #casesByDiscriminant = new Map, Cases[number]>(); + + constructor( + name: string, + switchOn: Switch, + cases: Cases, + defaultArm: DefaultArm, + switchKey: SwitchKey + ) { + super(name); + this.switchOn = switchOn; + this.cases = cases; + this.defaultArm = defaultArm; + this.switchKey = switchKey; + const names = new Set(); + for (const unionCase of cases) { + if (names.has(unionCase.name)) { + throw new XdrError( + `${name}: duplicate union case name ${unionCase.name}` + ); + } + names.add(unionCase.name); + if (this.#casesByDiscriminant.has(unionCase.discriminant)) { + throw new XdrError( + `${name}: duplicate union discriminator ${String( + unionCase.discriminant + )}` + ); + } + assertArmPayloadName(name, unionCase.name, unionCase.arm, switchKey); + this.#casesByDiscriminant.set(unionCase.discriminant, unionCase); + } + if (defaultArm !== undefined) { + assertArmPayloadName(name, DEFAULT_CASE_NAME, defaultArm, switchKey); + } + } + + _read( + reader: Reader, + path: string + ): UnionValue { + reader.enter(path); + try { + const discriminant = this.switchOn._read( + reader, + `${path}.${this.switchKey}` + ) as Infer; + const unionCase = this.#casesByDiscriminant.get(discriminant); + const arm = unionCase?.arm ?? this.defaultArm; + if (arm === undefined) { + throw new XdrError( + `${path}: no case for union discriminator ${String(discriminant)}` + ); + } + return readUnionArm( + discriminant, + arm, + this.switchKey, + reader, + `${path}.${unionCase?.name ?? DEFAULT_CASE_NAME}` + ) as UnionValue; + } finally { + reader.exit(); + } + } + + _write( + value: UnionValue, + writer: Writer, + path: string + ): void { + if (!isPlainObject(value) || !(this.switchKey in value)) { + throw new XdrError( + `${path}: expected union object with ${this.switchKey} discriminator` + ); + } + const unionValue = value as Readonly>; + const switchValue = unionValue[this.switchKey] as Infer; + const unionCase = this.#casesByDiscriminant.get(switchValue); + const arm = unionCase?.arm ?? this.defaultArm; + if (arm === undefined) { + throw new XdrError( + `${path}: no case for union discriminator ${String(switchValue)}` + ); + } + this.switchOn._write(switchValue, writer, `${path}.${this.switchKey}`); + writeUnionArm( + unionValue, + arm, + writer, + `${path}.${unionCase?.name ?? DEFAULT_CASE_NAME}` + ); + } +} + +export function field>( + name: Name, + schema: T +): Field { + return { kind: 'field', name, schema }; +} + +function case_< + Name extends string, + Disc extends string | number | boolean, + Arm extends UnionArm +>(name: Name, discriminant: Disc, arm: Arm): UnionCase { + return { name, discriminant, arm }; +} + +export { case_ as case }; + +export function union< + Name extends string, + Switch extends XdrType, + Cases extends readonly UnionCase, UnionArm>[], + DefaultArm extends UnionArm | undefined = undefined, + SwitchKey extends string = 'type' +>( + name: Name, + options: { + readonly switchOn: Switch; + readonly cases: Cases; + readonly defaultArm?: DefaultArm; + readonly switchKey?: SwitchKey; + } +): XdrType> & { + readonly name: Name; +} { + const switchKey = (options.switchKey ?? 'type') as SwitchKey; + return new UnionType( + name, + options.switchOn, + options.cases, + options.defaultArm, + switchKey + ) as unknown as XdrType> & { + readonly name: Name; + }; +} + +function readUnionArm( + discriminant: unknown, + arm: UnionArm, + switchKey: string, + reader: Reader, + path: string +): Record { + const base = { [switchKey]: discriminant }; + if (isFieldArm(arm)) { + return { + ...base, + [arm.name]: arm.schema._read(reader, `${path}.${arm.name}`) + }; + } + arm._read(reader, path); + return base; +} + +function writeUnionArm( + value: Readonly>, + arm: UnionArm, + writer: Writer, + path: string +): void { + if (isFieldArm(arm)) { + if (!(arm.name in value)) { + throw new XdrError(`${path}.${arm.name}: missing union arm payload`); + } + arm.schema._write(value[arm.name], writer, `${path}.${arm.name}`); + return; + } + arm._write(undefined, writer, path); +} + +function assertArmPayloadName( + unionName: string, + caseName: string, + arm: UnionArm, + switchKey: string +): void { + if (isFieldArm(arm) && arm.name === switchKey) { + throw new XdrError( + `${unionName}.${caseName}: union arm payload field must not be named ${switchKey}` + ); + } +} + +function isFieldArm(arm: UnionArm): arm is Field> { + return 'schema' in arm; +} diff --git a/src/types/var-opaque.ts b/src/types/var-opaque.ts new file mode 100644 index 0000000..8be0133 --- /dev/null +++ b/src/types/var-opaque.ts @@ -0,0 +1,45 @@ +import { XdrError } from '../core/error.js'; +import type { Reader } from '../core/reader.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; +import { assertLength, assertUint8Array } from '../core/helpers.js'; + +class VarOpaqueType extends BaseType { + readonly kind = 'varOpaque'; + + constructor(private readonly maxLength: number, name?: string) { + super(name); + assertLength(maxLength, 'varOpaque maxLength'); + } + + _read(reader: Reader, path: string): Uint8Array { + const length = reader.readUint32(path); + if (length > this.maxLength) { + throw new XdrError( + `${path}: opaque length ${length} exceeds maximum ${this.maxLength}` + ); + } + const bytes = reader.readBytes(length, path); + reader.skipPadding(length, path); + return bytes; + } + + _write(value: Uint8Array, writer: Writer, path: string): void { + assertUint8Array(value, path); + if (value.length > this.maxLength) { + throw new XdrError( + `${path}: opaque length ${value.length} exceeds maximum ${this.maxLength}` + ); + } + writer.writeUint32(value.length); + writer.writeBytes(value); + writer.writePadding(value.length); + } +} + +export function varOpaque( + maxLength: number, + name?: string +): XdrType { + return new VarOpaqueType(maxLength, name); +} diff --git a/src/types/void.ts b/src/types/void.ts new file mode 100644 index 0000000..192c274 --- /dev/null +++ b/src/types/void.ts @@ -0,0 +1,23 @@ +import { XdrError } from '../core/error.js'; +import type { Writer } from '../core/writer.js'; +import { BaseType, type XdrType } from '../core/xdr-type.js'; + +class VoidType extends BaseType { + readonly kind = 'void'; + + _read(): void { + return undefined; + } + + _write(value: void, _writer: Writer, path: string): void { + if (value !== undefined) { + throw new XdrError(`${path}: expected void`); + } + } +} + +function void_(): XdrType { + return new VoidType(); +} + +export { void_ as void }; diff --git a/src/union.js b/src/union.js deleted file mode 100644 index dfe699e..0000000 --- a/src/union.js +++ /dev/null @@ -1,179 +0,0 @@ -import { Void } from './void'; -import { Reference } from './reference'; -import { NestedXdrType, isSerializableIsh } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Union extends NestedXdrType { - constructor(aSwitch, value, maxDepth) { - const resolvedMaxDepth = maxDepth ?? new.target?._maxDepth; - super(resolvedMaxDepth); - this.set(aSwitch, value); - } - - set(aSwitch, value) { - if (typeof aSwitch === 'string') { - aSwitch = this.constructor._switchOn.fromName(aSwitch); - } - - this._switch = aSwitch; - const arm = this.constructor.armForSwitch(this._switch); - this._arm = arm; - this._armType = arm === Void ? Void : this.constructor._arms[arm]; - this._value = value; - } - - get(armName = this._arm) { - if (this._arm !== Void && this._arm !== armName) - throw new TypeError(`${armName} not set`); - return this._value; - } - - switch() { - return this._switch; - } - - arm() { - return this._arm; - } - - armType() { - return this._armType; - } - - value() { - return this._value; - } - - static armForSwitch(aSwitch) { - const member = this._switches.get(aSwitch); - if (member !== undefined) { - return member; - } - if (this._defaultArm) { - return this._defaultArm; - } - throw new TypeError(`Bad union switch: ${aSwitch}`); - } - - static armTypeForArm(arm) { - if (arm === Void) { - return Void; - } - return this._arms[arm]; - } - - /** - * @inheritDoc - */ - static read(reader, remainingDepth = this._maxDepth) { - NestedXdrType.checkDepth(remainingDepth); - const aSwitch = this._switchOn.read(reader, remainingDepth - 1); - const arm = this.armForSwitch(aSwitch); - const armType = arm === Void ? Void : this._arms[arm]; - let value; - if (armType !== undefined) { - value = armType.read(reader, remainingDepth - 1); - } else { - value = arm.read(reader, remainingDepth - 1); - } - return new this(aSwitch, value, this._maxDepth); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if (!this.isValid(value)) { - throw new XdrWriterError( - `${value} has union name ${value?.unionName}, not ${ - this.unionName - }: ${JSON.stringify(value)}` - ); - } - - this._switchOn.write(value.switch(), writer); - value.armType().write(value.value(), writer); - } - - /** - * @inheritDoc - */ - static isValid(value) { - return ( - value?.constructor?.unionName === this.unionName || - isSerializableIsh(value, this) - ); - } - - static create( - context, - name, - config, - maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH - ) { - const ChildUnion = class extends Union {}; - - ChildUnion.unionName = name; - ChildUnion._maxDepth = maxDepth; - context.results[name] = ChildUnion; - - if (config.switchOn instanceof Reference) { - ChildUnion._switchOn = config.switchOn.resolve(context); - } else { - ChildUnion._switchOn = config.switchOn; - } - - ChildUnion._switches = new Map(); - ChildUnion._arms = {}; - - // resolve default arm - let defaultArm = config.defaultArm; - if (defaultArm instanceof Reference) { - defaultArm = defaultArm.resolve(context); - } - - ChildUnion._defaultArm = defaultArm; - - for (const [aSwitch, armName] of config.switches) { - const key = - typeof aSwitch === 'string' - ? ChildUnion._switchOn.fromName(aSwitch) - : aSwitch; - - ChildUnion._switches.set(key, armName); - } - - // add enum-based helpers - // NOTE: we don't have good notation for "is a subclass of XDR.Enum", - // and so we use the following check (does _switchOn have a `values` - // attribute) to approximate the intent. - if (ChildUnion._switchOn.values !== undefined) { - for (const aSwitch of ChildUnion._switchOn.values()) { - // Add enum-based constructors - ChildUnion[aSwitch.name] = function ctr(value) { - return new ChildUnion(aSwitch, value); - }; - - // Add enum-based "set" helpers - ChildUnion.prototype[aSwitch.name] = function set(value) { - return this.set(aSwitch, value); - }; - } - } - - if (config.arms) { - for (const [armsName, value] of Object.entries(config.arms)) { - ChildUnion._arms[armsName] = - value instanceof Reference ? value.resolve(context) : value; - // Add arm accessor helpers - if (value !== Void) { - ChildUnion.prototype[armsName] = function get() { - return this.get(armsName); - }; - } - } - } - - return ChildUnion; - } -} diff --git a/src/unsigned-hyper.js b/src/unsigned-hyper.js deleted file mode 100644 index af3b81d..0000000 --- a/src/unsigned-hyper.js +++ /dev/null @@ -1,38 +0,0 @@ -import { LargeInt } from './large-int'; - -export class UnsignedHyper extends LargeInt { - /** - * @param {Array} parts - Slices to encode - */ - constructor(...args) { - super(args); - } - - get low() { - return Number(this._value & 0xffffffffn) << 0; - } - - get high() { - return Number(this._value >> 32n) >> 0; - } - - get size() { - return 64; - } - - get unsigned() { - return true; - } - - /** - * Create UnsignedHyper instance from two [high][low] i32 values - * @param {Number} low - Low part of u64 number - * @param {Number} high - High part of u64 number - * @return {UnsignedHyper} - */ - static fromBits(low, high) { - return new this(low, high); - } -} - -UnsignedHyper.defineIntBoundaries(); diff --git a/src/unsigned-int.js b/src/unsigned-int.js deleted file mode 100644 index 6d71fa4..0000000 --- a/src/unsigned-int.js +++ /dev/null @@ -1,42 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -const MAX_VALUE = 4294967295; -const MIN_VALUE = 0; - -export class UnsignedInt extends XdrPrimitiveType { - /** - * @inheritDoc - */ - static read(reader) { - return reader.readUInt32BE(); - } - - /** - * @inheritDoc - */ - static write(value, writer) { - if ( - typeof value !== 'number' || - !(value >= MIN_VALUE && value <= MAX_VALUE) || - value % 1 !== 0 - ) - throw new XdrWriterError('invalid u32 value'); - - writer.writeUInt32BE(value); - } - - /** - * @inheritDoc - */ - static isValid(value) { - if (typeof value !== 'number' || value % 1 !== 0) { - return false; - } - - return value >= MIN_VALUE && value <= MAX_VALUE; - } -} - -UnsignedInt.MAX_VALUE = MAX_VALUE; -UnsignedInt.MIN_VALUE = MIN_VALUE; diff --git a/src/var-array.js b/src/var-array.js deleted file mode 100644 index b9dfe9d..0000000 --- a/src/var-array.js +++ /dev/null @@ -1,72 +0,0 @@ -import { UnsignedInt } from './unsigned-int'; -import { NestedXdrType } from './xdr-type'; -import { XdrReaderError, XdrWriterError } from './errors'; - -export class VarArray extends NestedXdrType { - constructor( - childType, - maxLength = UnsignedInt.MAX_VALUE, - maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH - ) { - super(maxDepth); - this._childType = childType; - this._maxLength = maxLength; - } - - /** - * @inheritDoc - */ - read(reader, remainingDepth = this._maxDepth) { - NestedXdrType.checkDepth(remainingDepth); - const length = UnsignedInt.read(reader); - if (length > this._maxLength) - throw new XdrReaderError( - `saw ${length} length VarArray, max allowed is ${this._maxLength}` - ); - - // Upper-bound fast-fail: remaining bytes is a loose capacity check since - // each XDR element typically consumes more than 1 byte (e.g., 4+ bytes) - if (length > reader.remainingBytes()) { - throw new XdrReaderError( - `VarArray length ${length} exceeds remaining ${reader.remainingBytes()} bytes` - ); - } - - const result = []; - for (let i = 0; i < length; i++) { - result.push(this._childType.read(reader, remainingDepth - 1)); - } - return result; - } - - /** - * @inheritDoc - */ - write(value, writer) { - if (!(value instanceof Array)) - throw new XdrWriterError(`value is not array`); - - if (value.length > this._maxLength) - throw new XdrWriterError( - `got array of size ${value.length}, max allowed is ${this._maxLength}` - ); - - UnsignedInt.write(value.length, writer); - for (const child of value) { - this._childType.write(child, writer); - } - } - - /** - * @inheritDoc - */ - isValid(value) { - if (!(value instanceof Array) || value.length > this._maxLength) { - return false; - } - for (const child of value) { - if (!this._childType.isValid(child)) return false; - } - return true; - } -} diff --git a/src/var-opaque.js b/src/var-opaque.js deleted file mode 100644 index 056c97f..0000000 --- a/src/var-opaque.js +++ /dev/null @@ -1,43 +0,0 @@ -import { UnsignedInt } from './unsigned-int'; -import { XdrCompositeType } from './xdr-type'; -import { XdrReaderError, XdrWriterError } from './errors'; - -export class VarOpaque extends XdrCompositeType { - constructor(maxLength = UnsignedInt.MAX_VALUE) { - super(); - this._maxLength = maxLength; - } - - /** - * @inheritDoc - */ - read(reader) { - const size = UnsignedInt.read(reader); - if (size > this._maxLength) - throw new XdrReaderError( - `saw ${size} length VarOpaque, max allowed is ${this._maxLength}` - ); - return reader.read(size); - } - - /** - * @inheritDoc - */ - write(value, writer) { - const { length } = value; - if (value.length > this._maxLength) - throw new XdrWriterError( - `got ${value.length} bytes, max allowed is ${this._maxLength}` - ); - // write size info - UnsignedInt.write(length, writer); - writer.write(value, length); - } - - /** - * @inheritDoc - */ - isValid(value) { - return Buffer.isBuffer(value) && value.length <= this._maxLength; - } -} diff --git a/src/void.js b/src/void.js deleted file mode 100644 index 631379d..0000000 --- a/src/void.js +++ /dev/null @@ -1,19 +0,0 @@ -import { XdrPrimitiveType } from './xdr-type'; -import { XdrWriterError } from './errors'; - -export class Void extends XdrPrimitiveType { - /* jshint unused: false */ - - static read() { - return undefined; - } - - static write(value) { - if (value !== undefined) - throw new XdrWriterError('trying to write value to a void slot'); - } - - static isValid(value) { - return value === undefined; - } -} diff --git a/src/xdr-type.js b/src/xdr-type.js deleted file mode 100644 index ab89855..0000000 --- a/src/xdr-type.js +++ /dev/null @@ -1,253 +0,0 @@ -/* eslint-disable max-classes-per-file */ -import { XdrReader } from './serialization/xdr-reader'; -import { XdrWriter } from './serialization/xdr-writer'; -import { XdrNotImplementedDefinitionError, XdrReaderError } from './errors'; - -class XdrType { - /** - * Encode value to XDR format - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {String|Buffer} - */ - toXDR(format = 'raw') { - if (!this.write) return this.constructor.toXDR(this, format); - - const writer = new XdrWriter(); - this.write(this, writer); - return encodeResult(writer.finalize(), format); - } - - /** - * Decode XDR-encoded value - * @param {Buffer|String} input - XDR-encoded input data - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {this} - */ - fromXDR(input, format = 'raw') { - if (!this.read) return this.constructor.fromXDR(input, format); - - const reader = new XdrReader(decodeInput(input, format)); - const result = this.read(reader); - reader.ensureInputConsumed(); - return result; - } - - /** - * Check whether input contains a valid XDR-encoded value - * @param {Buffer|String} input - XDR-encoded input data - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {Boolean} - */ - validateXDR(input, format = 'raw') { - try { - this.fromXDR(input, format); - return true; - } catch (e) { - return false; - } - } - - /** - * Encode value to XDR format - * @param {this} value - Value to serialize - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {Buffer} - */ - static toXDR(value, format = 'raw') { - const writer = new XdrWriter(); - this.write(value, writer); - return encodeResult(writer.finalize(), format); - } - - /** - * Decode XDR-encoded value - * @param {Buffer|String} input - XDR-encoded input data - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {this} - */ - static fromXDR(input, format = 'raw') { - const reader = new XdrReader(decodeInput(input, format)); - const result = this.read(reader); - reader.ensureInputConsumed(); - return result; - } - - /** - * Check whether input contains a valid XDR-encoded value - * @param {Buffer|String} input - XDR-encoded input data - * @param {XdrEncodingFormat} [format] - Encoding format (one of "raw", "hex", "base64") - * @return {Boolean} - */ - static validateXDR(input, format = 'raw') { - try { - this.fromXDR(input, format); - return true; - } catch (e) { - return false; - } - } -} - -export class XdrPrimitiveType extends XdrType { - /** - * Read value from the XDR-serialized input - * @param {XdrReader} reader - XdrReader instance - * @return {this} - * @abstract - */ - // eslint-disable-next-line no-unused-vars - static read(reader) { - throw new XdrNotImplementedDefinitionError(); - } - - /** - * Write XDR value to the buffer - * @param {this} value - Value to write - * @param {XdrWriter} writer - XdrWriter instance - * @return {void} - * @abstract - */ - // eslint-disable-next-line no-unused-vars - static write(value, writer) { - throw new XdrNotImplementedDefinitionError(); - } - - /** - * Check whether XDR primitive value is valid - * @param {this} value - Value to check - * @return {Boolean} - * @abstract - */ - // eslint-disable-next-line no-unused-vars - static isValid(value) { - return false; - } -} - -export class XdrCompositeType extends XdrType { - // Every descendant should implement two methods: read(reader) and write(value, writer) - - /** - * Check whether XDR primitive value is valid - * @param {this} value - Value to check - * @return {Boolean} - * @abstract - */ - // eslint-disable-next-line no-unused-vars - isValid(value) { - return false; - } -} - -export class NestedXdrType extends XdrCompositeType { - /** - * @constructor - * @param {number} maxDepth - Maximum allowed depth for nested structures (e.g. arrays of arrays), to prevent DoS via excessively deep nesting - */ - constructor(maxDepth) { - super(); - this._maxDepth = maxDepth ?? NestedXdrType.DEFAULT_MAX_DEPTH; - } - - /** - * Check remaining depth budget and throw if exceeded - * @param {number} remainingDepth - Remaining recursion budget - * @returns {void} - * @throws {XdrReaderError} If remaining depth budget is exhausted - * @throws {TypeError} If remainingDepth is not a finite number - * @protected - */ - static checkDepth(remainingDepth) { - if (remainingDepth === undefined) return; - if (!Number.isFinite(remainingDepth)) { - throw new TypeError( - `remainingDepth (current remaining decoding depth budget) must be a finite number, got ${typeof remainingDepth}: ${remainingDepth}` - ); - } - if (remainingDepth < 0) { - throw new XdrReaderError('exceeded max decoding depth'); - } - } -} - -NestedXdrType.DEFAULT_MAX_DEPTH = 200; -NestedXdrType._maxDepth = NestedXdrType.DEFAULT_MAX_DEPTH; - -class InvalidXdrEncodingFormatError extends TypeError { - constructor(format) { - super(`Invalid format ${format}, must be one of "raw", "hex", "base64"`); - } -} - -function encodeResult(buffer, format) { - switch (format) { - case 'raw': - return buffer; - case 'hex': - return buffer.toString('hex'); - case 'base64': - return buffer.toString('base64'); - default: - throw new InvalidXdrEncodingFormatError(format); - } -} - -function decodeInput(input, format) { - switch (format) { - case 'raw': - return input; - case 'hex': - return Buffer.from(input, 'hex'); - case 'base64': - return Buffer.from(input, 'base64'); - default: - throw new InvalidXdrEncodingFormatError(format); - } -} - -/** - * Provides a "duck typed" version of the native `instanceof` for read/write. - * - * "Duck typing" means if the parameter _looks like_ and _acts like_ a duck - * (i.e. the type we're checking), it will be treated as that type. - * - * In this case, the "type" we're looking for is "like XdrType" but also "like - * XdrCompositeType|XdrPrimitiveType" (i.e. serializable), but also conditioned - * on a particular subclass of "XdrType" (e.g. {@link Union} which extends - * XdrType). - * - * This makes the package resilient to downstream systems that may be combining - * many versions of a package across its stack that are technically compatible - * but fail `instanceof` checks due to cross-pollination. - */ -export function isSerializableIsh(value, subtype) { - return ( - value !== undefined && - value !== null && // prereqs, otherwise `getPrototypeOf` pops - (value instanceof subtype || // quickest check - // Do an initial constructor check (anywhere is fine so that children of - // `subtype` still work), then - (hasConstructor(value, subtype) && - // ensure it has read/write methods, then - typeof value.constructor.read === 'function' && - typeof value.constructor.write === 'function' && - // ensure XdrType is in the prototype chain - hasConstructor(value, 'XdrType'))) - ); -} - -/** Tries to find `subtype` in any of the constructors or meta of `instance`. */ -export function hasConstructor(instance, subtype) { - do { - const ctor = instance.constructor; - if (ctor.name === subtype) { - return true; - } - // eslint-disable-next-line no-cond-assign - } while ((instance = Object.getPrototypeOf(instance))); - return false; -} - -/** - * @typedef {'raw'|'hex'|'base64'} XdrEncodingFormat - */ From 7f1531407a86addb348f66fac0751f9cd99c245b Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 12:25:01 -0700 Subject: [PATCH 02/22] refactor: add tests for new xdr classes / replace mocha-karma-sinon test framework with vitest --- test/unit/_helpers.ts | 22 ++ test/unit/array.test.ts | 46 +++ test/unit/array_test.js | 199 ------------ test/unit/bigint-encoder_test.js | 396 ------------------------ test/unit/bool.test.ts | 49 +++ test/unit/bool_test.js | 47 --- test/unit/define_test.js | 175 ----------- test/unit/double.test.ts | 35 +++ test/unit/double_test.js | 62 ---- test/unit/dynamic-buffer-resize_test.js | 19 -- test/unit/enum.test.ts | 58 ++++ test/unit/enum_test.js | 117 ------- test/unit/fixed-array.test.ts | 40 +++ test/unit/float.test.ts | 35 +++ test/unit/float_test.js | 58 ---- test/unit/hyper_test.js | 108 ------- test/unit/int32.test.ts | 53 ++++ test/unit/int64.test.ts | 52 ++++ test/unit/int_test.js | 78 ----- test/unit/large-int-128_test.js | 216 ------------- test/unit/lazy.test.ts | 44 +++ test/unit/opaque.test.ts | 44 +++ test/unit/opaque_test.js | 54 ---- test/unit/option.test.ts | 32 ++ test/unit/option_test.js | 102 ------ test/unit/quadruple_test.js | 35 --- test/unit/reader.test.ts | 90 ++++++ test/unit/string.test.ts | 70 +++++ test/unit/string_test.js | 148 --------- test/unit/struct.test.ts | 64 ++++ test/unit/struct_test.js | 252 --------------- test/unit/struct_union_test.js | 43 --- test/unit/uint32.test.ts | 49 +++ test/unit/uint64.test.ts | 42 +++ test/unit/union.test.ts | 119 +++++++ test/unit/union_test.js | 334 -------------------- test/unit/unsigned-hyper_test.js | 99 ------ test/unit/unsigned-int_test.js | 70 ----- test/unit/var-array_test.js | 249 --------------- test/unit/var-opaque.test.ts | 49 +++ test/unit/var-opaque_test.js | 84 ----- test/unit/void.test.ts | 26 ++ test/unit/void_test.js | 44 --- test/unit/writer.test.ts | 55 ++++ 44 files changed, 1074 insertions(+), 2989 deletions(-) create mode 100644 test/unit/_helpers.ts create mode 100644 test/unit/array.test.ts delete mode 100644 test/unit/array_test.js delete mode 100644 test/unit/bigint-encoder_test.js create mode 100644 test/unit/bool.test.ts delete mode 100644 test/unit/bool_test.js delete mode 100644 test/unit/define_test.js create mode 100644 test/unit/double.test.ts delete mode 100644 test/unit/double_test.js delete mode 100644 test/unit/dynamic-buffer-resize_test.js create mode 100644 test/unit/enum.test.ts delete mode 100644 test/unit/enum_test.js create mode 100644 test/unit/fixed-array.test.ts create mode 100644 test/unit/float.test.ts delete mode 100644 test/unit/float_test.js delete mode 100644 test/unit/hyper_test.js create mode 100644 test/unit/int32.test.ts create mode 100644 test/unit/int64.test.ts delete mode 100644 test/unit/int_test.js delete mode 100644 test/unit/large-int-128_test.js create mode 100644 test/unit/lazy.test.ts create mode 100644 test/unit/opaque.test.ts delete mode 100644 test/unit/opaque_test.js create mode 100644 test/unit/option.test.ts delete mode 100644 test/unit/option_test.js delete mode 100644 test/unit/quadruple_test.js create mode 100644 test/unit/reader.test.ts create mode 100644 test/unit/string.test.ts delete mode 100644 test/unit/string_test.js create mode 100644 test/unit/struct.test.ts delete mode 100644 test/unit/struct_test.js delete mode 100644 test/unit/struct_union_test.js create mode 100644 test/unit/uint32.test.ts create mode 100644 test/unit/uint64.test.ts create mode 100644 test/unit/union.test.ts delete mode 100644 test/unit/union_test.js delete mode 100644 test/unit/unsigned-hyper_test.js delete mode 100644 test/unit/unsigned-int_test.js delete mode 100644 test/unit/var-array_test.js create mode 100644 test/unit/var-opaque.test.ts delete mode 100644 test/unit/var-opaque_test.js create mode 100644 test/unit/void.test.ts delete mode 100644 test/unit/void_test.js create mode 100644 test/unit/writer.test.ts diff --git a/test/unit/_helpers.ts b/test/unit/_helpers.ts new file mode 100644 index 0000000..dab0ad0 --- /dev/null +++ b/test/unit/_helpers.ts @@ -0,0 +1,22 @@ +import type { XdrType } from '../../src/index.js'; + +export function bytes(values: number[]): Uint8Array { + return Uint8Array.from(values); +} + +export function toArray(value: Uint8Array): number[] { + return Array.from(value); +} + +export function roundTrip(schema: XdrType, value: T): T { + return schema.decode(schema.encode(value)); +} + +// Calls encode with intentionally mistyped input, for negative tests that +// exercise the runtime guards without fighting the compiler. +export function encodeInvalid( + schema: XdrType, + value: unknown +): Uint8Array { + return schema.encode(value as T); +} diff --git a/test/unit/array.test.ts b/test/unit/array.test.ts new file mode 100644 index 0000000..1b3aac6 --- /dev/null +++ b/test/unit/array.test.ts @@ -0,0 +1,46 @@ +import { describe, it, expect } from 'vitest'; +import { array, int32 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = array(int32(), 3); + +describe('array (variable-length)', () => { + describe('encode', () => { + it('writes a length prefix followed by each element', () => { + expect(toArray(schema.encode([1, 2, 3]))).toEqual([ + 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 + ]); + }); + + it('encodes an empty array', () => { + expect(toArray(schema.encode([]))).toEqual([0, 0, 0, 0]); + }); + + it('throws when exceeding maxLength', () => { + expect(() => schema.encode([1, 2, 3, 4])).toThrow(/exceeds maximum/i); + }); + + it('throws for non-array input', () => { + expect(() => encodeInvalid(schema, 'nope')).toThrow(/expected array/i); + }); + }); + + describe('decode', () => { + it('reads the length prefix then the elements', () => { + expect( + schema.decode(bytes([0, 0, 0, 2, 0, 0, 0, 7, 0, 0, 0, 8])) + ).toEqual([7, 8]); + expect(schema.decode(bytes([0, 0, 0, 0]))).toEqual([]); + }); + + it('throws when the declared length exceeds maxLength', () => { + expect(() => + schema.decode(bytes([0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 2])) + ).toThrow(/exceeds maximum/i); + }); + }); + + it('round-trips element values', () => { + expect(roundTrip(schema, [10, 20, 30])).toEqual([10, 20, 30]); + }); +}); diff --git a/test/unit/array_test.js b/test/unit/array_test.js deleted file mode 100644 index 2749e05..0000000 --- a/test/unit/array_test.js +++ /dev/null @@ -1,199 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -let zero = new XDR.Array(XDR.Int, 0); -let one = new XDR.Array(XDR.Int, 1); -let many = new XDR.Array(XDR.Int, 2); - -describe('Array#read', function () { - function createFixedSizeChild() { - let calls = 0; - - return { - FixedSizeChild: class FixedSizeChild { - static read(io) { - calls += 1; - return io.readInt32BE(); - } - - static write() {} - - static isValid() { - return true; - } - }, - getCalls() { - return calls; - } - }; - } - - it('decodes correctly', function () { - expect(read(zero, [])).to.eql([]); - expect(read(zero, [0x00, 0x00, 0x00, 0x00])).to.eql([]); - - expect(read(one, [0x00, 0x00, 0x00, 0x00])).to.eql([0]); - expect(read(one, [0x00, 0x00, 0x00, 0x01])).to.eql([1]); - - expect(read(many, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])).to.eql( - [0, 1] - ); - expect(read(many, [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])).to.eql( - [1, 1] - ); - }); - - it("throws XdrReaderError when the byte stream isn't large enough", function () { - expect(() => read(many, [0x00, 0x00, 0x00, 0x00])).to.throw( - /(read outside the boundary|insufficient bytes)/i - ); - }); - - it('fast-fails before decoding child elements when remaining bytes are insufficient', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const fixed = new XDR.Array(FixedSizeChild, 5); - const reader = new XdrReader([0x00, 0x00, 0x00, 0x01]); - expect(() => fixed.read(reader)).to.throw( - new RegExp(`exceeds remaining ${reader.remainingBytes()} bytes`, 'i') - ); - expect(getCalls()).to.eql(0); - }); - - it('decodes on exact-fit byte length and reads each child exactly once', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const fixed = new XDR.Array(FixedSizeChild, 2); - const reader = new XdrReader([ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 - ]); - - expect(fixed.read(reader)).to.eql([1, 2]); - expect(getCalls()).to.eql(2); - }); - - it('zero-length array does not decode child elements', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const fixed = new XDR.Array(FixedSizeChild, 0); - const reader = new XdrReader([0x01, 0x02, 0x03, 0x04]); - - expect(fixed.read(reader)).to.eql([]); - expect(getCalls()).to.eql(0); - }); - - it('keeps reader position unchanged on Array fast-fail', function () { - const { FixedSizeChild } = createFixedSizeChild(); - - const fixed = new XDR.Array(FixedSizeChild, 3); - const reader = new XdrReader([0x00, 0x00]); - const before = reader.remainingBytes(); - - expect(() => fixed.read(reader)).to.throw( - new RegExp(`exceeds remaining ${reader.remainingBytes()} bytes`, 'i') - ); - expect(reader.remainingBytes()).to.eql(before); - }); - - function read(arr, bytes) { - let reader = new XdrReader(bytes); - return arr.read(reader); - } -}); - -describe('Array#read maxDepth', function () { - it('throws when depth exceeds maxDepth', function () { - const arrayType = new XDR.Array(XDR.Int, 2, 2); - const bytes = [0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a]; - const reader = new XdrReader(bytes); - - expect(() => arrayType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('succeeds when depth is within maxDepth', function () { - const arrayType = new XDR.Array(XDR.Int, 2, 5); - const bytes = [0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a]; - const reader = new XdrReader(bytes); - - const result = arrayType.read(reader, 4); - expect(result).to.eql([5, 10]); - }); - - it('uses default maxDepth of 200', function () { - const arrayType = new XDR.Array(XDR.Int, 2); - const bytes = [0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a]; - const reader = new XdrReader(bytes); - - expect(arrayType._maxDepth).to.equal(200); - expect(() => arrayType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('uses the root maxDepth for nested arrays', function () { - const innerArray = new XDR.Array(XDR.Int, 1, 2); - const outerArray = new XDR.Array(innerArray, 1, 5); - const bytes = [0x00, 0x00, 0x00, 0x2a]; - const reader = new XdrReader(bytes); - - const result = outerArray.read(reader, 2); - expect(result).to.eql([[42]]); - }); -}); - -describe('Array#write', function () { - let subject = many; - - it('encodes correctly', function () { - expect(write([1, 2])).to.eql([ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 - ]); - expect(write([3, 4])).to.eql([ - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 - ]); - }); - - it('throws a write error if the value is not the correct length', function () { - expect(() => write(null)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write([1])).to.throw(/write error/i); - expect(() => write([1, 2, 3])).to.throw(/write error/i); - }); - - it('throws a write error if a child element is of the wrong type', function () { - expect(() => write([1, null])).to.throw(/write error/i); - expect(() => write([1, undefined])).to.throw(/write error/i); - expect(() => write([1, 'hi'])).to.throw(/write error/i); - }); - - function write(value) { - let writer = new XdrWriter(8); - subject.write(value, writer); - return writer.toArray(); - } -}); - -describe('Array#isValid', function () { - let subject = many; - - it('returns true for an array of the correct size with the correct types', function () { - expect(subject.isValid([1, 2])).to.be.true; - }); - - it('returns false for arrays of the wrong size', function () { - expect(subject.isValid([])).to.be.false; - expect(subject.isValid([1])).to.be.false; - expect(subject.isValid([1, 2, 3])).to.be.false; - }); - - it('returns false if a child element is invalid for the child type', function () { - expect(subject.isValid([1, null])).to.be.false; - expect(subject.isValid([1, undefined])).to.be.false; - expect(subject.isValid([1, 'hello'])).to.be.false; - expect(subject.isValid([1, []])).to.be.false; - expect(subject.isValid([1, {}])).to.be.false; - }); -}); diff --git a/test/unit/bigint-encoder_test.js b/test/unit/bigint-encoder_test.js deleted file mode 100644 index e2f978d..0000000 --- a/test/unit/bigint-encoder_test.js +++ /dev/null @@ -1,396 +0,0 @@ -import { - encodeBigIntFromBits, - formatIntName, - sliceBigInt -} from '../../src/bigint-encoder'; - -describe('encodeBigIntWithPrecision', function () { - it(`encodes values correctly`, () => { - const testCases = [ - // i64 - [[0], 64, false, 0n], - [[-1], 64, false, -1n], - [['-15258'], 64, false, -15258n], - [[-0x8000000000000000n], 64, false, -0x8000000000000000n], - [[0x7fffffffffffffffn], 64, false, 0x7fffffffffffffffn], - [[1, -0x80000000n], 64, false, -0x7fffffffffffffffn], - [[-1, -1], 64, false, -1n], - [[-2, 0x7fffffffn], 64, false, 0x7ffffffffffffffen], - [[345, -345], 64, false, -0x158fffffea7n], - // u64 - [[0], 64, true, 0n], - [[1n], 64, true, 1n], - [[0xffffffffffffffffn], 64, true, 0xffffffffffffffffn], - [[0n, 0n], 64, true, 0n], - [[1, 0], 64, true, 1n], - [[-1, -1], 64, true, 0xffffffffffffffffn], - [[-2, -1], 64, true, 0xfffffffffffffffen], - // i128 - [[0], 128, false, 0n], - [[-1], 128, false, -1n], - [['-15258'], 128, false, -15258n], - [ - [-0x80000000000000000000000000000000n], - 128, - false, - -0x80000000000000000000000000000000n - ], - [ - [0x7fffffffffffffffffffffffffffffffn], - 128, - false, - 0x7fffffffffffffffffffffffffffffffn - ], - [[1, -2147483648], 128, false, -0x7fffffffffffffffffffffffn], - [[-1, -1], 128, false, -1n], - [ - [-1, 0x7fffffffffffffffn], - 128, - false, - 0x7fffffffffffffffffffffffffffffffn - ], - [ - [0xffffffffffffffffn, 0x7fffffffffffffffn], - 128, - false, - 0x7fffffffffffffffffffffffffffffffn - ], - [ - [0, -0x8000000000000000n], - 128, - false, - -0x80000000000000000000000000000000n - ], - [ - [1, -0x8000000000000000n], - 128, - false, - -0x7fffffffffffffffffffffffffffffffn - ], - [ - [1, 0, 0, -0x80000000n], - 128, - false, - -0x7fffffffffffffffffffffffffffffffn - ], - [[345, 345n, '345', 0x159], 128, false, 0x159000001590000015900000159n], - // u128 - [[0], 128, true, 0n], - [[1n], 128, true, 1n], - [ - [0xffffffffffffffffffffffffffffffffn], - 128, - true, - 0xffffffffffffffffffffffffffffffffn - ], - [[0n, 0n], 128, true, 0n], - [[1, 0], 128, true, 1n], - [[-1, -1], 128, true, 0xffffffffffffffffffffffffffffffffn], - [[-2, -1], 128, true, 0xfffffffffffffffffffffffffffffffen], - [ - [0x5cffffffffffffffn, 0x7fffffffffffffffn], - 128, - true, - 0x7fffffffffffffff5cffffffffffffffn - ], - [ - [1, 1, -1, -0x80000000n], - 128, - true, - 0x80000000ffffffff0000000100000001n - ], - [[345, 345n, '345', 0x159], 128, false, 0x159000001590000015900000159n], - // i256 - [[0], 256, false, 0n], - [[-1], 256, false, -1n], - [['-15258'], 256, false, -15258n], - [ - [-0x8000000000000000000000000000000000000000000000000000000000000000n], - 256, - false, - -0x8000000000000000000000000000000000000000000000000000000000000000n - ], - [ - [0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn], - 256, - false, - 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [1, -2147483648], - 256, - false, - -0x7fffffffffffffffffffffffffffffffffffffffn - ], - [[-1, -1], 256, false, -1n], - [ - [-1, 0x7fffffffffffffffn], - 256, - false, - 0x7fffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [ - 0xffffffffffffffffffffffffffffffffn, - 0x7fffffffffffffffffffffffffffffffn - ], - 256, - false, - 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [0, -0x80000000000000000000000000000000n], - 256, - false, - -0x8000000000000000000000000000000000000000000000000000000000000000n - ], - [ - [1, -0x80000000000000000000000000000000n], - 256, - false, - -0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [1, 0, 0, -0x800000000000000n], - 256, - false, - -0x7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [345, 345n, '345', -0x159], - 256, - false, - -0x158fffffffffffffea6fffffffffffffea6fffffffffffffea7n - ], - [ - [1, 2, 3, 4, 5, 6, 7, -8], - 256, - false, - -0x7fffffff8fffffff9fffffffafffffffbfffffffcfffffffdffffffffn - ], - [ - [1, -2, 3, -4, 5, -6, 7, -8], - 256, - false, - -0x7fffffff800000005fffffffa00000003fffffffc00000001ffffffffn - ], - // u256 - [[0], 256, true, 0n], - [[1n], 256, true, 1n], - [ - [0xffffffffffffffffffffffffffffffffn], - 256, - true, - 0xffffffffffffffffffffffffffffffffn - ], - [[0n, 0n], 256, true, 0n], - [[1, 0], 256, true, 1n], - [ - [-1, -1], - 256, - true, - 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn - ], - [ - [-2, -1], - 256, - true, - 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffen - ], - [ - [ - 0x5cffffffffffffffffffffffffffffffn, - 0x7fffffffffffffffffffffffffffffffn - ], - 256, - true, - 0x7fffffffffffffffffffffffffffffff5cffffffffffffffffffffffffffffffn - ], - [ - [1, 1, -1, -0x80000000n], - 256, - true, - 0xffffffff80000000ffffffffffffffff00000000000000010000000000000001n - ], - [ - [ - 1558245471070191615n, - 1558245471070191615n, - '1558245471070191615', - 0x159fffffffffffffn - ], - 256, - false, - 0x159fffffffffffff159fffffffffffff159fffffffffffff159fffffffffffffn - ], - [ - [1, 2, 3, 4, 5, 6, 7, 8], - 256, - false, - 0x0000000800000007000000060000000500000004000000030000000200000001n - ] - ]; - - for (let [args, bits, unsigned, expected] of testCases) { - try { - const actual = encodeBigIntFromBits(args, bits, unsigned); - expect(actual).to.eq( - expected, - `bigint values for ${formatIntName( - bits, - unsigned - )} out of range: [${args.join()}]` - ); - } catch (e) { - e.message = `Encoding [${args.join()}] => ${formatIntName( - bits, - unsigned - )} BigInt failed with error: ${e.message}`; - throw e; - } - } - }); - - it(`throws on slice overflow and underflow`, () => { - const invalidCases = [ - { - parts: [0n, 0x100000000n], - bits: 64, - unsigned: true, - reason: 'u32 slice overflow (+2^32)' - }, - { - parts: [0n, -0x80000001n], - bits: 64, - unsigned: false, - reason: 'i32 slice underflow (< -2^31)' - }, - { - parts: [0n, 0n, 0n, 0x10000000000000000n], - bits: 256, - unsigned: true, - reason: 'u64 slice overflow (+2^64)' - }, - { - parts: [0n, 0n, 0n, -0x8000000000000001n], - bits: 256, - unsigned: false, - reason: 'i64 slice underflow (< -2^63)' - } - ]; - - for (const { parts, bits, unsigned, reason } of invalidCases) { - expect( - () => encodeBigIntFromBits(parts, bits, unsigned), - `${formatIntName(bits, unsigned)} should throw for ${reason}` - ).to.throw(RangeError, /does not fit/i); - } - }); - - it(`accepts exact slice boundary values`, () => { - const validCases = [ - { - parts: [0n, 0xffffffffn], - bits: 64, - unsigned: true, - expected: 0xffffffff00000000n, - reason: 'u32 upper boundary (2^32 - 1)' - }, - { - parts: [0n, -0x80000000n], - bits: 64, - unsigned: false, - expected: -0x8000000000000000n, - reason: 'i32 lower boundary (-2^31)' - }, - { - parts: [0n, 0n, 0n, 0xffffffffffffffffn], - bits: 256, - unsigned: true, - expected: - 0xffffffffffffffff000000000000000000000000000000000000000000000000n, - reason: 'u64 upper boundary (2^64 - 1)' - }, - { - parts: [0n, 0n, 0n, -0x8000000000000000n], - bits: 256, - unsigned: false, - expected: - -0x8000000000000000000000000000000000000000000000000000000000000000n, - reason: 'i64 lower boundary (-2^63)' - } - ]; - - for (const { parts, bits, unsigned, expected, reason } of validCases) { - expect( - encodeBigIntFromBits(parts, bits, unsigned), - `${formatIntName(bits, unsigned)} should accept ${reason}` - ).to.eq(expected); - } - }); -}); - -describe('sliceBigInt', function () { - it(`slices values correctly`, () => { - const testCases = [ - [0n, 64, 64, [0n]], - [0n, 256, 256, [0n]], - [-1n, 64, 32, [-1n, -1n]], - [0xfffffffffffffffen, 64, 32, [-2n, -1n]], - [ - 0x7fffffffffffffff5cffffffffffffffn, - 128, - 64, - [0x5cffffffffffffffn, 0x7fffffffffffffffn] - ], - [ - 0x80000000ffffffff0000000100000001n, - 128, - 32, - [1n, 1n, -1n, -0x80000000n] - ], - [ - -0x158fffffffffffffea6fffffffffffffea6fffffffffffffea7n, - 256, - 64, - [345n, 345n, 345n, -345n] - ], - [ - 0x0000000800000007000000060000000500000004000000030000000200000001n, - 256, - 32, - [1n, 2n, 3n, 4n, 5n, 6n, 7n, 8n] - ], - [ - -0x7fffffff8fffffff9fffffffafffffffbfffffffcfffffffdffffffffn, - 256, - 32, - [1n, 2n, 3n, 4n, 5n, 6n, 7n, -8n] - ], - [ - -0x7fffffff800000005fffffffa00000003fffffffc00000001ffffffffn, - 256, - 32, - [1n, -2n, 3n, -4n, 5n, -6n, 7n, -8n] - ] - ]; - for (let [value, size, sliceSize, expected] of testCases) { - try { - const actual = sliceBigInt(value, size, sliceSize); - expect(actual).to.eql( - expected, - `Invalid ${formatIntName( - size, - false - )} / ${sliceSize} slicing result for ${value}` - ); - } catch (e) { - e.message = `Slicing ${value} for ${formatIntName( - size, - false - )} / ${sliceSize} failed with error: ${e.message}`; - throw e; - } - } - }); -}); diff --git a/test/unit/bool.test.ts b/test/unit/bool.test.ts new file mode 100644 index 0000000..c0c5dad --- /dev/null +++ b/test/unit/bool.test.ts @@ -0,0 +1,49 @@ +import { describe, it, expect } from 'vitest'; +import { bool } from '../../src/index.js'; +import { bytes, toArray, encodeInvalid } from './_helpers.js'; + +const schema = bool(); + +describe('bool', () => { + describe('decode', () => { + it('decodes 0 as false and 1 as true', () => { + expect(schema.decode(bytes([0, 0, 0, 0]))).toBe(false); + expect(schema.decode(bytes([0, 0, 0, 1]))).toBe(true); + }); + + it('throws on an invalid discriminant', () => { + expect(() => schema.decode(bytes([0, 0, 0, 2]))).toThrow(/invalid bool/i); + expect(() => schema.decode(bytes([255, 255, 255, 255]))).toThrow( + /invalid bool/i + ); + }); + }); + + describe('encode', () => { + it('encodes booleans', () => { + expect(toArray(schema.encode(false))).toEqual([0, 0, 0, 0]); + expect(toArray(schema.encode(true))).toEqual([0, 0, 0, 1]); + }); + + it('throws on non-boolean input', () => { + expect(() => encodeInvalid(schema, 1)).toThrow(/expected boolean/i); + expect(() => encodeInvalid(schema, null)).toThrow(/expected boolean/i); + }); + }); + + describe('validate', () => { + it('accepts booleans', () => { + expect(schema.validate(true)).toBe(true); + expect(schema.validate(false)).toBe(true); + }); + + it('rejects non-booleans', () => { + expect(schema.validate(0)).toBe(false); + expect(schema.validate('0')).toBe(false); + expect(schema.validate([true])).toBe(false); + expect(schema.validate(null)).toBe(false); + expect(schema.validate({})).toBe(false); + expect(schema.validate(undefined)).toBe(false); + }); + }); +}); diff --git a/test/unit/bool_test.js b/test/unit/bool_test.js deleted file mode 100644 index 237c448..0000000 --- a/test/unit/bool_test.js +++ /dev/null @@ -1,47 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; -let Bool = XDR.Bool; - -describe('Bool.read', function () { - it('decodes correctly', function () { - expect(read([0, 0, 0, 0])).to.eql(false); - expect(read([0, 0, 0, 1])).to.eql(true); - - expect(() => read([0, 0, 0, 2])).to.throw(/read error/i); - expect(() => read([255, 255, 255, 255])).to.throw(/read error/i); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Bool.read(io); - } -}); - -describe('Bool.write', function () { - it('encodes correctly', function () { - expect(write(false)).to.eql([0, 0, 0, 0]); - expect(write(true)).to.eql([0, 0, 0, 1]); - }); - - function write(value) { - let io = new XdrWriter(8); - Bool.write(value, io); - return io.toArray(); - } -}); - -describe('Bool.isValid', function () { - it('returns true for booleans', function () { - expect(Bool.isValid(true)).to.be.true; - expect(Bool.isValid(false)).to.be.true; - }); - - it('returns false for non booleans', function () { - expect(Bool.isValid(0)).to.be.false; - expect(Bool.isValid('0')).to.be.false; - expect(Bool.isValid([true])).to.be.false; - expect(Bool.isValid(null)).to.be.false; - expect(Bool.isValid({})).to.be.false; - expect(Bool.isValid(undefined)).to.be.false; - }); -}); diff --git a/test/unit/define_test.js b/test/unit/define_test.js deleted file mode 100644 index 504b471..0000000 --- a/test/unit/define_test.js +++ /dev/null @@ -1,175 +0,0 @@ -import * as XDR from '../../src'; - -describe('XDR.config', function () { - beforeEach(function () { - this.types = XDR.config(); // get the xdr object root - for (const toDelete of Object.keys(this.types)) { - delete this.types[toDelete]; - } - }); - - it('can define objects that have no dependency', function () { - XDR.config((xdr) => { - xdr.enum('Color', { - red: 0, - green: 1, - blue: 2 - }); - - xdr.enum('ResultType', { - ok: 0, - error: 1 - }); - }, this.types); - - expect(this.types.Color).to.exist; - expect(this.types.ResultType).to.exist; - }); - - it('can define objects with the same name from different contexts', function () { - XDR.config((xdr) => { - xdr.enum('Color', { - red: 0, - green: 1, - blue: 2 - }); - }); - - XDR.config((xdr) => { - xdr.enum('Color', { - red: 0, - green: 1, - blue: 2 - }); - }); - }); - - it('can define objects that have simple dependencies', function () { - XDR.config((xdr) => { - xdr.union('Result', { - switchOn: xdr.lookup('ResultType'), - switches: [ - ['ok', XDR.Void], - ['error', 'message'] - ], - defaultArm: XDR.Void, - arms: { - message: new XDR.String(100) - } - }); - - xdr.enum('ResultType', { - ok: 0, - error: 1 - }); - }, this.types); - - expect(this.types.Result).to.exist; - expect(this.types.ResultType).to.exist; - - let result = this.types.Result.ok(); - expect(result.switch()).to.eql(this.types.ResultType.ok()); - - result = this.types.Result.error('It broke!'); - expect(result.switch()).to.eql(this.types.ResultType.error()); - expect(result.message()).to.eql('It broke!'); - }); - - it('can define structs', function () { - XDR.config((xdr) => { - xdr.struct('Color', [ - ['red', xdr.int()], - ['green', xdr.int()], - ['blue', xdr.int()] - ]); - }, this.types); - - expect(this.types.Color).to.exist; - - let result = new this.types.Color({ - red: 0, - green: 1, - blue: 2 - }); - expect(result.red()).to.eql(0); - expect(result.green()).to.eql(1); - expect(result.blue()).to.eql(2); - }); - - it('can define typedefs', function () { - let xdr = XDR.config((xdr) => { - xdr.typedef('Uint256', xdr.opaque(32)); - }); - expect(xdr.Uint256).to.be.instanceof(XDR.Opaque); - }); - - it('can define consts', function () { - let xdr = XDR.config((xdr) => { - xdr.typedef('MAX_SIZE', 300); - }); - expect(xdr.MAX_SIZE).to.eql(300); - }); - - it('can define arrays', function () { - let xdr = XDR.config((xdr) => { - xdr.typedef('ArrayOfInts', xdr.array(xdr.int(), 3)); - xdr.struct('MyStruct', [['red', xdr.int()]]); - xdr.typedef('ArrayOfEmpty', xdr.array(xdr.lookup('MyStruct'), 5)); - }); - - expect(xdr.ArrayOfInts).to.be.instanceof(XDR.Array); - expect(xdr.ArrayOfInts._childType).to.eql(XDR.Int); - expect(xdr.ArrayOfInts._length).to.eql(3); - - expect(xdr.ArrayOfEmpty).to.be.instanceof(XDR.Array); - expect(xdr.ArrayOfEmpty._childType).to.eql(xdr.MyStruct); - expect(xdr.ArrayOfEmpty._length).to.eql(5); - }); - - it('can define vararrays', function () { - let xdr = XDR.config((xdr) => { - xdr.typedef('ArrayOfInts', xdr.varArray(xdr.int(), 3)); - }); - - expect(xdr.ArrayOfInts).to.be.instanceof(XDR.VarArray); - expect(xdr.ArrayOfInts._childType).to.eql(XDR.Int); - expect(xdr.ArrayOfInts._maxLength).to.eql(3); - }); - - it('can define options', function () { - let xdr = XDR.config((xdr) => { - xdr.typedef('OptionalInt', xdr.option(xdr.int())); - }); - - expect(xdr.OptionalInt).to.be.instanceof(XDR.Option); - expect(xdr.OptionalInt._childType).to.eql(XDR.Int); - }); - - it('can use sizes defined as an xdr const', function () { - let xdr = XDR.config((xdr) => { - xdr.const('SIZE', 5); - xdr.typedef('MyArray', xdr.array(xdr.int(), xdr.lookup('SIZE'))); - xdr.typedef('MyVarArray', xdr.varArray(xdr.int(), xdr.lookup('SIZE'))); - xdr.typedef('MyString', xdr.string(xdr.lookup('SIZE'))); - xdr.typedef('MyOpaque', xdr.opaque(xdr.lookup('SIZE'))); - xdr.typedef('MyVarOpaque', xdr.varOpaque(xdr.lookup('SIZE'))); - }); - - expect(xdr.MyArray).to.be.instanceof(XDR.Array); - expect(xdr.MyArray._childType).to.eql(XDR.Int); - expect(xdr.MyArray._length).to.eql(5); - - expect(xdr.MyVarArray).to.be.instanceof(XDR.VarArray); - expect(xdr.MyVarArray._childType).to.eql(XDR.Int); - expect(xdr.MyVarArray._maxLength).to.eql(5); - - expect(xdr.MyString).to.be.instanceof(XDR.String); - expect(xdr.MyString._maxLength).to.eql(5); - - expect(xdr.MyOpaque).to.be.instanceof(XDR.Opaque); - expect(xdr.MyOpaque._length).to.eql(5); - - expect(xdr.MyVarOpaque).to.be.instanceof(XDR.VarOpaque); - expect(xdr.MyVarOpaque._maxLength).to.eql(5); - }); -}); diff --git a/test/unit/double.test.ts b/test/unit/double.test.ts new file mode 100644 index 0000000..212e526 --- /dev/null +++ b/test/unit/double.test.ts @@ -0,0 +1,35 @@ +import { describe, it, expect } from 'vitest'; +import { double } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = double(); + +describe('double', () => { + describe('decode', () => { + it('decodes 64-bit IEEE-754 values', () => { + expect(schema.decode(bytes([0, 0, 0, 0, 0, 0, 0, 0]))).toBe(0); + expect(schema.decode(bytes([63, 240, 0, 0, 0, 0, 0, 0]))).toBe(1); + expect(schema.decode(bytes([192, 0, 0, 0, 0, 0, 0, 0]))).toBe(-2); + }); + }); + + describe('encode', () => { + it('encodes 64-bit IEEE-754 values', () => { + expect(toArray(schema.encode(0))).toEqual([0, 0, 0, 0, 0, 0, 0, 0]); + expect(toArray(schema.encode(1))).toEqual([63, 240, 0, 0, 0, 0, 0, 0]); + expect(toArray(schema.encode(-2))).toEqual([192, 0, 0, 0, 0, 0, 0, 0]); + }); + + it('throws on non-finite numbers', () => { + expect(() => schema.encode(NaN)).toThrow(/finite/i); + expect(() => schema.encode(-Infinity)).toThrow(/finite/i); + expect(() => encodeInvalid(schema, '1')).toThrow(/finite/i); + }); + }); + + it('round-trips representable values', () => { + for (const value of [0, 1, -1, 0.1, -2, 3.141592653589793, 1e308]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); +}); diff --git a/test/unit/double_test.js b/test/unit/double_test.js deleted file mode 100644 index 98ccc26..0000000 --- a/test/unit/double_test.js +++ /dev/null @@ -1,62 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; -let Double = XDR.Double; - -describe('Double.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql(0.0); - expect(read([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql(-0.0); - expect(read([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql(1.0); - expect(read([0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql(-1.0); - expect(read([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql(NaN); - expect(read([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])).to.eql(NaN); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Double.read(io); - } -}); - -describe('Double.write', function () { - it('encodes correctly', function () { - expect(write(0.0)).to.eql([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); - expect(write(-0.0)).to.eql([ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - expect(write(1.0)).to.eql([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); - expect(write(-1.0)).to.eql([ - 0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - }); - - function write(value) { - let io = new XdrWriter(8); - Double.write(value, io); - return io.toArray(); - } -}); - -describe('Double.isValid', function () { - it('returns true for numbers', function () { - expect(Double.isValid(0)).to.be.true; - expect(Double.isValid(-1)).to.be.true; - expect(Double.isValid(1.0)).to.be.true; - expect(Double.isValid(100000.0)).to.be.true; - expect(Double.isValid(NaN)).to.be.true; - expect(Double.isValid(Infinity)).to.be.true; - expect(Double.isValid(-Infinity)).to.be.true; - }); - - it('returns false for non numbers', function () { - expect(Double.isValid(true)).to.be.false; - expect(Double.isValid(false)).to.be.false; - expect(Double.isValid(null)).to.be.false; - expect(Double.isValid('0')).to.be.false; - expect(Double.isValid([])).to.be.false; - expect(Double.isValid([0])).to.be.false; - expect(Double.isValid('hello')).to.be.false; - expect(Double.isValid({ why: 'hello' })).to.be.false; - expect(Double.isValid(['how', 'do', 'you', 'do'])).to.be.false; - }); -}); diff --git a/test/unit/dynamic-buffer-resize_test.js b/test/unit/dynamic-buffer-resize_test.js deleted file mode 100644 index 3ad5b64..0000000 --- a/test/unit/dynamic-buffer-resize_test.js +++ /dev/null @@ -1,19 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -describe('Dynamic writer buffer resize', function () { - it('automatically resize buffer', function () { - const str = new XDR.String(32768); - let io = new XdrWriter(12); - str.write('7 bytes', io); - // expect buffer size to equal base size - expect(io._buffer.length).to.eql(12); - str.write('a'.repeat(32768), io); - // expect buffer growth up to 5 chunks - expect(io._buffer.length).to.eql(40960); - // increase by 1 more 8 KB chunk - str.write('a'.repeat(9000), io); - expect(io._buffer.length).to.eql(49152); - // check final buffer size - expect(io.toArray().length).to.eql(41788); - }); -}); diff --git a/test/unit/enum.test.ts b/test/unit/enum.test.ts new file mode 100644 index 0000000..3981ba7 --- /dev/null +++ b/test/unit/enum.test.ts @@ -0,0 +1,58 @@ +import { describe, it, expect } from 'vitest'; +import { enumType } from '../../src/index.js'; +import { bytes, toArray, encodeInvalid } from './_helpers.js'; + +const Color = enumType('Color', { red: 0, green: 1, blue: 2 }); + +describe('enum', () => { + it('exposes members as numeric properties and keeps its name', () => { + expect(Color.red).toBe(0); + expect(Color.green).toBe(1); + expect(Color.blue).toBe(2); + expect(Color.name).toBe('Color'); + }); + + describe('encode', () => { + it('writes the member value as an int32', () => { + expect(toArray(Color.encode(Color.red))).toEqual([0, 0, 0, 0]); + expect(toArray(Color.encode(Color.blue))).toEqual([0, 0, 0, 2]); + }); + + it('throws on an unknown value', () => { + expect(() => Color.encode(9)).toThrow(/unknown enum value/i); + expect(() => encodeInvalid(Color, 'red')).toThrow(/unknown enum value/i); + }); + }); + + describe('decode', () => { + it('reads a known member value', () => { + expect(Color.decode(bytes([0, 0, 0, 1]))).toBe(1); + }); + + it('throws on an unknown value', () => { + expect(() => Color.decode(bytes([0, 0, 0, 9]))).toThrow( + /unknown enum value/i + ); + }); + }); + + describe('validate', () => { + it('accepts known members and rejects everything else', () => { + expect(Color.validate(0)).toBe(true); + expect(Color.validate(2)).toBe(true); + expect(Color.validate(9)).toBe(false); + expect(Color.validate('red')).toBe(false); + }); + }); + + describe('construction', () => { + it('rejects duplicate values', () => { + expect(() => enumType('Dup', { a: 0, b: 0 })).toThrow(/duplicate/i); + }); + + it('rejects member names that collide with reserved properties', () => { + expect(() => enumType('Bad', { name: 0 })).toThrow(/reserved/i); + expect(() => enumType('Bad', { decode: 1 })).toThrow(/reserved/i); + }); + }); +}); diff --git a/test/unit/enum_test.js b/test/unit/enum_test.js deleted file mode 100644 index f9b59c7..0000000 --- a/test/unit/enum_test.js +++ /dev/null @@ -1,117 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { Enum } from '../../src/enum'; - -/* jshint -W030 */ - -let emptyContext = { definitions: {}, results: {} }; -let Color = XDR.Enum.create(emptyContext, 'Color', { - red: 0, - green: 1, - evenMoreGreen: 3 -}); - -describe('Enum.fromName', function () { - it('returns the member with the provided name', function () { - expect(Color.fromName('red')).to.eql(Color.red()); - expect(Color.fromName('green')).to.eql(Color.green()); - expect(Color.fromName('evenMoreGreen')).to.eql(Color.evenMoreGreen()); - }); - - it('throws an error if the name is not correct', function () { - expect(() => Color.fromName('obviouslyNotAColor')).to.throw( - /not a member/i - ); - }); -}); - -describe('Enum.fromValue', function () { - it('returns the member with the provided value', function () { - expect(Color.fromValue(0)).to.eql(Color.red()); - expect(Color.fromValue(1)).to.eql(Color.green()); - expect(Color.fromValue(3)).to.eql(Color.evenMoreGreen()); - }); - - it('throws an error if the value is not correct', function () { - expect(() => Color.fromValue(999)).to.throw(/not a value/i); - }); -}); - -describe('Enum.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.eql(Color.red()); - expect(read([0x00, 0x00, 0x00, 0x01])).to.eql(Color.green()); - expect(read([0x00, 0x00, 0x00, 0x03])).to.eql(Color.evenMoreGreen()); - }); - - it("throws read error when encoded value isn't defined on the enum", function () { - expect(() => read([0x00, 0x00, 0x00, 0x02])).to.throw(/read error/i); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Color.read(io); - } -}); - -describe('Enum.write', function () { - it('encodes correctly', function () { - expect(write(Color.red())).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write(Color.green())).to.eql([0x00, 0x00, 0x00, 0x01]); - expect(write(Color.evenMoreGreen())).to.eql([0x00, 0x00, 0x00, 0x03]); - - expect(Color.red().toXDR('hex')).to.eql('00000000'); - expect(Color.green().toXDR('hex')).to.eql('00000001'); - expect(Color.evenMoreGreen().toXDR('hex')).to.eql('00000003'); - }); - - it('throws a write error if the value is not the correct type', function () { - expect(() => write(null)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write({})).to.throw(/write error/i); - expect(() => write(1)).to.throw(/write error/i); - expect(() => write(true)).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(8); - Color.write(value, io); - return io.toArray(); - } -}); - -describe('Enum.isValid', function () { - it('returns true for members of the enum', function () { - expect(Color.isValid(Color.red())).to.be.true; - expect(Color.isValid(Color.green())).to.be.true; - expect(Color.isValid(Color.evenMoreGreen())).to.be.true; - }); - - it('works for "enum-like" objects', function () { - class FakeEnum extends Enum {} - FakeEnum.enumName = 'Color'; - - let r = new FakeEnum(); - expect(Color.isValid(r)).to.be.true; - - FakeEnum.enumName = 'NotColor'; - r = new FakeEnum(); - expect(Color.isValid(r)).to.be.false; - - // make sure you can't fool it - FakeEnum.enumName = undefined; - FakeEnum.unionName = 'Color'; - r = new FakeEnum(); - expect(Color.isValid(r)).to.be.false; - }); - - it('returns false for arrays of the wrong size', function () { - expect(Color.isValid(null)).to.be.false; - expect(Color.isValid(undefined)).to.be.false; - expect(Color.isValid([])).to.be.false; - expect(Color.isValid({})).to.be.false; - expect(Color.isValid(1)).to.be.false; - expect(Color.isValid(true)).to.be.false; - }); -}); diff --git a/test/unit/fixed-array.test.ts b/test/unit/fixed-array.test.ts new file mode 100644 index 0000000..37abe8d --- /dev/null +++ b/test/unit/fixed-array.test.ts @@ -0,0 +1,40 @@ +import { describe, it, expect } from 'vitest'; +import { fixedArray, int32 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = fixedArray(int32(), 3); + +describe('fixedArray (fixed-length)', () => { + describe('encode', () => { + it('writes each element with no length prefix', () => { + expect(toArray(schema.encode([1, 2, 3]))).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 + ]); + }); + + it('throws on a length mismatch', () => { + expect(() => schema.encode([1, 2])).toThrow( + /expected array length 3, got 2/i + ); + expect(() => schema.encode([1, 2, 3, 4])).toThrow( + /expected array length 3, got 4/i + ); + }); + + it('throws for non-array input', () => { + expect(() => encodeInvalid(schema, null)).toThrow(/expected array/i); + }); + }); + + describe('decode', () => { + it('reads exactly length elements', () => { + expect( + schema.decode(bytes([0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6])) + ).toEqual([4, 5, 6]); + }); + }); + + it('round-trips element values', () => { + expect(roundTrip(schema, [10, 20, 30])).toEqual([10, 20, 30]); + }); +}); diff --git a/test/unit/float.test.ts b/test/unit/float.test.ts new file mode 100644 index 0000000..9dd9c47 --- /dev/null +++ b/test/unit/float.test.ts @@ -0,0 +1,35 @@ +import { describe, it, expect } from 'vitest'; +import { float } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = float(); + +describe('float', () => { + describe('decode', () => { + it('decodes 32-bit IEEE-754 values', () => { + expect(schema.decode(bytes([0, 0, 0, 0]))).toBe(0); + expect(schema.decode(bytes([63, 128, 0, 0]))).toBe(1); + expect(schema.decode(bytes([192, 0, 0, 0]))).toBe(-2); + }); + }); + + describe('encode', () => { + it('encodes 32-bit IEEE-754 values', () => { + expect(toArray(schema.encode(0))).toEqual([0, 0, 0, 0]); + expect(toArray(schema.encode(1))).toEqual([63, 128, 0, 0]); + expect(toArray(schema.encode(-2))).toEqual([192, 0, 0, 0]); + }); + + it('throws on non-finite numbers', () => { + expect(() => schema.encode(NaN)).toThrow(/finite/i); + expect(() => schema.encode(Infinity)).toThrow(/finite/i); + expect(() => encodeInvalid(schema, '1')).toThrow(/finite/i); + }); + }); + + it('round-trips representable values', () => { + for (const value of [0, 1, -1, 0.5, -2, 1234.5]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); +}); diff --git a/test/unit/float_test.js b/test/unit/float_test.js deleted file mode 100644 index be790dd..0000000 --- a/test/unit/float_test.js +++ /dev/null @@ -1,58 +0,0 @@ -let Float = XDR.Float; -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -describe('Float.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.eql(0.0); - expect(read([0x80, 0x00, 0x00, 0x00])).to.eql(-0.0); - expect(read([0x3f, 0x80, 0x00, 0x00])).to.eql(1.0); - expect(read([0xbf, 0x80, 0x00, 0x00])).to.eql(-1.0); - expect(read([0x7f, 0xc0, 0x00, 0x00])).to.eql(NaN); - expect(read([0x7f, 0xf8, 0x00, 0x00])).to.eql(NaN); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Float.read(io); - } -}); - -describe('Float.write', function () { - it('encodes correctly', function () { - expect(write(0.0)).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write(-0.0)).to.eql([0x80, 0x00, 0x00, 0x00]); - expect(write(1.0)).to.eql([0x3f, 0x80, 0x00, 0x00]); - expect(write(-1.0)).to.eql([0xbf, 0x80, 0x00, 0x00]); - }); - - function write(value) { - let io = new XdrWriter(8); - Float.write(value, io); - return io.toArray(); - } -}); - -describe('Float.isValid', function () { - it('returns true for numbers', function () { - expect(Float.isValid(0)).to.be.true; - expect(Float.isValid(-1)).to.be.true; - expect(Float.isValid(1.0)).to.be.true; - expect(Float.isValid(100000.0)).to.be.true; - expect(Float.isValid(NaN)).to.be.true; - expect(Float.isValid(Infinity)).to.be.true; - expect(Float.isValid(-Infinity)).to.be.true; - }); - - it('returns false for non numbers', function () { - expect(Float.isValid(true)).to.be.false; - expect(Float.isValid(false)).to.be.false; - expect(Float.isValid(null)).to.be.false; - expect(Float.isValid('0')).to.be.false; - expect(Float.isValid([])).to.be.false; - expect(Float.isValid([0])).to.be.false; - expect(Float.isValid('hello')).to.be.false; - expect(Float.isValid({ why: 'hello' })).to.be.false; - expect(Float.isValid(['how', 'do', 'you', 'do'])).to.be.false; - }); -}); diff --git a/test/unit/hyper_test.js b/test/unit/hyper_test.js deleted file mode 100644 index 587c665..0000000 --- a/test/unit/hyper_test.js +++ /dev/null @@ -1,108 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; -let Hyper = XDR.Hyper; - -describe('Hyper.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql( - Hyper.fromString('0') - ); - expect(read([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])).to.eql( - Hyper.fromString('1') - ); - expect(read([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])).to.eql( - Hyper.fromString('-1') - ); - expect(read([0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])).to.eql( - new Hyper(Hyper.MAX_VALUE) - ); - expect(read([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql( - new Hyper(Hyper.MIN_VALUE) - ); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Hyper.read(io); - } -}); - -describe('Hyper.write', function () { - it('encodes correctly', function () { - expect(write(Hyper.fromString('0'))).to.eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - expect(write(Hyper.fromString('1'))).to.eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - ]); - expect(write(Hyper.fromString('-1'))).to.eql([ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - ]); - expect(write(Hyper.MAX_VALUE)).to.eql([ - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - ]); - expect(write(Hyper.MIN_VALUE)).to.eql([ - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - }); - - function write(value) { - let io = new XdrWriter(8); - Hyper.write(value, io); - return io.toArray(); - } -}); - -describe('Hyper.isValid', function () { - it('returns true for Hyper instances', function () { - expect(Hyper.isValid(Hyper.MIN_VALUE)).to.be.true; - expect(Hyper.isValid(Hyper.MAX_VALUE)).to.be.true; - expect(Hyper.isValid(Hyper.fromString('0'))).to.be.true; - expect(Hyper.isValid(Hyper.fromString('-1'))).to.be.true; - }); - - it('returns false for non Hypers', function () { - expect(Hyper.isValid(null)).to.be.false; - expect(Hyper.isValid(undefined)).to.be.false; - expect(Hyper.isValid([])).to.be.false; - expect(Hyper.isValid({})).to.be.false; - expect(Hyper.isValid(1)).to.be.false; - expect(Hyper.isValid(true)).to.be.false; - }); -}); - -describe('Hyper.fromString', function () { - it('works for positive numbers', function () { - expect(Hyper.fromString('1059').toString()).to.eql('1059'); - }); - - it('works for negative numbers', function () { - expect(Hyper.fromString('-1059').toString()).to.eql('-1059'); - }); - - it('fails when providing a string with a decimal place', function () { - expect(() => Hyper.fromString('105946095601.5')).to.throw(/bigint/); - }); -}); - -describe('Hyper overflow/underflow', function () { - it('throws when constructing with a value exceeding i64 max', function () { - const tooBig = 2n ** 63n; // one above MAX_VALUE - expect(() => new Hyper(tooBig)).to.throw(/out of range|does not fit/i); - }); - - it('throws when constructing with a value below i64 min', function () { - const tooSmall = -(2n ** 63n) - 1n; // one below MIN_VALUE - expect(() => new Hyper(tooSmall)).to.throw(/out of range|does not fit/i); - }); - - it('throws for a 300-bit bigint', function () { - const huge = 2n ** 300n; - expect(() => new Hyper(huge)).to.throw(/out of range|does not fit/i); - }); - - it('accepts exact boundary values without throwing', function () { - expect(() => new Hyper(Hyper.MAX_VALUE)).to.not.throw(); - expect(() => new Hyper(Hyper.MIN_VALUE)).to.not.throw(); - }); -}); diff --git a/test/unit/int32.test.ts b/test/unit/int32.test.ts new file mode 100644 index 0000000..86abab6 --- /dev/null +++ b/test/unit/int32.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from 'vitest'; +import { int32 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = int32(); + +describe('int32', () => { + describe('decode', () => { + it('decodes big-endian signed integers', () => { + expect(schema.decode(bytes([0, 0, 0, 0]))).toBe(0); + expect(schema.decode(bytes([0, 0, 0, 5]))).toBe(5); + expect(schema.decode(bytes([255, 255, 255, 255]))).toBe(-1); + expect(schema.decode(bytes([127, 255, 255, 255]))).toBe(2147483647); + expect(schema.decode(bytes([128, 0, 0, 0]))).toBe(-2147483648); + }); + }); + + describe('encode', () => { + it('encodes big-endian signed integers', () => { + expect(toArray(schema.encode(0))).toEqual([0, 0, 0, 0]); + expect(toArray(schema.encode(5))).toEqual([0, 0, 0, 5]); + expect(toArray(schema.encode(-1))).toEqual([255, 255, 255, 255]); + expect(toArray(schema.encode(2147483647))).toEqual([127, 255, 255, 255]); + expect(toArray(schema.encode(-2147483648))).toEqual([128, 0, 0, 0]); + }); + + it('throws when out of range', () => { + expect(() => schema.encode(2147483648)).toThrow(/range/i); + expect(() => schema.encode(-2147483649)).toThrow(/range/i); + }); + + it('throws for non-integers', () => { + expect(() => schema.encode(1.5)).toThrow(/range/i); + expect(() => encodeInvalid(schema, '1')).toThrow(/range/i); + }); + }); + + it('round-trips boundary values', () => { + for (const value of [0, 1, -1, 2147483647, -2147483648]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); + + describe('validate', () => { + it('accepts in-range integers and rejects everything else', () => { + expect(schema.validate(0)).toBe(true); + expect(schema.validate(-2147483648)).toBe(true); + expect(schema.validate(2147483648)).toBe(false); + expect(schema.validate(1.5)).toBe(false); + expect(schema.validate('1')).toBe(false); + }); + }); +}); diff --git a/test/unit/int64.test.ts b/test/unit/int64.test.ts new file mode 100644 index 0000000..2840cb8 --- /dev/null +++ b/test/unit/int64.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect } from 'vitest'; +import { int64 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = int64(); +const MAX = (1n << 63n) - 1n; +const MIN = -(1n << 63n); + +describe('int64', () => { + describe('decode', () => { + it('decodes big-endian signed bigints', () => { + expect(schema.decode(bytes([0, 0, 0, 0, 0, 0, 0, 0]))).toBe(0n); + expect(schema.decode(bytes([0, 0, 0, 0, 0, 0, 0, 1]))).toBe(1n); + expect( + schema.decode(bytes([255, 255, 255, 255, 255, 255, 255, 255])) + ).toBe(-1n); + expect( + schema.decode(bytes([127, 255, 255, 255, 255, 255, 255, 255])) + ).toBe(MAX); + expect(schema.decode(bytes([128, 0, 0, 0, 0, 0, 0, 0]))).toBe(MIN); + }); + }); + + describe('encode', () => { + it('encodes big-endian signed bigints', () => { + expect(toArray(schema.encode(1n))).toEqual([0, 0, 0, 0, 0, 0, 0, 1]); + expect(toArray(schema.encode(-1n))).toEqual([ + 255, 255, 255, 255, 255, 255, 255, 255 + ]); + expect(toArray(schema.encode(MAX))).toEqual([ + 127, 255, 255, 255, 255, 255, 255, 255 + ]); + expect(toArray(schema.encode(MIN))).toEqual([128, 0, 0, 0, 0, 0, 0, 0]); + }); + + it('throws when out of range', () => { + expect(() => schema.encode(MAX + 1n)).toThrow(/range/i); + expect(() => schema.encode(MIN - 1n)).toThrow(/range/i); + }); + + it('throws for non-bigint input', () => { + expect(() => encodeInvalid(schema, 5)).toThrow(/range/i); + expect(() => encodeInvalid(schema, '5')).toThrow(/range/i); + }); + }); + + it('round-trips boundary values', () => { + for (const value of [0n, 1n, -1n, MAX, MIN]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); +}); diff --git a/test/unit/int_test.js b/test/unit/int_test.js deleted file mode 100644 index 1222604..0000000 --- a/test/unit/int_test.js +++ /dev/null @@ -1,78 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; -let Int = XDR.Int; - -describe('Int.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.eql(0); - expect(read([0x00, 0x00, 0x00, 0x01])).to.eql(1); - expect(read([0xff, 0xff, 0xff, 0xff])).to.eql(-1); - expect(read([0x7f, 0xff, 0xff, 0xff])).to.eql(Math.pow(2, 31) - 1); - expect(read([0x80, 0x00, 0x00, 0x00])).to.eql(-Math.pow(2, 31)); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Int.read(io); - } -}); - -describe('Int.write', function () { - it('encodes correctly', function () { - expect(write(0)).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write(1)).to.eql([0x00, 0x00, 0x00, 0x01]); - expect(write(-1)).to.eql([0xff, 0xff, 0xff, 0xff]); - expect(write(Math.pow(2, 31) - 1)).to.eql([0x7f, 0xff, 0xff, 0xff]); - expect(write(-Math.pow(2, 31))).to.eql([0x80, 0x00, 0x00, 0x00]); - }); - - it('throws a write error if the value is not an integral number', function () { - expect(() => write(true)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write({})).to.throw(/write error/i); - expect(() => write(1.1)).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(8); - Int.write(value, io); - return io.toArray(); - } -}); - -describe('Int.isValid', function () { - it('returns true for number in a 32-bit range', function () { - expect(Int.isValid(0)).to.be.true; - expect(Int.isValid(-1)).to.be.true; - expect(Int.isValid(1.0)).to.be.true; - expect(Int.isValid(Math.pow(2, 31) - 1)).to.be.true; - expect(Int.isValid(-Math.pow(2, 31))).to.be.true; - }); - - it('returns false for numbers outside a 32-bit range', function () { - expect(Int.isValid(Math.pow(2, 31))).to.be.false; - expect(Int.isValid(-(Math.pow(2, 31) + 1))).to.be.false; - expect(Int.isValid(1000000000000)).to.be.false; - }); - - it('returns false for non numbers', function () { - expect(Int.isValid(true)).to.be.false; - expect(Int.isValid(false)).to.be.false; - expect(Int.isValid(null)).to.be.false; - expect(Int.isValid('0')).to.be.false; - expect(Int.isValid([])).to.be.false; - expect(Int.isValid([0])).to.be.false; - expect(Int.isValid('hello')).to.be.false; - expect(Int.isValid({ why: 'hello' })).to.be.false; - expect(Int.isValid(['how', 'do', 'you', 'do'])).to.be.false; - expect(Int.isValid(NaN)).to.be.false; - }); - - it('returns false for non-integral values', function () { - expect(Int.isValid(1.1)).to.be.false; - expect(Int.isValid(0.1)).to.be.false; - expect(Int.isValid(-0.1)).to.be.false; - expect(Int.isValid(-1.1)).to.be.false; - }); -}); diff --git a/test/unit/large-int-128_test.js b/test/unit/large-int-128_test.js deleted file mode 100644 index cc4af9e..0000000 --- a/test/unit/large-int-128_test.js +++ /dev/null @@ -1,216 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { LargeInt } from '../../src/large-int'; - -// -- Inline 128-bit subclasses for testing the >64 bit LargeInt paths -- - -class Int128 extends LargeInt { - constructor(...args) { - super(args); - } - get size() { - return 128; - } - get unsigned() { - return false; - } -} -Int128.defineIntBoundaries(); - -class UnsignedInt128 extends LargeInt { - constructor(...args) { - super(args); - } - get size() { - return 128; - } - get unsigned() { - return true; - } -} -UnsignedInt128.defineIntBoundaries(); - -// ---------- Construction ---------- - -describe('Int128 construction', function () { - it('constructs zero', function () { - const val = new Int128(0n); - expect(val.toBigInt()).to.eql(0n); - }); - - it('constructs positive values', function () { - const val = new Int128(123456789012345678901234n); - expect(val.toBigInt()).to.eql(123456789012345678901234n); - }); - - it('constructs negative values', function () { - const val = new Int128(-42n); - expect(val.toBigInt()).to.eql(-42n); - }); - - it('constructs from exact boundary values', function () { - expect(() => new Int128(Int128.MAX_VALUE)).to.not.throw(); - expect(() => new Int128(Int128.MIN_VALUE)).to.not.throw(); - expect(new Int128(Int128.MAX_VALUE).toBigInt()).to.eql(Int128.MAX_VALUE); - expect(new Int128(Int128.MIN_VALUE).toBigInt()).to.eql(Int128.MIN_VALUE); - }); - - it('constructs from two 64-bit chunks', function () { - // low=1, high=2 => 2 * 2^64 + 1 - const val = new Int128(1n, 2n); - expect(val.toBigInt()).to.eql(2n * 2n ** 64n + 1n); - }); - - it('constructs from four 32-bit chunks', function () { - const val = new Int128(1n, 2n, 3n, 4n); - expect(val.toBigInt()).to.eql((4n << 96n) | (3n << 64n) | (2n << 32n) | 1n); - }); -}); - -describe('UnsignedInt128 construction', function () { - it('constructs zero', function () { - const val = new UnsignedInt128(0n); - expect(val.toBigInt()).to.eql(0n); - }); - - it('constructs max value', function () { - const val = new UnsignedInt128(UnsignedInt128.MAX_VALUE); - expect(val.toBigInt()).to.eql(2n ** 128n - 1n); - }); -}); - -// ---------- Overflow / Underflow ---------- - -describe('Int128 overflow/underflow', function () { - it('throws when value exceeds i128 max', function () { - const tooBig = 2n ** 127n; // one above MAX_VALUE - expect(() => new Int128(tooBig)).to.throw(/out of range|does not fit/i); - }); - - it('throws when value is below i128 min', function () { - const tooSmall = -(2n ** 127n) - 1n; - expect(() => new Int128(tooSmall)).to.throw(/out of range|does not fit/i); - }); - - it('throws for a 300-bit bigint', function () { - expect(() => new Int128(2n ** 300n)).to.throw(/out of range|does not fit/i); - }); -}); - -describe('UnsignedInt128 overflow/underflow', function () { - it('throws when value exceeds u128 max', function () { - const tooBig = 2n ** 128n; - expect(() => new UnsignedInt128(tooBig)).to.throw( - /out of range|does not fit/i - ); - }); - - it('throws for negative values', function () { - expect(() => new UnsignedInt128(-1n)).to.throw(/positive/i); - }); -}); - -// ---------- Read / Write round-trip ---------- - -describe('Int128 read/write', function () { - it('round-trips zero', function () { - const original = new Int128(0n); - const writer = new XdrWriter(16); - Int128.write(original, writer); - const reader = new XdrReader(writer.finalize()); - const decoded = Int128.read(reader); - expect(decoded.toBigInt()).to.eql(0n); - }); - - it('round-trips positive values', function () { - const value = 123456789012345678901234n; - const original = new Int128(value); - const writer = new XdrWriter(16); - Int128.write(original, writer); - const reader = new XdrReader(writer.finalize()); - const decoded = Int128.read(reader); - expect(decoded.toBigInt()).to.eql(value); - }); - - it('round-trips negative values', function () { - const value = -987654321098765432109876n; - const original = new Int128(value); - const writer = new XdrWriter(16); - Int128.write(original, writer); - const reader = new XdrReader(writer.finalize()); - const decoded = Int128.read(reader); - expect(decoded.toBigInt()).to.eql(value); - }); - - it('round-trips max value', function () { - const writer = new XdrWriter(16); - Int128.write(new Int128(Int128.MAX_VALUE), writer); - const reader = new XdrReader(writer.finalize()); - expect(Int128.read(reader).toBigInt()).to.eql(Int128.MAX_VALUE); - }); - - it('round-trips min value', function () { - const writer = new XdrWriter(16); - Int128.write(new Int128(Int128.MIN_VALUE), writer); - const reader = new XdrReader(writer.finalize()); - expect(Int128.read(reader).toBigInt()).to.eql(Int128.MIN_VALUE); - }); -}); - -describe('UnsignedInt128 read/write', function () { - it('round-trips zero', function () { - const writer = new XdrWriter(16); - UnsignedInt128.write(new UnsignedInt128(0n), writer); - const reader = new XdrReader(writer.finalize()); - expect(UnsignedInt128.read(reader).toBigInt()).to.eql(0n); - }); - - it('round-trips max value', function () { - const writer = new XdrWriter(16); - UnsignedInt128.write(new UnsignedInt128(UnsignedInt128.MAX_VALUE), writer); - const reader = new XdrReader(writer.finalize()); - expect(UnsignedInt128.read(reader).toBigInt()).to.eql( - UnsignedInt128.MAX_VALUE - ); - }); -}); - -// ---------- isValid ---------- - -describe('Int128.isValid', function () { - it('returns true for in-range bigint values', function () { - expect(Int128.isValid(0n)).to.be.true; - expect(Int128.isValid(-1n)).to.be.true; - expect(Int128.isValid(Int128.MAX_VALUE)).to.be.true; - expect(Int128.isValid(Int128.MIN_VALUE)).to.be.true; - }); - - it('returns false for out-of-range bigint values', function () { - expect(Int128.isValid(2n ** 127n)).to.be.false; - expect(Int128.isValid(-(2n ** 127n) - 1n)).to.be.false; - }); - - it('returns true for instances', function () { - expect(Int128.isValid(new Int128(42n))).to.be.true; - }); - - it('returns false for non-bigint/non-instance values', function () { - expect(Int128.isValid(42)).to.be.false; - expect(Int128.isValid('42')).to.be.false; - expect(Int128.isValid(null)).to.be.false; - }); -}); - -// ---------- toString / toJSON ---------- - -describe('Int128 serialization helpers', function () { - it('toString returns decimal string', function () { - const val = new Int128(-42n); - expect(val.toString()).to.eql('-42'); - }); - - it('toJSON returns object with string value', function () { - const val = new Int128(999n); - expect(val.toJSON()).to.eql({ _value: '999' }); - }); -}); diff --git a/test/unit/lazy.test.ts b/test/unit/lazy.test.ts new file mode 100644 index 0000000..2547b8a --- /dev/null +++ b/test/unit/lazy.test.ts @@ -0,0 +1,44 @@ +import { describe, it, expect } from 'vitest'; +import { lazy, int32, struct, option } from '../../src/index.js'; +import type { XdrType } from '../../src/index.js'; +import { bytes, toArray } from './_helpers.js'; + +interface ListNodeValue { + value: number; + next: ListNodeValue | null; +} + +describe('lazy', () => { + it('delegates encode/decode to the resolved schema', () => { + const schema = lazy(() => int32()); + expect(toArray(schema.encode(7))).toEqual([0, 0, 0, 7]); + expect(schema.decode(bytes([0, 0, 0, 7]))).toBe(7); + }); + + it('does not resolve the schema until first use', () => { + let resolved = 0; + const schema = lazy(() => { + resolved += 1; + return int32(); + }); + expect(resolved).toBe(0); + schema.encode(1); + expect(resolved).toBeGreaterThan(0); + }); + + it('supports recursive, self-referential schemas', () => { + // A cons-list node referencing itself through a lazy thunk. The explicit + // annotation breaks the self-referential type-inference cycle. + const ListNode: XdrType = struct('ListNode', { + value: int32(), + next: option(lazy((): XdrType => ListNode)) + }); + + const list = { value: 1, next: { value: 2, next: null } }; + const encoded = ListNode.encode(list); + expect(toArray(encoded)).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0 + ]); + expect(ListNode.decode(encoded)).toEqual(list); + }); +}); diff --git a/test/unit/opaque.test.ts b/test/unit/opaque.test.ts new file mode 100644 index 0000000..f568c13 --- /dev/null +++ b/test/unit/opaque.test.ts @@ -0,0 +1,44 @@ +import { describe, it, expect } from 'vitest'; +import { opaque } from '../../src/index.js'; +import { bytes, toArray, encodeInvalid } from './_helpers.js'; + +describe('opaque (fixed-length)', () => { + describe('encode', () => { + it('writes exactly length bytes when aligned', () => { + const schema = opaque(4); + expect(toArray(schema.encode(bytes([1, 2, 3, 4])))).toEqual([1, 2, 3, 4]); + }); + + it('zero-pads to a 4-byte boundary', () => { + const schema = opaque(3); + expect(toArray(schema.encode(bytes([1, 2, 3])))).toEqual([1, 2, 3, 0]); + }); + + it('throws on a length mismatch', () => { + const schema = opaque(3); + expect(() => schema.encode(bytes([1, 2]))).toThrow(/expected 3 byte/i); + expect(() => schema.encode(bytes([1, 2, 3, 4]))).toThrow( + /expected 3 byte/i + ); + }); + + it('throws for non-Uint8Array input', () => { + expect(() => encodeInvalid(opaque(2), [1, 2])).toThrow( + /expected Uint8Array/i + ); + }); + }); + + describe('decode', () => { + it('reads length bytes and consumes the padding', () => { + expect(toArray(opaque(4).decode(bytes([1, 2, 3, 4])))).toEqual([ + 1, 2, 3, 4 + ]); + expect(toArray(opaque(3).decode(bytes([1, 2, 3, 0])))).toEqual([1, 2, 3]); + }); + + it('throws on non-zero padding', () => { + expect(() => opaque(3).decode(bytes([1, 2, 3, 9]))).toThrow(/non-zero/i); + }); + }); +}); diff --git a/test/unit/opaque_test.js b/test/unit/opaque_test.js deleted file mode 100644 index 7bab216..0000000 --- a/test/unit/opaque_test.js +++ /dev/null @@ -1,54 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; -let Opaque = XDR.Opaque; - -let subject = new Opaque(3); - -describe('Opaque#read', function () { - it('decodes correctly', function () { - expect(read([0, 0, 0, 0])).to.eql(Buffer.from([0, 0, 0])); - expect(read([0, 0, 1, 0])).to.eql(Buffer.from([0, 0, 1])); - }); - - it('throws a read error if the padding bytes are not zero', function () { - expect(() => read([0, 0, 1, 1])).to.throw(/read error/i); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - const res = subject.read(io); - expect(io._index).to.eql(4, 'padding not processed by the reader'); - return res; - } -}); - -describe('Opaque#write', function () { - it('encodes correctly', function () { - expect(write(Buffer.from([0, 0, 0]))).to.eql([0, 0, 0, 0]); - expect(write(Buffer.from([0, 0, 1]))).to.eql([0, 0, 1, 0]); - }); - - function write(value) { - let io = new XdrWriter(8); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('Opaque#isValid', function () { - it('returns true for buffers of the correct length', function () { - expect(subject.isValid(Buffer.alloc(3))).to.be.true; - }); - - it('returns false for buffers of the wrong size', function () { - expect(subject.isValid(Buffer.alloc(2))).to.be.false; - expect(subject.isValid(Buffer.alloc(4))).to.be.false; - }); - - it('returns false for non buffers', function () { - expect(subject.isValid(true)).to.be.false; - expect(subject.isValid(null)).to.be.false; - expect(subject.isValid(3)).to.be.false; - expect(subject.isValid([0])).to.be.false; - }); -}); diff --git a/test/unit/option.test.ts b/test/unit/option.test.ts new file mode 100644 index 0000000..de4f2f6 --- /dev/null +++ b/test/unit/option.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect } from 'vitest'; +import { option, int32 } from '../../src/index.js'; +import { bytes, toArray, roundTrip } from './_helpers.js'; + +const schema = option(int32()); + +describe('option', () => { + describe('encode', () => { + it('writes a present flag plus the value when set', () => { + expect(toArray(schema.encode(5))).toEqual([0, 0, 0, 1, 0, 0, 0, 5]); + }); + + it('writes only the absent flag for null', () => { + expect(toArray(schema.encode(null))).toEqual([0, 0, 0, 0]); + }); + }); + + describe('decode', () => { + it('reads the present flag then the value', () => { + expect(schema.decode(bytes([0, 0, 0, 1, 0, 0, 0, 5]))).toBe(5); + }); + + it('reads null when the flag is absent', () => { + expect(schema.decode(bytes([0, 0, 0, 0]))).toBeNull(); + }); + }); + + it('round-trips present and absent values', () => { + expect(roundTrip(schema, 42)).toBe(42); + expect(roundTrip(schema, null)).toBeNull(); + }); +}); diff --git a/test/unit/option_test.js b/test/unit/option_test.js deleted file mode 100644 index 108fbb7..0000000 --- a/test/unit/option_test.js +++ /dev/null @@ -1,102 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -const subject = new XDR.Option(XDR.Int); - -describe('Option#read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00])).to.eql(0); - expect(read([0x00, 0x00, 0x00, 0x00])).to.be.undefined; - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return subject.read(io); - } -}); - -describe('Option#read maxDepth', function () { - it('throws when depth exceeds maxDepth', function () { - const optionType = new XDR.Option(XDR.Int, 2); - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(() => optionType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('succeeds when depth is within maxDepth', function () { - const optionType = new XDR.Option(XDR.Int, 5); - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - const result = optionType.read(reader, 4); - expect(result).to.eql(5); - }); - - it('succeeds for None value within maxDepth', function () { - const optionType = new XDR.Option(XDR.Int, 5); - const bytes = [0x00, 0x00, 0x00, 0x00]; - const reader = new XdrReader(bytes); - - const result = optionType.read(reader, 4); - expect(result).to.be.undefined; - }); - - it('uses default maxDepth of 200', function () { - const optionType = new XDR.Option(XDR.Int); - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(optionType._maxDepth).to.equal(200); - expect(() => optionType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('uses option maxDepth for child types', function () { - const innerArray = new XDR.VarArray(XDR.Int, 10, 2); - const optionType = new XDR.Option(innerArray, 5); - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a - ]; - const reader = new XdrReader(bytes); - - const result = optionType.read(reader, 2); - expect(result).to.eql([42]); - }); -}); - -describe('Option#write', function () { - it('encodes correctly', function () { - expect(write(3)).to.eql([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03]); - expect(write(null)).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write(undefined)).to.eql([0x00, 0x00, 0x00, 0x00]); - }); - - function write(value) { - let io = new XdrWriter(8); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('Option#isValid', function () { - it('returns true for values of the correct child type', function () { - expect(subject.isValid(0)).to.be.true; - expect(subject.isValid(-1)).to.be.true; - expect(subject.isValid(1)).to.be.true; - }); - - it('returns true for null and undefined', function () { - expect(subject.isValid(null)).to.be.true; - expect(subject.isValid(undefined)).to.be.true; - }); - - it('returns false for values of the wrong type', function () { - expect(subject.isValid(false)).to.be.false; - expect(subject.isValid('hello')).to.be.false; - expect(subject.isValid({})).to.be.false; - }); -}); diff --git a/test/unit/quadruple_test.js b/test/unit/quadruple_test.js deleted file mode 100644 index 8f1c0af..0000000 --- a/test/unit/quadruple_test.js +++ /dev/null @@ -1,35 +0,0 @@ -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrReader } from '../../src/serialization/xdr-reader'; - -const Quadruple = XDR.Quadruple; - -describe('Quadruple.read', function () { - it('is not supported', function () { - expect(() => read([0x00, 0x00, 0x00, 0x00])).to.throw( - /Type Definition Error/i - ); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Quadruple.read(io); - } -}); - -describe('Quadruple.write', function () { - it('is not supported', function () { - expect(() => write(0.0)).to.throw(/Type Definition Error/i); - }); - - function write(value) { - let io = new XdrWriter(8); - Quadruple.write(value, io); - return io.toArray(); - } -}); - -describe('Quadruple.isValid', function () { - it('returns false', function () { - expect(Quadruple.isValid(1.0)).to.be.false; - }); -}); diff --git a/test/unit/reader.test.ts b/test/unit/reader.test.ts new file mode 100644 index 0000000..f73730a --- /dev/null +++ b/test/unit/reader.test.ts @@ -0,0 +1,90 @@ +import { describe, it, expect } from 'vitest'; +import { Reader, option, int32 } from '../../src/index.js'; +import { bytes } from './_helpers.js'; + +describe('Reader', () => { + it('reads big-endian values and advances the offset', () => { + const reader = new Reader(bytes([0, 0, 0, 5, 255, 255, 255, 255])); + expect(reader.offset).toBe(0); + expect(reader.readInt32('p')).toBe(5); + expect(reader.offset).toBe(4); + expect(reader.readInt32('p')).toBe(-1); + expect(reader.remaining).toBe(0); + }); + + it('reads 64-bit and floating-point values', () => { + expect( + new Reader(bytes([255, 255, 255, 255, 255, 255, 255, 255])).readBigInt64( + 'p' + ) + ).toBe(-1n); + expect(new Reader(bytes([0, 0, 0, 0, 0, 0, 0, 1])).readBigUint64('p')).toBe( + 1n + ); + expect(new Reader(bytes([63, 128, 0, 0])).readFloat32('p')).toBe(1); + expect( + new Reader(bytes([63, 240, 0, 0, 0, 0, 0, 0])).readFloat64('p') + ).toBe(1); + }); + + describe('readBytes', () => { + it('throws on an invalid length', () => { + const reader = new Reader(bytes([0, 0, 0, 0])); + expect(() => reader.readBytes(-1, 'p')).toThrow(/invalid byte length/i); + expect(() => reader.readBytes(1.5, 'p')).toThrow(/invalid byte length/i); + }); + + it('throws when there is not enough data', () => { + const reader = new Reader(bytes([0, 0])); + expect(() => reader.readBytes(4, 'p')).toThrow(/incomplete/i); + }); + }); + + describe('skipPadding', () => { + it('consumes the padding bytes for a given length', () => { + const reader = new Reader(bytes([0, 0, 0])); + reader.skipPadding(1, 'p'); + expect(reader.remaining).toBe(0); + }); + + it('throws on non-zero padding', () => { + const reader = new Reader(bytes([0, 9, 0])); + expect(() => reader.skipPadding(1, 'p')).toThrow(/non-zero/i); + }); + }); + + describe('done', () => { + it('passes when input is fully consumed', () => { + expect(() => new Reader(bytes([])).done('p')).not.toThrow(); + }); + + it('throws when bytes remain', () => { + expect(() => new Reader(bytes([1, 2])).done('p')).toThrow(/trailing/i); + }); + }); + + describe('enter / exit depth tracking', () => { + it('throws once depth exceeds maxDepth', () => { + const reader = new Reader(bytes([]), 2); + reader.enter('p'); + reader.enter('p'); + expect(() => reader.enter('p')).toThrow(/max recursion depth/i); + }); + + it('exit frees a level of depth', () => { + const reader = new Reader(bytes([]), 1); + reader.enter('p'); + reader.exit(); + expect(() => reader.enter('p')).not.toThrow(); + }); + }); + + it('decode honors the maxDepth option', () => { + const nested = option(option(int32())); + const wire = bytes([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5]); + expect(() => nested.decode(wire, { maxDepth: 1 })).toThrow( + /max recursion depth/i + ); + expect(nested.decode(wire, { maxDepth: 2 })).toBe(5); + }); +}); diff --git a/test/unit/string.test.ts b/test/unit/string.test.ts new file mode 100644 index 0000000..fd4eef3 --- /dev/null +++ b/test/unit/string.test.ts @@ -0,0 +1,70 @@ +import { describe, it, expect } from 'vitest'; +import { string } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +// `string` is a charset-free primitive: length-prefixed, 4-byte-padded raw +// bytes. Charset handling lives in a higher layer, so the schema operates on +// Uint8Array directly. +const schema = string(100); + +describe('string', () => { + describe('encode', () => { + it('length-prefixes and pads to a 4-byte boundary', () => { + expect(toArray(schema.encode(bytes([72, 105])))).toEqual([ + 0, 0, 0, 2, 72, 105, 0, 0 + ]); + expect(toArray(schema.encode(bytes([97, 98, 99, 100])))).toEqual([ + 0, 0, 0, 4, 97, 98, 99, 100 + ]); + }); + + it('encodes empty content', () => { + expect(toArray(schema.encode(bytes([])))).toEqual([0, 0, 0, 0]); + }); + + it('throws when exceeding maxLength', () => { + expect(() => string(2).encode(bytes([1, 2, 3]))).toThrow( + /exceeds maximum/i + ); + }); + + it('throws for non-Uint8Array input', () => { + expect(() => encodeInvalid(schema, 'Hi')).toThrow(/expected Uint8Array/i); + expect(() => encodeInvalid(schema, 123)).toThrow(/expected Uint8Array/i); + }); + }); + + describe('decode', () => { + it('reads the length-prefixed payload and consumes padding', () => { + expect( + toArray(schema.decode(bytes([0, 0, 0, 2, 72, 105, 0, 0]))) + ).toEqual([72, 105]); + expect(toArray(schema.decode(bytes([0, 0, 0, 0])))).toEqual([]); + }); + + it('throws when the declared length exceeds maxLength', () => { + expect(() => + string(2).decode(bytes([0, 0, 0, 3, 97, 98, 99, 0])) + ).toThrow(/exceeds maximum/i); + }); + }); + + it('round-trips arbitrary bytes, including non-UTF-8', () => { + for (const value of [[], [0], [255], [72, 105], [0xff, 0x00, 0xab]]) { + expect(toArray(roundTrip(schema, bytes(value)))).toEqual(value); + } + }); + + describe('validate', () => { + it('accepts byte arrays within maxLength', () => { + expect(schema.validate(bytes([1, 2, 3]))).toBe(true); + expect(schema.validate(bytes([]))).toBe(true); + }); + + it('rejects oversized payloads and non-bytes', () => { + expect(string(2).validate(bytes([1, 2, 3]))).toBe(false); + expect(schema.validate('hi')).toBe(false); + expect(schema.validate(123)).toBe(false); + }); + }); +}); diff --git a/test/unit/string_test.js b/test/unit/string_test.js deleted file mode 100644 index 5e8ad32..0000000 --- a/test/unit/string_test.js +++ /dev/null @@ -1,148 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -let subject = new XDR.String(4); - -describe('String#read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00]).toString('utf8')).to.eql(''); - expect( - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x00]).toString('utf8') - ).to.eql('A'); - expect( - read([0x00, 0x00, 0x00, 0x03, 0xe4, 0xb8, 0x89, 0x00]).toString('utf8') - ).to.eql('三'); - expect( - read([0x00, 0x00, 0x00, 0x02, 0x41, 0x41, 0x00, 0x00]).toString('utf8') - ).to.eql('AA'); - }); - - it('decodes correctly to string', function () { - expect(readString([0x00, 0x00, 0x00, 0x00])).to.eql(''); - expect(readString([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x00])).to.eql( - 'A' - ); - expect(readString([0x00, 0x00, 0x00, 0x03, 0xe4, 0xb8, 0x89, 0x00])).to.eql( - '三' - ); - expect(readString([0x00, 0x00, 0x00, 0x02, 0x41, 0x41, 0x00, 0x00])).to.eql( - 'AA' - ); - }); - - it('decodes non-utf-8 correctly', function () { - let val = read([0x00, 0x00, 0x00, 0x01, 0xd1, 0x00, 0x00, 0x00]); - expect(val[0]).to.eql(0xd1); - }); - - it('throws a read error when the encoded length is greater than the allowed max', function () { - expect(() => - read([0x00, 0x00, 0x00, 0x05, 0x41, 0x41, 0x41, 0x41, 0x41]) - ).to.throw(/read error/i); - }); - - it('throws a read error if the padding bytes are not zero', function () { - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00]) - ).to.throw(/read error/i); - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x01, 0x00]) - ).to.throw(/read error/i); - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01]) - ).to.throw(/read error/i); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return subject.read(io); - } - - function readString(bytes) { - const io = new XdrReader(bytes); - const res = subject.readString(io); - expect(io._index).to.eql( - !res ? 4 : 8, - 'padding not processed by the reader' - ); - return res; - } -}); - -describe('String#write', function () { - it('encodes string correctly', function () { - expect(write('')).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write('三')).to.eql([ - 0x00, 0x00, 0x00, 0x03, 0xe4, 0xb8, 0x89, 0x00 - ]); - expect(write('A')).to.eql([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x00]); - expect(write('AA')).to.eql([ - 0x00, 0x00, 0x00, 0x02, 0x41, 0x41, 0x00, 0x00 - ]); - }); - - it('encodes non-utf-8 correctly', function () { - expect(write([0xd1])).to.eql([ - 0x00, 0x00, 0x00, 0x01, 0xd1, 0x00, 0x00, 0x00 - ]); - }); - - it('encodes non-utf-8 correctly (buffer)', function () { - expect(write(Buffer.from([0xd1]))).to.eql([ - 0x00, 0x00, 0x00, 0x01, 0xd1, 0x00, 0x00, 0x00 - ]); - }); - - it('checks actual utf-8 strings length on write', function () { - expect(() => write('€€€€')).to.throw(/max allowed/i); - }); - - function write(value) { - let io = new XdrWriter(8); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('String#isValid', function () { - it('returns true for strings of the correct length', function () { - expect(subject.isValid('')).to.be.true; - expect(subject.isValid('a')).to.be.true; - expect(subject.isValid('aa')).to.be.true; - }); - - it('returns true for arrays of the correct length', function () { - expect(subject.isValid([0x01])).to.be.true; - }); - - it('returns true for buffers of the correct length', function () { - expect(subject.isValid(Buffer.from([0x01]))).to.be.true; - }); - - it('returns false for strings that are too large', function () { - expect(subject.isValid('aaaaa')).to.be.false; - }); - - it('returns false for arrays that are too large', function () { - expect(subject.isValid([0x01, 0x01, 0x01, 0x01, 0x01])).to.be.false; - }); - - it('returns false for buffers that are too large', function () { - expect(subject.isValid(Buffer.from([0x01, 0x01, 0x01, 0x01, 0x01]))).to.be - .false; - }); - - it('returns false for non string/array/buffer', function () { - expect(subject.isValid(true)).to.be.false; - expect(subject.isValid(null)).to.be.false; - expect(subject.isValid(3)).to.be.false; - }); -}); - -describe('String#constructor', function () { - let subject = new XDR.String(); - - it('defaults to max length of a uint max value', function () { - expect(subject._maxLength).to.eql(Math.pow(2, 32) - 1); - }); -}); diff --git a/test/unit/struct.test.ts b/test/unit/struct.test.ts new file mode 100644 index 0000000..7f5c922 --- /dev/null +++ b/test/unit/struct.test.ts @@ -0,0 +1,64 @@ +import { describe, it, expect } from 'vitest'; +import { struct, int32, bool } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const Range = struct('Range', { + begin: int32(), + end: int32(), + inclusive: bool() +}); + +describe('struct', () => { + it('keeps its name', () => { + expect(Range.name).toBe('Range'); + }); + + describe('encode', () => { + it('writes fields in declaration order', () => { + expect( + toArray(Range.encode({ begin: 5, end: 255, inclusive: true })) + ).toEqual([0, 0, 0, 5, 0, 0, 0, 255, 0, 0, 0, 1]); + }); + + it('throws when a field is missing', () => { + expect(() => encodeInvalid(Range, { begin: 1, end: 2 })).toThrow( + /missing struct field/i + ); + }); + + it('throws for non-object input', () => { + expect(() => encodeInvalid(Range, null)).toThrow( + /expected plain object/i + ); + expect(() => encodeInvalid(Range, [])).toThrow(/expected plain object/i); + }); + + it('propagates field validation errors', () => { + expect(() => + Range.encode({ begin: 2147483648, end: 0, inclusive: false }) + ).toThrow(/range/i); + }); + }); + + describe('decode', () => { + it('reads each field in order', () => { + expect( + Range.decode(bytes([0, 0, 0, 5, 0, 0, 0, 255, 0, 0, 0, 1])) + ).toEqual({ begin: 5, end: 255, inclusive: true }); + }); + }); + + it('supports nested structs', () => { + const Line = struct('Line', { a: Range, b: Range }); + const value = { + a: { begin: 0, end: 1, inclusive: false }, + b: { begin: 2, end: 3, inclusive: true } + }; + expect(roundTrip(Line, value)).toEqual(value); + }); + + it('round-trips', () => { + const value = { begin: -1, end: 100, inclusive: false }; + expect(roundTrip(Range, value)).toEqual(value); + }); +}); diff --git a/test/unit/struct_test.js b/test/unit/struct_test.js deleted file mode 100644 index a8441b0..0000000 --- a/test/unit/struct_test.js +++ /dev/null @@ -1,252 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { Struct } from '../../src/struct'; - -/* jshint -W030 */ - -let emptyContext = { definitions: {}, results: {} }; -let MyRange = XDR.Struct.create(emptyContext, 'MyRange', [ - ['begin', XDR.Int], - ['end', XDR.Int], - ['inclusive', XDR.Bool] -]); - -describe('Struct.read', function () { - it('decodes correctly', function () { - let empty = read([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - expect(empty).to.be.instanceof(MyRange); - expect(empty.begin()).to.eql(0); - expect(empty.end()).to.eql(0); - expect(empty.inclusive()).to.eql(false); - - let filled = read([ - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01 - ]); - expect(filled).to.be.instanceof(MyRange); - expect(filled.begin()).to.eql(5); - expect(filled.end()).to.eql(255); - expect(filled.inclusive()).to.eql(true); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return MyRange.read(io); - } -}); - -describe('Struct.read maxDepth', function () { - let context; - - beforeEach(function () { - context = { definitions: {}, results: {} }; - }); - - it('throws when depth exceeds maxDepth', function () { - const MyStruct = XDR.Struct.create(context, 'DepthStruct', [ - ['value', XDR.Int] - ]); - MyStruct._maxDepth = 2; - - const bytes = [0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(() => MyStruct.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('succeeds when depth is within maxDepth', function () { - const MyStruct = XDR.Struct.create(context, 'DepthStruct2', [ - ['value', XDR.Int] - ]); - MyStruct._maxDepth = 5; - - const bytes = [0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - const result = MyStruct.read(reader, 4); - expect(result.value()).to.eql(5); - }); - - it('uses default maxDepth of 200 from create', function () { - const MyStruct = XDR.Struct.create(context, 'DepthStruct3', [ - ['value', XDR.Int] - ]); - expect(MyStruct._maxDepth).to.eql(200); - - const bytes = [0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(() => MyStruct.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('uses maxDepth provided by create', function () { - const MyStruct = XDR.Struct.create( - context, - 'DepthStruct3', - [['value', XDR.Int]], - 300 - ); - expect(MyStruct._maxDepth).to.eql(300); - const bytes = [0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(() => MyStruct.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('propagates depth to child fields', function () { - const stringArray = new XDR.VarArray(new XDR.String(100), 10, 3); - const MyStruct = XDR.Struct.create(context, 'NestedStruct', [ - ['names', stringArray] - ]); - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x48, 0x69, 0x00, 0x00 - ]; - const reader = new XdrReader(bytes); - - const result = MyStruct.read(reader, 1); - expect(result.names().length).to.eql(1); - expect(result.names()[0].toString('utf8')).to.eql('Hi'); - }); - - it('uses struct maxDepth for nested field decoding', function () { - const innerArray = new XDR.VarArray(XDR.Int, 10, 1); - const outerArray = new XDR.VarArray(innerArray, 10, 5); - const MyStruct = XDR.Struct.create( - context, - 'NestedDepthStruct', - [['values', outerArray]], - 5 - ); - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a - ]; - const reader = new XdrReader(bytes); - - const result = MyStruct.read(reader, 2); - expect(result.values()).to.eql([[42]]); - }); -}); - -describe('Struct.write', function () { - it('encodes correctly', function () { - let empty = new MyRange({ - begin: 0, - end: 0, - inclusive: false - }); - - expect(write(empty)).to.eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - - let filled = new MyRange({ - begin: 5, - end: 255, - inclusive: true - }); - - expect(write(filled)).to.eql([ - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01 - ]); - }); - - it('throws a write error if the value is not the correct type', function () { - expect(() => write(null)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write({})).to.throw(/write error/i); - expect(() => write(1)).to.throw(/write error/i); - expect(() => write(true)).to.throw(/write error/i); - }); - - it('throws a write error if the struct is not valid', function () { - expect(() => write(new MyRange({}))).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(256); - MyRange.write(value, io); - return io.toArray(); - } -}); - -describe('Struct.isValid', function () { - it('returns true for instances of the struct', function () { - expect(MyRange.isValid(new MyRange({}))).to.be.true; - }); - - it('works for "struct-like" objects', function () { - class FakeStruct extends Struct {} - - FakeStruct.structName = 'MyRange'; - let r = new FakeStruct(); - expect(MyRange.isValid(r)).to.be.true; - - FakeStruct.structName = 'NotMyRange'; - r = new FakeStruct(); - expect(MyRange.isValid(r)).to.be.false; - }); - - it('returns false for anything else', function () { - expect(MyRange.isValid(null)).to.be.false; - expect(MyRange.isValid(undefined)).to.be.false; - expect(MyRange.isValid([])).to.be.false; - expect(MyRange.isValid({})).to.be.false; - expect(MyRange.isValid(1)).to.be.false; - expect(MyRange.isValid(true)).to.be.false; - }); -}); - -describe('Struct.validateXDR', function () { - it('returns true for valid XDRs', function () { - let subject = new MyRange({ begin: 5, end: 255, inclusive: true }); - expect(MyRange.validateXDR(subject.toXDR())).to.be.true; - expect(MyRange.validateXDR(subject.toXDR('hex'), 'hex')).to.be.true; - expect(MyRange.validateXDR(subject.toXDR('base64'), 'base64')).to.be.true; - }); - - it('returns false for invalid XDRs', function () { - expect(MyRange.validateXDR(Buffer.alloc(1))).to.be.false; - expect(MyRange.validateXDR('00', 'hex')).to.be.false; - expect(MyRange.validateXDR('AA==', 'base64')).to.be.false; - }); -}); - -describe('Struct: attributes', function () { - it('properly retrieves attributes', function () { - let subject = new MyRange({ begin: 5, end: 255, inclusive: true }); - expect(subject.begin()).to.eql(5); - }); - - it('properly sets attributes', function () { - let subject = new MyRange({ begin: 5, end: 255, inclusive: true }); - expect(subject.begin(10)).to.eql(10); - expect(subject.begin()).to.eql(10); - }); -}); - -describe('Struct: constructor maxDepth', function () { - it('inherits maxDepth from the struct class when omitted', function () { - let context = { definitions: {}, results: {} }; - let DepthStruct = XDR.Struct.create( - context, - 'CtorDepthStruct', - [['value', XDR.Int]], - 9 - ); - - expect(new DepthStruct({ value: 1 })._maxDepth).to.eql(9); - - DepthStruct._maxDepth = 4; - expect(new DepthStruct({ value: 2 })._maxDepth).to.eql(4); - }); -}); diff --git a/test/unit/struct_union_test.js b/test/unit/struct_union_test.js deleted file mode 100644 index 8e32120..0000000 --- a/test/unit/struct_union_test.js +++ /dev/null @@ -1,43 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; - -/* jshint -W030 */ - -let emptyContext = { definitions: {}, results: {} }; - -let Ext = XDR.Union.create(emptyContext, 'Ext', { - switchOn: XDR.Int, - switches: [ - [0, XDR.Void], - [1, XDR.Int] - ] -}); - -let StructUnion = XDR.Struct.create(emptyContext, 'StructUnion', [ - ['id', XDR.Int], - ['ext', Ext] -]); - -describe('StructUnion.read', function () { - it('decodes correctly', function () { - let empty = read([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]); - expect(empty).to.be.instanceof(StructUnion); - expect(empty.id()).to.eql(1); - expect(empty.ext().switch()).to.eql(0); - expect(empty.ext().arm()).to.eql(XDR.Void); - - let filled = read([ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 - ]); - - expect(filled).to.be.instanceof(StructUnion); - expect(filled.id()).to.eql(2); - expect(filled.ext().switch()).to.eql(1); - expect(filled.ext().arm()).to.eql(XDR.Int); - expect(filled.ext().value()).to.eql(2); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return StructUnion.read(io); - } -}); diff --git a/test/unit/uint32.test.ts b/test/unit/uint32.test.ts new file mode 100644 index 0000000..4f65b8c --- /dev/null +++ b/test/unit/uint32.test.ts @@ -0,0 +1,49 @@ +import { describe, it, expect } from 'vitest'; +import { uint32 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = uint32(); + +describe('uint32', () => { + describe('decode', () => { + it('decodes big-endian unsigned integers', () => { + expect(schema.decode(bytes([0, 0, 0, 0]))).toBe(0); + expect(schema.decode(bytes([0, 0, 0, 255]))).toBe(255); + expect(schema.decode(bytes([255, 255, 255, 255]))).toBe(4294967295); + }); + }); + + describe('encode', () => { + it('encodes big-endian unsigned integers', () => { + expect(toArray(schema.encode(0))).toEqual([0, 0, 0, 0]); + expect(toArray(schema.encode(255))).toEqual([0, 0, 0, 255]); + expect(toArray(schema.encode(4294967295))).toEqual([255, 255, 255, 255]); + }); + + it('throws when out of range', () => { + expect(() => schema.encode(-1)).toThrow(/range/i); + expect(() => schema.encode(4294967296)).toThrow(/range/i); + }); + + it('throws for non-integers', () => { + expect(() => schema.encode(1.5)).toThrow(/range/i); + expect(() => encodeInvalid(schema, '1')).toThrow(/range/i); + }); + }); + + it('round-trips boundary values', () => { + for (const value of [0, 1, 255, 4294967295]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); + + describe('validate', () => { + it('accepts in-range integers and rejects everything else', () => { + expect(schema.validate(0)).toBe(true); + expect(schema.validate(4294967295)).toBe(true); + expect(schema.validate(-1)).toBe(false); + expect(schema.validate(4294967296)).toBe(false); + expect(schema.validate(1.5)).toBe(false); + }); + }); +}); diff --git a/test/unit/uint64.test.ts b/test/unit/uint64.test.ts new file mode 100644 index 0000000..dec6b50 --- /dev/null +++ b/test/unit/uint64.test.ts @@ -0,0 +1,42 @@ +import { describe, it, expect } from 'vitest'; +import { uint64 } from '../../src/index.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const schema = uint64(); +const MAX = (1n << 64n) - 1n; + +describe('uint64', () => { + describe('decode', () => { + it('decodes big-endian unsigned bigints', () => { + expect(schema.decode(bytes([0, 0, 0, 0, 0, 0, 0, 0]))).toBe(0n); + expect(schema.decode(bytes([0, 0, 0, 0, 0, 0, 0, 1]))).toBe(1n); + expect( + schema.decode(bytes([255, 255, 255, 255, 255, 255, 255, 255])) + ).toBe(MAX); + }); + }); + + describe('encode', () => { + it('encodes big-endian unsigned bigints', () => { + expect(toArray(schema.encode(1n))).toEqual([0, 0, 0, 0, 0, 0, 0, 1]); + expect(toArray(schema.encode(MAX))).toEqual([ + 255, 255, 255, 255, 255, 255, 255, 255 + ]); + }); + + it('throws when out of range', () => { + expect(() => schema.encode(-1n)).toThrow(/range/i); + expect(() => schema.encode(MAX + 1n)).toThrow(/range/i); + }); + + it('throws for non-bigint input', () => { + expect(() => encodeInvalid(schema, 5)).toThrow(/range/i); + }); + }); + + it('round-trips boundary values', () => { + for (const value of [0n, 1n, MAX]) { + expect(roundTrip(schema, value)).toBe(value); + } + }); +}); diff --git a/test/unit/union.test.ts b/test/unit/union.test.ts new file mode 100644 index 0000000..082e8d4 --- /dev/null +++ b/test/unit/union.test.ts @@ -0,0 +1,119 @@ +import { describe, it, expect } from 'vitest'; +import { union, enumType, int32, void as voidType } from '../../src/index.js'; +import { field, case as caseOf } from '../../src/types/union.js'; +import { bytes, toArray, roundTrip, encodeInvalid } from './_helpers.js'; + +const AssetType = enumType('AssetType', { native: 0, credit: 1 }); +const Asset = union('Asset', { + switchOn: AssetType, + cases: [ + caseOf('native', AssetType.native, voidType()), + caseOf('credit', AssetType.credit, field('code', int32())) + ] +}); + +describe('union', () => { + it('keeps its name', () => { + expect(Asset.name).toBe('Asset'); + }); + + describe('encode', () => { + it('writes the discriminant then a void arm', () => { + expect(toArray(Asset.encode({ type: 0 }))).toEqual([0, 0, 0, 0]); + }); + + it('writes the discriminant then the arm payload', () => { + expect(toArray(Asset.encode({ type: 1, code: 7 }))).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 7 + ]); + }); + + it('throws when the arm payload is missing', () => { + expect(() => encodeInvalid(Asset, { type: 1 })).toThrow( + /missing union arm payload/i + ); + }); + + it('throws when the value has no discriminator key', () => { + expect(() => encodeInvalid(Asset, {})).toThrow(/expected union object/i); + }); + }); + + describe('decode', () => { + it('reads a void arm', () => { + expect(Asset.decode(bytes([0, 0, 0, 0]))).toEqual({ type: 0 }); + }); + + it('reads an arm payload', () => { + expect(Asset.decode(bytes([0, 0, 0, 1, 0, 0, 0, 7]))).toEqual({ + type: 1, + code: 7 + }); + }); + }); + + it('round-trips both arms', () => { + expect(roundTrip(Asset, { type: 0 })).toEqual({ type: 0 }); + expect(roundTrip(Asset, { type: 1, code: 42 })).toEqual({ + type: 1, + code: 42 + }); + }); + + describe('default arm', () => { + const Tagged = union('Tagged', { + switchOn: int32(), + cases: [caseOf('one', 1, field('a', int32()))], + defaultArm: field('other', int32()) + }); + + it('uses the matching case when present', () => { + expect(toArray(Tagged.encode({ type: 1, a: 5 }))).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 5 + ]); + }); + + it('falls back to the default arm', () => { + expect(toArray(Tagged.encode({ type: 99, other: 7 }))).toEqual([ + 0, 0, 0, 99, 0, 0, 0, 7 + ]); + expect(Tagged.decode(bytes([0, 0, 0, 99, 0, 0, 0, 7]))).toEqual({ + type: 99, + other: 7 + }); + }); + }); + + describe('without a default arm', () => { + const NoDefault = union('NoDefault', { + switchOn: int32(), + cases: [caseOf('one', 1, voidType())] + }); + + it('throws on an unmatched discriminant when encoding', () => { + expect(() => encodeInvalid(NoDefault, { type: 2 })).toThrow(/no case/i); + }); + + it('throws on an unmatched discriminant when decoding', () => { + expect(() => NoDefault.decode(bytes([0, 0, 0, 2]))).toThrow(/no case/i); + }); + }); + + describe('custom switchKey', () => { + const Custom = union('Custom', { + switchOn: int32(), + switchKey: 'kind', + cases: [caseOf('one', 1, field('a', int32()))] + }); + + it('uses the configured discriminator key', () => { + expect(toArray(Custom.encode({ kind: 1, a: 5 }))).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 5 + ]); + expect(Custom.decode(bytes([0, 0, 0, 1, 0, 0, 0, 5]))).toEqual({ + kind: 1, + a: 5 + }); + }); + }); +}); diff --git a/test/unit/union_test.js b/test/unit/union_test.js deleted file mode 100644 index 09d8a11..0000000 --- a/test/unit/union_test.js +++ /dev/null @@ -1,334 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; -import { XdrPrimitiveType } from '../../src/xdr-type'; - -/* jshint -W030 */ - -let emptyContext = { definitions: {}, results: {} }; -let ResultType = XDR.Enum.create(emptyContext, 'ResultType', { - ok: 0, - error: 1, - nonsense: 2 -}); - -let Result = XDR.Union.create(emptyContext, 'Result', { - switchOn: ResultType, - switches: [ - ['ok', XDR.Void], - ['error', 'code'] - ], - defaultArm: XDR.Void, - arms: { - code: XDR.Int - } -}); - -let Ext = XDR.Union.create(emptyContext, 'Ext', { - switchOn: XDR.Int, - switches: [[0, XDR.Void]] -}); - -describe('Union.armForSwitch', function () { - it('returns the defined arm for the provided switch', function () { - expect(Result.armForSwitch(ResultType.ok())).to.eql(XDR.Void); - expect(Result.armForSwitch(ResultType.error())).to.eql('code'); - }); - - it('returns the default arm if no specific arm is defined', function () { - expect(Result.armForSwitch(ResultType.nonsense())).to.eql(XDR.Void); - }); - - it('works for XDR.Int discriminated unions', function () { - expect(Ext.armForSwitch(0)).to.eql(XDR.Void); - }); -}); - -describe('Union: constructor', function () { - beforeEach(function () { - Result._maxDepth = 200; - }); - - it('works for XDR.Int discriminated unions', function () { - expect(() => new Ext(0)).to.not.throw(); - }); - - it('works for Enum discriminated unions', function () { - expect(() => new Result('ok')).to.not.throw(); - expect(() => new Result(ResultType.ok())).to.not.throw(); - }); - - it('inherits maxDepth from the union class when omitted', function () { - let context = { definitions: {}, results: {} }; - let Kind = XDR.Enum.create(context, 'CtorDepthKind', { - ok: 0, - error: 1 - }); - let DepthUnion = XDR.Union.create( - context, - 'CtorDepthUnion', - { - switchOn: Kind, - switches: [ - ['ok', XDR.Void], - ['error', 'code'] - ], - arms: { - code: XDR.Int - } - }, - 7 - ); - - expect(DepthUnion.ok()._maxDepth).to.eql(7); - - DepthUnion._maxDepth = 3; - expect(DepthUnion.ok()._maxDepth).to.eql(3); - }); -}); - -describe('Union: set', function () { - it('works for XDR.Int discriminated unions', function () { - let u = new Ext(0); - u.set(0); - }); - - it('works for Enum discriminated unions', function () { - let u = Result.ok(); - - expect(() => u.set('ok')).to.not.throw(); - expect(() => u.set('notok')).to.throw(/not a member/); - expect(() => u.set(ResultType.ok())).to.not.throw(); - }); -}); - -describe('Union.read', function () { - it('decodes correctly', function () { - let ok = read([0x00, 0x00, 0x00, 0x00]); - - expect(ok).to.be.instanceof(Result); - expect(ok.switch()).to.eql(ResultType.ok()); - expect(ok.arm()).to.eql(XDR.Void); - expect(ok.armType()).to.eql(XDR.Void); - expect(ok.value()).to.be.undefined; - - let error = read([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]); - - expect(error).to.be.instanceof(Result); - expect(error.switch()).to.eql(ResultType.error()); - expect(error.arm()).to.eql('code'); - expect(error.armType()).to.eql(XDR.Int); - expect(error.value()).to.eql(5); - expect(error.code()).to.eql(5); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return Result.read(io); - } -}); - -describe('Union.read maxDepth', function () { - beforeEach(function () { - Result._maxDepth = 200; - }); - - it('throws when depth exceeds maxDepth', function () { - Result._maxDepth = 2; - - const bytes = [0x00, 0x00, 0x00, 0x00]; - const reader = new XdrReader(bytes); - - expect(() => Result.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('succeeds when depth is within maxDepth', function () { - Result._maxDepth = 5; - - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - const result = Result.read(reader, 4); - expect(result.switch()).to.eql(ResultType.error()); - expect(result.code()).to.eql(5); - }); - - it('uses default maxDepth of 200 from create', function () { - const context = { definitions: {}, results: {} }; - const Kind = XDR.Enum.create(context, 'Kind', { ok: 0, error: 1 }); - const DepthUnion = XDR.Union.create(context, 'DepthUnion', { - switchOn: Kind, - switches: [ - ['ok', XDR.Void], - ['error', 'code'] - ], - arms: { - code: XDR.Int - } - }); - - expect(DepthUnion._maxDepth).to.eql(200); - - const bytes = [0x00, 0x00, 0x00, 0x00]; - const reader = new XdrReader(bytes); - - expect(() => DepthUnion.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('uses maxDepth from create', function () { - const context = { definitions: {}, results: {} }; - const Kind = XDR.Enum.create(context, 'Kind', { ok: 0, error: 1 }); - const DepthUnion = XDR.Union.create( - context, - 'DepthUnion', - { - switchOn: Kind, - switches: [ - ['ok', XDR.Void], - ['error', 'code'] - ], - arms: { - code: XDR.Int - } - }, - 300 - ); - - expect(DepthUnion._maxDepth).to.eql(300); - - const bytes = [0x00, 0x00, 0x00, 0x00]; - const reader = new XdrReader(bytes); - - expect(() => DepthUnion.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); -}); - -describe('Union.read nested maxDepth', function () { - let context; - let ResultTypeDepth; - - beforeEach(function () { - context = { definitions: {}, results: {} }; - ResultTypeDepth = XDR.Enum.create(context, 'ResultTypeDepth', { - ok: 0, - data: 1 - }); - }); - - it('propagates depth to arm types', function () { - const dataArray = new XDR.VarArray(XDR.Int, 10, 3); - const DepthUnion = XDR.Union.create(context, 'NestedUnion', { - switchOn: ResultTypeDepth, - switches: [ - ['ok', XDR.Void], - ['data', 'values'] - ], - arms: { - values: dataArray - } - }); - DepthUnion._maxDepth = 5; - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a - ]; - const reader = new XdrReader(bytes); - - const result = DepthUnion.read(reader, 1); - expect(result.switch()).to.eql(ResultTypeDepth.data()); - expect(result.values()).to.eql([42]); - }); - - it('uses union maxDepth for arm type decoding', function () { - const dataArray = new XDR.VarArray(XDR.Int, 10, 1); - const DepthUnion = XDR.Union.create(context, 'NestedUnion2', { - switchOn: ResultTypeDepth, - switches: [ - ['ok', XDR.Void], - ['data', 'values'] - ], - arms: { - values: dataArray - } - }); - DepthUnion._maxDepth = 5; - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a - ]; - const reader = new XdrReader(bytes); - - const result = DepthUnion.read(reader, 1); - expect(result.values()).to.eql([42]); - }); -}); - -describe('Union.write', function () { - it('encodes correctly', function () { - let ok = Result.ok(); - - expect(write(ok)).to.eql([0x00, 0x00, 0x00, 0x00]); - - let error = Result.error(5); - - expect(write(error)).to.eql([ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05 - ]); - }); - - it('throws a write error if the value is not the correct type', function () { - expect(() => write(null)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write({})).to.throw(/write error/i); - expect(() => write(1)).to.throw(/write error/i); - expect(() => write(true)).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(256); - Result.write(value, io); - return io.toArray(); - } -}); - -describe('Union.isValid', function () { - it('returns true for instances of the union', function () { - expect(Result.isValid(Result.ok())).to.be.true; - expect(Result.isValid(Result.error(1))).to.be.true; - expect(Result.isValid(Result.nonsense())).to.be.true; - }); - - it('works for "union-like" objects', function () { - class FakeUnion extends XdrPrimitiveType {} - - FakeUnion.unionName = 'Result'; - let r = new FakeUnion(); - expect(Result.isValid(r)).to.be.true; - - FakeUnion.unionName = 'NotResult'; - r = new FakeUnion(); - expect(Result.isValid(r)).to.be.false; - - // make sure you can't fool it - FakeUnion.unionName = undefined; - FakeUnion.structName = 'Result'; - r = new FakeUnion(); - expect(Result.isValid(r)).to.be.false; - }); - - it('returns false for anything else', function () { - expect(Result.isValid(null)).to.be.false; - expect(Result.isValid(undefined)).to.be.false; - expect(Result.isValid([])).to.be.false; - expect(Result.isValid({})).to.be.false; - expect(Result.isValid(1)).to.be.false; - expect(Result.isValid(true)).to.be.false; - expect(Result.isValid('ok')).to.be.false; - }); -}); diff --git a/test/unit/unsigned-hyper_test.js b/test/unit/unsigned-hyper_test.js deleted file mode 100644 index 8100f57..0000000 --- a/test/unit/unsigned-hyper_test.js +++ /dev/null @@ -1,99 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -const UnsignedHyper = XDR.UnsignedHyper; - -describe('UnsignedHyper.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])).to.eql( - UnsignedHyper.fromString('0') - ); - expect(read([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])).to.eql( - UnsignedHyper.fromString('1') - ); - expect(read([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])).to.eql( - new UnsignedHyper(UnsignedHyper.MAX_VALUE) - ); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return UnsignedHyper.read(io); - } -}); - -describe('UnsignedHyper.write', function () { - it('encodes correctly', function () { - expect(write(UnsignedHyper.fromString('0'))).to.eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ]); - expect(write(UnsignedHyper.fromString('1'))).to.eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - ]); - expect(write(UnsignedHyper.MAX_VALUE)).to.eql([ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - ]); - }); - - function write(value) { - let io = new XdrWriter(8); - UnsignedHyper.write(value, io); - return io.toArray(); - } -}); - -describe('UnsignedHyper.isValid', function () { - it('returns true for UnsignedHyper instances', function () { - expect(UnsignedHyper.isValid(UnsignedHyper.fromString('1'))).to.be.true; - expect(UnsignedHyper.isValid(UnsignedHyper.MIN_VALUE)).to.be.true; - expect(UnsignedHyper.isValid(UnsignedHyper.MAX_VALUE)).to.be.true; - }); - - it('returns false for non UnsignedHypers', function () { - expect(UnsignedHyper.isValid(null)).to.be.false; - expect(UnsignedHyper.isValid(undefined)).to.be.false; - expect(UnsignedHyper.isValid([])).to.be.false; - expect(UnsignedHyper.isValid({})).to.be.false; - expect(UnsignedHyper.isValid(1)).to.be.false; - expect(UnsignedHyper.isValid(true)).to.be.false; - }); -}); - -describe('UnsignedHyper.fromString', function () { - it('works for positive numbers', function () { - expect(UnsignedHyper.fromString('1059').toString()).to.eql('1059'); - }); - - it('fails for negative numbers', function () { - expect(() => UnsignedHyper.fromString('-1059')).to.throw(/positive/); - }); - - it('fails when providing a string with a decimal place', function () { - expect(() => UnsignedHyper.fromString('105946095601.5')).to.throw(/bigint/); - }); -}); - -describe('UnsignedHyper overflow', function () { - it('throws when constructing with a value exceeding u64 max', function () { - const tooBig = 2n ** 64n; // one above MAX_VALUE - expect(() => new UnsignedHyper(tooBig)).to.throw( - /out of range|does not fit/i - ); - }); - - it('throws for a 300-bit bigint', function () { - const huge = 2n ** 300n; - expect(() => new UnsignedHyper(huge)).to.throw( - /out of range|does not fit/i - ); - }); - - it('throws for negative values', function () { - expect(() => new UnsignedHyper(-1n)).to.throw(/positive/); - }); - - it('accepts exact boundary values without throwing', function () { - expect(() => new UnsignedHyper(UnsignedHyper.MAX_VALUE)).to.not.throw(); - expect(() => new UnsignedHyper(UnsignedHyper.MIN_VALUE)).to.not.throw(); - }); -}); diff --git a/test/unit/unsigned-int_test.js b/test/unit/unsigned-int_test.js deleted file mode 100644 index d8ff871..0000000 --- a/test/unit/unsigned-int_test.js +++ /dev/null @@ -1,70 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; -let UnsignedInt = XDR.UnsignedInt; - -describe('UnsignedInt.read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.eql(0); - expect(read([0x00, 0x00, 0x00, 0x01])).to.eql(1); - expect(read([0xff, 0xff, 0xff, 0xff])).to.eql(Math.pow(2, 32) - 1); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return UnsignedInt.read(io); - } -}); - -describe('UnsignedInt.write', function () { - it('encodes correctly', function () { - expect(write(0)).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write(1)).to.eql([0x00, 0x00, 0x00, 0x01]); - expect(write(Math.pow(2, 32) - 1)).to.eql([0xff, 0xff, 0xff, 0xff]); - }); - - it('throws a write error if the value is not an integral number', function () { - expect(() => write(true)).to.throw(/write error/i); - expect(() => write(undefined)).to.throw(/write error/i); - expect(() => write([])).to.throw(/write error/i); - expect(() => write({})).to.throw(/write error/i); - expect(() => write(1.1)).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(8); - UnsignedInt.write(value, io); - return io.toArray(); - } -}); - -describe('UnsignedInt.isValid', function () { - it('returns true for number in a 32-bit range', function () { - expect(UnsignedInt.isValid(0)).to.be.true; - expect(UnsignedInt.isValid(1)).to.be.true; - expect(UnsignedInt.isValid(1.0)).to.be.true; - expect(UnsignedInt.isValid(Math.pow(2, 32) - 1)).to.be.true; - }); - - it('returns false for numbers outside a 32-bit range', function () { - expect(UnsignedInt.isValid(Math.pow(2, 32))).to.be.false; - expect(UnsignedInt.isValid(-1)).to.be.false; - }); - - it('returns false for non numbers', function () { - expect(UnsignedInt.isValid(true)).to.be.false; - expect(UnsignedInt.isValid(false)).to.be.false; - expect(UnsignedInt.isValid(null)).to.be.false; - expect(UnsignedInt.isValid('0')).to.be.false; - expect(UnsignedInt.isValid([])).to.be.false; - expect(UnsignedInt.isValid([0])).to.be.false; - expect(UnsignedInt.isValid('hello')).to.be.false; - expect(UnsignedInt.isValid({ why: 'hello' })).to.be.false; - expect(UnsignedInt.isValid(['how', 'do', 'you', 'do'])).to.be.false; - expect(UnsignedInt.isValid(NaN)).to.be.false; - }); - - it('returns false for non-integral values', function () { - expect(UnsignedInt.isValid(1.1)).to.be.false; - expect(UnsignedInt.isValid(0.1)).to.be.false; - }); -}); diff --git a/test/unit/var-array_test.js b/test/unit/var-array_test.js deleted file mode 100644 index a4f8a39..0000000 --- a/test/unit/var-array_test.js +++ /dev/null @@ -1,249 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -const subject = new XDR.VarArray(XDR.Int, 2); - -describe('VarArray#read', function () { - function createFixedSizeChild() { - let calls = 0; - - return { - FixedSizeChild: class FixedSizeChild { - static read(io) { - calls += 1; - return io.readInt32BE(); - } - - static write() {} - - static isValid() { - return true; - } - }, - getCalls() { - return calls; - } - }; - } - - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.eql([]); - - expect(read([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00])).to.eql([0]); - expect(read([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01])).to.eql([1]); - - expect( - read([ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - ]) - ).to.eql([0, 1]); - expect( - read([ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01 - ]) - ).to.eql([1, 1]); - }); - - it('throws read error when the encoded array is too large', function () { - expect(() => read([0x00, 0x00, 0x00, 0x03])).to.throw(/read error/i); - }); - - it('fast-fails when declared length cannot fit remaining bytes for fixed-size child', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const arr = new XDR.VarArray(FixedSizeChild, 10); - const io = new XdrReader([0x00, 0x00, 0x00, 0x02]); - const remainingAfterLengthPrefix = io.remainingBytes() - 4; - - expect(() => arr.read(io)).to.throw( - new RegExp(`exceeds remaining ${remainingAfterLengthPrefix} bytes`, 'i') - ); - expect(getCalls()).to.eql(0); - }); - - it('decodes on exact-fit payload and reads each child once', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const arr = new XDR.VarArray(FixedSizeChild, 10); - const io = new XdrReader([ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 - ]); - - expect(arr.read(io)).to.eql([1, 2]); - expect(getCalls()).to.eql(2); - }); - - it('checks maxLength before insufficient-bytes fast-fail', function () { - const { FixedSizeChild, getCalls } = createFixedSizeChild(); - - const arr = new XDR.VarArray(FixedSizeChild, 1); - const io = new XdrReader([0x00, 0x00, 0x00, 0x02]); - - expect(() => arr.read(io)).to.throw(/max allowed/i); - expect(getCalls()).to.eql(0); - }); - - it('consumes only the 4-byte length prefix on VarArray insufficient-bytes fast-fail', function () { - const { FixedSizeChild } = createFixedSizeChild(); - - const arr = new XDR.VarArray(FixedSizeChild, 10); - const io = new XdrReader([0x00, 0x00, 0x00, 0x02]); - const before = io.remainingBytes(); - const remainingAfterLengthPrefix = io.remainingBytes() - 4; - - expect(() => arr.read(io)).to.throw( - new RegExp(`exceeds remaining ${remainingAfterLengthPrefix} bytes`, 'i') - ); - expect(before - io.remainingBytes()).to.eql(4); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return subject.read(io); - } -}); - -describe('VarArray#read maxDepth', function () { - it('throws when depth exceeds maxDepth', function () { - const varArrayType = new XDR.VarArray(XDR.Int, 10, 2); - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(() => varArrayType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('succeeds when depth is within maxDepth', function () { - const varArrayType = new XDR.VarArray(XDR.Int, 10, 5); - const bytes = [ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a - ]; - const reader = new XdrReader(bytes); - - const result = varArrayType.read(reader, 4); - expect(result).to.eql([5, 10]); - }); - - it('uses default maxDepth of 200', function () { - const varArrayType = new XDR.VarArray(XDR.Int, 10); - const bytes = [0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05]; - const reader = new XdrReader(bytes); - - expect(varArrayType._maxDepth).to.equal(200); - expect(() => varArrayType.read(reader, -1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); - - it('uses the root maxDepth for child types', function () { - const innerArray = new XDR.VarArray(XDR.Int, 10, 2); - const outerArray = new XDR.VarArray(innerArray, 10, 5); - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01 - ]; - const reader = new XdrReader(bytes); - - const result = outerArray.read(reader, 2); - expect(result).to.eql([[1]]); - }); - - it('VarArray containing Strings respects depth', function () { - const stringType = new XDR.String(100); - const arrayOfStrings = new XDR.VarArray(stringType, 10, 3); - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x00 - ]; - const reader = new XdrReader(bytes); - - const result = arrayOfStrings.read(reader, 2); - expect(result.length).to.eql(1); - expect(result[0].toString('utf8')).to.eql('A'); - }); - - it('deeply nested VarArrays read at appropriate depth', function () { - const level3 = new XDR.VarArray(XDR.Int, 10, 4); - const level2 = new XDR.VarArray(level3, 10, 4); - const level1 = new XDR.VarArray(level2, 10, 4); - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01 - ]; - const reader = new XdrReader(bytes); - - const result = level1.read(reader, 2); - expect(result).to.eql([[[1]]]); - }); - - it('deeply nested VarArrays throw when depth exceeds limit', function () { - const level3 = new XDR.VarArray(XDR.Int, 10, 2); - const level2 = new XDR.VarArray(level3, 10, 2); - const level1 = new XDR.VarArray(level2, 10, 2); - - const bytes = [ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01 - ]; - const reader = new XdrReader(bytes); - - expect(() => level1.read(reader, 1)).to.throw( - /exceeded max decoding depth.*/i - ); - }); -}); - -describe('VarArray#write', function () { - it('encodes correctly', function () { - expect(write([])).to.eql([0x00, 0x00, 0x00, 0x00]); - expect(write([0])).to.eql([0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]); - expect(write([0, 1])).to.eql([ - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 - ]); - }); - - it('throws a write error if the value is too large', function () { - expect(() => write([1, 2, 3])).to.throw(/write error/i); - }); - - it('throws a write error if a child element is of the wrong type', function () { - expect(() => write([1, null])).to.throw(/write error/i); - expect(() => write([1, undefined])).to.throw(/write error/i); - expect(() => write([1, 'hi'])).to.throw(/write error/i); - }); - - function write(value) { - let io = new XdrWriter(256); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('VarArray#isValid', function () { - it('returns true for an array of the correct sizes with the correct types', function () { - expect(subject.isValid([])).to.be.true; - expect(subject.isValid([1])).to.be.true; - expect(subject.isValid([1, 2])).to.be.true; - }); - - it('returns false for arrays of the wrong size', function () { - expect(subject.isValid([1, 2, 3])).to.be.false; - }); - - it('returns false if a child element is invalid for the child type', function () { - expect(subject.isValid([1, null])).to.be.false; - expect(subject.isValid([1, undefined])).to.be.false; - expect(subject.isValid([1, 'hello'])).to.be.false; - expect(subject.isValid([1, []])).to.be.false; - expect(subject.isValid([1, {}])).to.be.false; - }); -}); - -describe('VarArray#constructor', function () { - let subject = new XDR.VarArray(XDR.Int); - - it('defaults to max length of a uint max value', function () { - expect(subject._maxLength).to.eql(Math.pow(2, 32) - 1); - }); -}); diff --git a/test/unit/var-opaque.test.ts b/test/unit/var-opaque.test.ts new file mode 100644 index 0000000..fd16ad7 --- /dev/null +++ b/test/unit/var-opaque.test.ts @@ -0,0 +1,49 @@ +import { describe, it, expect } from 'vitest'; +import { varOpaque } from '../../src/index.js'; +import { bytes, toArray, encodeInvalid } from './_helpers.js'; + +const schema = varOpaque(100); + +describe('varOpaque (variable-length)', () => { + describe('encode', () => { + it('length-prefixes and pads to a 4-byte boundary', () => { + expect(toArray(schema.encode(bytes([1, 2, 3])))).toEqual([ + 0, 0, 0, 3, 1, 2, 3, 0 + ]); + expect(toArray(schema.encode(bytes([1, 2, 3, 4])))).toEqual([ + 0, 0, 0, 4, 1, 2, 3, 4 + ]); + }); + + it('encodes empty data', () => { + expect(toArray(schema.encode(bytes([])))).toEqual([0, 0, 0, 0]); + }); + + it('throws when exceeding maxLength', () => { + expect(() => varOpaque(2).encode(bytes([1, 2, 3]))).toThrow( + /exceeds maximum/i + ); + }); + + it('throws for non-Uint8Array input', () => { + expect(() => encodeInvalid(schema, [1, 2, 3])).toThrow( + /expected Uint8Array/i + ); + }); + }); + + describe('decode', () => { + it('reads the length-prefixed payload and consumes padding', () => { + expect(toArray(schema.decode(bytes([0, 0, 0, 3, 1, 2, 3, 0])))).toEqual([ + 1, 2, 3 + ]); + expect(toArray(schema.decode(bytes([0, 0, 0, 0])))).toEqual([]); + }); + + it('throws when the declared length exceeds maxLength', () => { + expect(() => + varOpaque(2).decode(bytes([0, 0, 0, 3, 1, 2, 3, 0])) + ).toThrow(/exceeds maximum/i); + }); + }); +}); diff --git a/test/unit/var-opaque_test.js b/test/unit/var-opaque_test.js deleted file mode 100644 index ee85a8b..0000000 --- a/test/unit/var-opaque_test.js +++ /dev/null @@ -1,84 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -const VarOpaque = XDR.VarOpaque; - -let subject = new VarOpaque(2); - -describe('VarOpaque#read', function () { - it('decodes correctly', function () { - expect(read([0, 0, 0, 0])).to.eql(Buffer.from([])); - expect(read([0, 0, 0, 1, 0, 0, 0, 0])).to.eql(Buffer.from([0])); - expect(read([0, 0, 0, 1, 1, 0, 0, 0])).to.eql(Buffer.from([1])); - expect(read([0, 0, 0, 2, 0, 1, 0, 0])).to.eql(Buffer.from([0, 1])); - }); - - it('throws a read error when the encoded length is greater than the allowed max', function () { - expect(() => read([0, 0, 0, 3, 0, 0, 0, 0])).to.throw(/read error/i); - }); - - it('throws a read error if the padding bytes are not zero', function () { - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00]) - ).to.throw(/read error/i); - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x01, 0x00]) - ).to.throw(/read error/i); - expect(() => - read([0x00, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01]) - ).to.throw(/read error/i); - }); - - function read(bytes) { - let io = new XdrReader(bytes); - const res = subject.read(io); - expect(io._index).to.eql( - !res.length ? 4 : 8, - 'padding not processed by the reader' - ); - return res; - } -}); - -describe('VarOpaque#write', function () { - it('encodes correctly', function () { - expect(write(Buffer.from([]))).to.eql([0, 0, 0, 0]); - expect(write(Buffer.from([0]))).to.eql([0, 0, 0, 1, 0, 0, 0, 0]); - expect(write(Buffer.from([1]))).to.eql([0, 0, 0, 1, 1, 0, 0, 0]); - expect(write(Buffer.from([0, 1]))).to.eql([0, 0, 0, 2, 0, 1, 0, 0]); - }); - - function write(value) { - let io = new XdrWriter(8); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('VarOpaque#isValid', function () { - it('returns true for buffers of the correct length', function () { - expect(subject.isValid(Buffer.alloc(0))).to.be.true; - expect(subject.isValid(Buffer.alloc(1))).to.be.true; - expect(subject.isValid(Buffer.alloc(2))).to.be.true; - }); - - it('returns false for buffers of the wrong size', function () { - expect(subject.isValid(Buffer.alloc(3))).to.be.false; - expect(subject.isValid(Buffer.alloc(3000))).to.be.false; - }); - - it('returns false for non buffers', function () { - expect(subject.isValid(true)).to.be.false; - expect(subject.isValid(null)).to.be.false; - expect(subject.isValid(3)).to.be.false; - expect(subject.isValid([0])).to.be.false; - }); -}); - -describe('VarOpaque#constructor', function () { - let subject = new XDR.VarOpaque(); - - it('defaults to max length of a uint max value', function () { - expect(subject._maxLength).to.eql(Math.pow(2, 32) - 1); - }); -}); diff --git a/test/unit/void.test.ts b/test/unit/void.test.ts new file mode 100644 index 0000000..1e7ec8a --- /dev/null +++ b/test/unit/void.test.ts @@ -0,0 +1,26 @@ +import { describe, it, expect } from 'vitest'; +import { void as voidType } from '../../src/index.js'; +import { bytes, toArray, encodeInvalid } from './_helpers.js'; + +const schema = voidType(); + +describe('void', () => { + it('encodes to zero bytes', () => { + expect(toArray(schema.encode(undefined))).toEqual([]); + }); + + it('decodes empty input to undefined', () => { + expect(schema.decode(bytes([]))).toBeUndefined(); + }); + + it('throws when encoding a non-undefined value', () => { + expect(() => encodeInvalid(schema, null)).toThrow(/expected void/i); + expect(() => encodeInvalid(schema, 0)).toThrow(/expected void/i); + }); + + it('validates only undefined', () => { + expect(schema.validate(undefined)).toBe(true); + expect(schema.validate(null)).toBe(false); + expect(schema.validate(0)).toBe(false); + }); +}); diff --git a/test/unit/void_test.js b/test/unit/void_test.js deleted file mode 100644 index 08dc20a..0000000 --- a/test/unit/void_test.js +++ /dev/null @@ -1,44 +0,0 @@ -import { XdrReader } from '../../src/serialization/xdr-reader'; -import { XdrWriter } from '../../src/serialization/xdr-writer'; - -let subject = XDR.Void; - -describe('Void#read', function () { - it('decodes correctly', function () { - expect(read([0x00, 0x00, 0x00, 0x00])).to.be.undefined; - expect(read([0x00, 0x00, 0x00, 0x01])).to.be.undefined; - expect(read([0x00, 0x00, 0x00, 0x02])).to.be.undefined; - }); - - function read(bytes) { - let io = new XdrReader(bytes); - return subject.read(io); - } -}); - -describe('Void#write', function () { - it('encodes correctly', function () { - expect(write(undefined)).to.eql([]); - }); - - function write(value) { - let io = new XdrWriter(8); - subject.write(value, io); - return io.toArray(); - } -}); - -describe('Void#isValid', function () { - it('returns true undefined', function () { - expect(subject.isValid(undefined)).to.be.true; - }); - - it('returns false for anything defined', function () { - expect(subject.isValid(null)).to.be.false; - expect(subject.isValid(false)).to.be.false; - expect(subject.isValid(1)).to.be.false; - expect(subject.isValid('aaa')).to.be.false; - expect(subject.isValid({})).to.be.false; - expect(subject.isValid([undefined])).to.be.false; - }); -}); diff --git a/test/unit/writer.test.ts b/test/unit/writer.test.ts new file mode 100644 index 0000000..1736e08 --- /dev/null +++ b/test/unit/writer.test.ts @@ -0,0 +1,55 @@ +import { describe, it, expect } from 'vitest'; +import { Writer } from '../../src/index.js'; +import { bytes, toArray } from './_helpers.js'; + +describe('Writer', () => { + it('writes big-endian fixed-width integers', () => { + const writer = new Writer(); + writer.writeInt32(-1); + writer.writeUint32(255); + expect(toArray(writer.toUint8Array())).toEqual([ + 255, 255, 255, 255, 0, 0, 0, 255 + ]); + }); + + it('writes big-endian 64-bit integers', () => { + const writer = new Writer(); + writer.writeBigInt64(-1n); + writer.writeBigUint64(1n); + expect(toArray(writer.toUint8Array())).toEqual([ + 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 1 + ]); + }); + + it('writes IEEE-754 floats', () => { + const writer = new Writer(); + writer.writeFloat32(1); + writer.writeFloat64(1); + expect(toArray(writer.toUint8Array())).toEqual([ + 63, 128, 0, 0, 63, 240, 0, 0, 0, 0, 0, 0 + ]); + }); + + it('appends raw byte chunks in order', () => { + const writer = new Writer(); + writer.writeBytes(bytes([1, 2, 3])); + writer.writeBytes(bytes([4])); + expect(toArray(writer.toUint8Array())).toEqual([1, 2, 3, 4]); + }); + + it('pads to the next 4-byte boundary based on length', () => { + const cases: Array<[number, number[]]> = [ + [0, []], + [1, [0, 0, 0]], + [2, [0, 0]], + [3, [0]], + [4, []], + [5, [0, 0, 0]] + ]; + for (const [length, expected] of cases) { + const writer = new Writer(); + writer.writePadding(length); + expect(toArray(writer.toUint8Array())).toEqual(expected); + } + }); +}); From 520e22961734a696696afc41792b2889ddbcedfb Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 12:26:00 -0700 Subject: [PATCH 03/22] feat: modernize build chain and package configs --- .eslintrc.js | 10 - babel.config.json | 16 - eslint.config.mjs | 24 + karma.conf.js | 45 - package.json | 91 +- pnpm-lock.yaml | 6089 +++++++++++---------------------------------- rollup.config.mjs | 25 + test/.eslintrc.js | 19 - test/setup.js | 23 - tsconfig.json | 18 + vitest.config.ts | 7 + webpack.config.js | 57 - 12 files changed, 1593 insertions(+), 4831 deletions(-) delete mode 100644 .eslintrc.js delete mode 100644 babel.config.json create mode 100644 eslint.config.mjs delete mode 100644 karma.conf.js create mode 100644 rollup.config.mjs delete mode 100644 test/.eslintrc.js delete mode 100644 test/setup.js create mode 100644 tsconfig.json create mode 100644 vitest.config.ts delete mode 100644 webpack.config.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index b36e0ae..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - env: { - node: true - }, - extends: ['eslint:recommended', 'plugin:node/recommended'], - rules: { - 'node/no-unpublished-require': 0, - indent: ['warn', 2] - } -}; diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index e2b47ec..0000000 --- a/babel.config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "browsers": [ - "> 2%", - "not ie 11", - "not op_mini all" - ] - } - } - ] - ] -} \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..a34c701 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,24 @@ +import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import prettier from 'eslint-config-prettier'; + +export default tseslint.config( + { ignores: ['dist/**', 'lib/**', 'generated/**', 'coverage/**'] }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + rules: { + // TypeScript's own checker covers undefined identifiers/globals, and the + // rule otherwise flags platform globals (TextEncoder, DataView, …). + 'no-undef': 'off', + // `{}` is used intentionally in the union type algebra to mean "adds no + // properties" (the void-arm branch of a conditional type). + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { argsIgnorePattern: '^_', varsIgnorePattern: '^_' } + ] + } + }, + prettier +); diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 9ced768..0000000 --- a/karma.conf.js +++ /dev/null @@ -1,45 +0,0 @@ -const webpack = require('webpack'); - -module.exports = function (config) { - config.set({ - frameworks: ['mocha', 'webpack', 'sinon-chai'], - browsers: ['FirefoxHeadless', 'ChromeHeadless'], - browserNoActivityTimeout: 20000, - - plugins: [ - 'karma-mocha', - 'karma-webpack', - 'karma-sinon-chai', - 'karma-chrome-launcher', - 'karma-firefox-launcher' - ], - - files: ['dist/xdr.js', 'test/unit/**/*.js'], - - preprocessors: { - 'test/unit/**/*.js': ['webpack'] - }, - - webpack: { - mode: 'development', - module: { - rules: [ - { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' } - ] - }, - plugins: [ - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'] - }) - ] - }, - - webpackMiddleware: { - noInfo: true - }, - - singleRun: true, - - reporters: ['dots'] - }); -}; diff --git a/package.json b/package.json index f310139..be0c596 100644 --- a/package.json +++ b/package.json @@ -6,20 +6,36 @@ "node": ">=20.0.0", "pnpm": ">=9.0.0" }, - "main": "lib/xdr.js", - "browser": "dist/xdr.js", - "module": "src/index.js", + "main": "./dist/js-xdr.cjs", + "module": "./dist/js-xdr.mjs", + "types": "./dist/js-xdr.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/js-xdr.d.ts", + "default": "./dist/js-xdr.mjs" + }, + "require": { + "types": "./dist/js-xdr.d.ts", + "default": "./dist/js-xdr.cjs" + } + }, + "./package.json": "./package.json" + }, + "files": [ + "dist" + ], + "sideEffects": false, "scripts": { - "build": "pnpm run build:browser && pnpm run build:node", - "build:browser": "webpack --mode=production --config ./webpack.config.js", - "build:node": "webpack --mode=development --config ./webpack.config.js", - "test:node": "pnpm run build:node && mocha", - "test:browser": "pnpm run build:browser && karma start", - "test": "pnpm run test:node && pnpm run test:browser", + "build": "pnpm run clean && rollup -c rollup.config.mjs", + "test": "vitest run", + "test:watch": "vitest", + "lint": "eslint .", + "typecheck": "tsc --noEmit", "test-generate": "bundle exec xdrgen -o generated -n test -l javascript examples/test.x", - "fmt": "prettier --write '**/*.js'", + "fmt": "prettier --write '**/*.{js,ts,json}'", "prepare": "pnpm build", - "clean": "rm -rf lib/ dist/" + "clean": "rm -rf dist" }, "repository": { "type": "git", @@ -33,47 +49,28 @@ }, "homepage": "https://github.com/stellar/js-xdr", "lint-staged": { - "**/*.{js,json}": [ - "pnpm fmt" - ] - }, - "mocha": { - "require": [ - "@babel/register", - "./test/setup.js" + "**/*.ts": [ + "eslint --fix", + "prettier --write" ], - "recursive": true, - "ui": "bdd" + "**/*.{js,mjs,json}": [ + "prettier --write" + ] }, "devDependencies": { - "@babel/core": "^7.24.9", - "@babel/eslint-parser": "^7.24.8", - "@babel/preset-env": "^7.24.8", - "@babel/register": "^7.24.6", - "babel-loader": "^9.1.3", - "buffer": "^6.0.3", - "chai": "^4.3.10", - "eslint": "^8.57.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prefer-import": "^0.0.1", - "eslint-plugin-prettier": "^4.2.1", + "@eslint/js": "^9.39.4", + "@types/node": "^20.12.0", + "esbuild": "^0.27.1", + "eslint": "^9.39.4", + "eslint-config-prettier": "^9.1.2", "husky": "^8.0.3", - "karma": "^6.4.3", - "karma-chrome-launcher": "^3.2.0", - "karma-firefox-launcher": "^2.1.3", - "karma-mocha": "^2.0.1", - "karma-sinon-chai": "^2.0.2", - "karma-webpack": "^5.0.1", "lint-staged": "13.2.2", - "mocha": "^10.6.0", "prettier": "^2.8.7", - "sinon": "^15.2.0", - "sinon-chai": "^3.7.0", - "terser-webpack-plugin": "^5.3.10", - "webpack": "^5.93.0", - "webpack-cli": "^5.0.2" + "rollup": "^4.53.3", + "rollup-plugin-dts": "^6.4.1", + "rollup-plugin-esbuild": "^6.2.1", + "typescript": "^5.6.0", + "typescript-eslint": "^8.60.0", + "vitest": "^1.6.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c26f9f5..45fee2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,1002 +8,734 @@ importers: .: devDependencies: - '@babel/core': - specifier: ^7.24.9 - version: 7.28.6 - '@babel/eslint-parser': - specifier: ^7.24.8 - version: 7.28.6(@babel/core@7.28.6)(eslint@8.57.1) - '@babel/preset-env': - specifier: ^7.24.8 - version: 7.28.6(@babel/core@7.28.6) - '@babel/register': - specifier: ^7.24.6 - version: 7.28.6(@babel/core@7.28.6) - babel-loader: - specifier: ^9.1.3 - version: 9.2.1(@babel/core@7.28.6)(webpack@5.104.1) - buffer: - specifier: ^6.0.3 - version: 6.0.3 - chai: - specifier: ^4.3.10 - version: 4.5.0 + '@eslint/js': + specifier: ^9.39.4 + version: 9.39.4 + '@types/node': + specifier: ^20.12.0 + version: 20.19.41 + esbuild: + specifier: ^0.27.1 + version: 0.27.7 eslint: - specifier: ^8.57.0 - version: 8.57.1 - eslint-config-airbnb-base: - specifier: ^15.0.0 - version: 15.0.0(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1) + specifier: ^9.39.4 + version: 9.39.4 eslint-config-prettier: - specifier: ^8.8.0 - version: 8.10.2(eslint@8.57.1) - eslint-plugin-import: - specifier: ^2.29.1 - version: 2.32.0(eslint@8.57.1) - eslint-plugin-node: - specifier: ^11.1.0 - version: 11.1.0(eslint@8.57.1) - eslint-plugin-prefer-import: - specifier: ^0.0.1 - version: 0.0.1 - eslint-plugin-prettier: - specifier: ^4.2.1 - version: 4.2.5(eslint-config-prettier@8.10.2(eslint@8.57.1))(eslint@8.57.1)(prettier@2.8.8) + specifier: ^9.1.2 + version: 9.1.2(eslint@9.39.4) husky: specifier: ^8.0.3 version: 8.0.3 - karma: - specifier: ^6.4.3 - version: 6.4.4 - karma-chrome-launcher: - specifier: ^3.2.0 - version: 3.2.0 - karma-firefox-launcher: - specifier: ^2.1.3 - version: 2.1.3 - karma-mocha: - specifier: ^2.0.1 - version: 2.0.1 - karma-sinon-chai: - specifier: ^2.0.2 - version: 2.0.2(chai@4.5.0)(sinon-chai@3.7.0(chai@4.5.0)(sinon@15.2.0))(sinon@15.2.0) - karma-webpack: - specifier: ^5.0.1 - version: 5.0.1(webpack@5.104.1) lint-staged: specifier: 13.2.2 version: 13.2.2 - mocha: - specifier: ^10.6.0 - version: 10.8.2 prettier: specifier: ^2.8.7 version: 2.8.8 - sinon: - specifier: ^15.2.0 - version: 15.2.0 - sinon-chai: - specifier: ^3.7.0 - version: 3.7.0(chai@4.5.0)(sinon@15.2.0) - terser-webpack-plugin: - specifier: ^5.3.10 - version: 5.3.16(webpack@5.104.1) - webpack: - specifier: ^5.93.0 - version: 5.104.1(webpack-cli@5.1.4) - webpack-cli: - specifier: ^5.0.2 - version: 5.1.4(webpack@5.104.1) + rollup: + specifier: ^4.53.3 + version: 4.60.4 + rollup-plugin-dts: + specifier: ^6.4.1 + version: 6.4.1(rollup@4.60.4)(typescript@5.9.3) + rollup-plugin-esbuild: + specifier: ^6.2.1 + version: 6.2.1(esbuild@0.27.7)(rollup@4.60.4) + typescript: + specifier: ^5.6.0 + version: 5.9.3 + typescript-eslint: + specifier: ^8.60.0 + version: 8.60.0(eslint@9.39.4)(typescript@5.9.3) + vitest: + specifier: ^1.6.0 + version: 1.6.1(@types/node@20.19.41)(terser@5.46.0) packages: - '@babel/code-frame@7.28.6': - resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.28.6': - resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/core@7.28.6': - resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} - engines: {node: '>=6.9.0'} + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] - '@babel/eslint-parser@7.28.6': - resolution: {integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] - '@babel/generator@7.28.6': - resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} - engines: {node: '>=6.9.0'} + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] - '@babel/helper-annotate-as-pure@7.27.3': - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} - engines: {node: '>=6.9.0'} + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] - '@babel/helper-create-class-features-plugin@7.28.6': - resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] - '@babel/helper-create-regexp-features-plugin@7.28.5': - resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] - '@babel/helper-define-polyfill-provider@0.6.5': - resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] - '@babel/helper-member-expression-to-functions@7.28.5': - resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} - engines: {node: '>=6.9.0'} + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] - '@babel/helper-optimise-call-expression@7.27.1': - resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} - engines: {node: '>=6.9.0'} + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] - '@babel/helper-remap-async-to-generator@7.27.1': - resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] - '@babel/helper-replace-supers@7.28.6': - resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] - '@babel/helper-skip-transparent-expression-wrappers@7.27.1': - resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] - '@babel/helper-wrap-function@7.28.6': - resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] - '@babel/helpers@7.28.6': - resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] - '@babel/parser@7.28.6': - resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} - engines: {node: '>=6.0.0'} - hasBin: true + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': - resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': - resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': - resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': - resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': - resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] - '@babel/plugin-syntax-import-assertions@7.28.6': - resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] - '@babel/plugin-syntax-import-attributes@7.28.6': - resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] - '@babel/plugin-syntax-unicode-sets-regex@7.18.6': - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] - '@babel/plugin-transform-arrow-functions@7.27.1': - resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] - '@babel/plugin-transform-async-generator-functions@7.28.6': - resolution: {integrity: sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] - '@babel/plugin-transform-async-to-generator@7.28.6': - resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] - '@babel/plugin-transform-block-scoped-functions@7.27.1': - resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] - '@babel/plugin-transform-block-scoping@7.28.6': - resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] - '@babel/plugin-transform-class-properties@7.28.6': - resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] - '@babel/plugin-transform-class-static-block@7.28.6': - resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] - '@babel/plugin-transform-classes@7.28.6': - resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] - '@babel/plugin-transform-computed-properties@7.28.6': - resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} - engines: {node: '>=6.9.0'} + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - '@babel/core': ^7.0.0-0 + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@babel/plugin-transform-destructuring@7.28.5': - resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@babel/plugin-transform-dotall-regex@7.28.6': - resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-duplicate-keys@7.27.1': - resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.28.6': - resolution: {integrity: sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-dynamic-import@7.27.1': - resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-explicit-resource-management@7.28.6': - resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-exponentiation-operator@7.28.6': - resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-export-namespace-from@7.27.1': - resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-for-of@7.27.1': - resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} - '@babel/plugin-transform-function-name@7.27.1': - resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} - '@babel/plugin-transform-json-strings@7.28.6': - resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} - '@babel/plugin-transform-literals@7.27.1': - resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} - '@babel/plugin-transform-logical-assignment-operators@7.28.6': - resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} - '@babel/plugin-transform-member-expression-literals@7.27.1': - resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@babel/plugin-transform-modules-amd@7.27.1': - resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@babel/plugin-transform-modules-commonjs@7.28.6': - resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - '@babel/plugin-transform-modules-systemjs@7.28.5': - resolution: {integrity: sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} - '@babel/plugin-transform-modules-umd@7.27.1': - resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': - resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@babel/plugin-transform-new-target@7.27.1': - resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': - resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@rollup/rollup-android-arm-eabi@4.60.4': + resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} + cpu: [arm] + os: [android] - '@babel/plugin-transform-numeric-separator@7.28.6': - resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@rollup/rollup-android-arm64@4.60.4': + resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==} + cpu: [arm64] + os: [android] - '@babel/plugin-transform-object-rest-spread@7.28.6': - resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@rollup/rollup-darwin-arm64@4.60.4': + resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==} + cpu: [arm64] + os: [darwin] - '@babel/plugin-transform-object-super@7.27.1': - resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@rollup/rollup-darwin-x64@4.60.4': + resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==} + cpu: [x64] + os: [darwin] - '@babel/plugin-transform-optional-catch-binding@7.28.6': - resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@rollup/rollup-freebsd-arm64@4.60.4': + resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.4': + resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.60.4': + resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.60.4': + resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.60.4': + resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.4': + resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.4': + resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.60.4': + resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.60.4': + resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.60.4': + resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.60.4': + resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.60.4': + resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.4': + resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.4': + resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.4': + resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.4': + resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.4': + resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} - '@babel/plugin-transform-optional-chaining@7.28.6': - resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@babel/plugin-transform-parameters@7.27.7': - resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@babel/plugin-transform-private-methods@7.28.6': - resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@types/node@20.19.41': + resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} - '@babel/plugin-transform-private-property-in-object@7.28.6': - resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/eslint-plugin@8.60.0': + resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + '@typescript-eslint/parser': ^8.60.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-property-literals@7.27.1': - resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/parser@8.60.0': + resolution: {integrity: sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-regenerator@7.28.6': - resolution: {integrity: sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/project-service@8.60.0': + resolution: {integrity: sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-regexp-modifiers@7.28.6': - resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@typescript-eslint/scope-manager@8.60.0': + resolution: {integrity: sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-reserved-words@7.27.1': - resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/tsconfig-utils@8.60.0': + resolution: {integrity: sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-shorthand-properties@7.27.1': - resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/type-utils@8.60.0': + resolution: {integrity: sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-spread@7.28.6': - resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@typescript-eslint/types@8.60.0': + resolution: {integrity: sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-sticky-regex@7.27.1': - resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/typescript-estree@8.60.0': + resolution: {integrity: sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-template-literals@7.27.1': - resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} - engines: {node: '>=6.9.0'} + '@typescript-eslint/utils@8.60.0': + resolution: {integrity: sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@babel/core': ^7.0.0-0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@babel/plugin-transform-typeof-symbol@7.27.1': - resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@typescript-eslint/visitor-keys@8.60.0': + resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@babel/plugin-transform-unicode-escapes@7.27.1': - resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@vitest/expect@1.6.1': + resolution: {integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==} - '@babel/plugin-transform-unicode-property-regex@7.28.6': - resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@vitest/runner@1.6.1': + resolution: {integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==} - '@babel/plugin-transform-unicode-regex@7.27.1': - resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@vitest/snapshot@1.6.1': + resolution: {integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==} - '@babel/plugin-transform-unicode-sets-regex@7.28.6': - resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@vitest/spy@1.6.1': + resolution: {integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==} - '@babel/preset-env@7.28.6': - resolution: {integrity: sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@vitest/utils@1.6.1': + resolution: {integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==} - '@babel/preset-modules@0.1.6-no-external-plugins': - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - '@babel/register@7.28.6': - resolution: {integrity: sha512-pgcbbEl/dWQYb6L6Yew6F94rdwygfuv+vJ/tXfwIOYAfPB6TNWpXUMEtEq3YuTeHRdvMIhvz13bkT9CNaS+wqA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true - '@babel/traverse@7.28.6': - resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} - engines: {node: '>=6.9.0'} + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true - '@babel/types@7.28.6': - resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} - engines: {node: '>=6.9.0'} + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} - '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - '@discoveryjs/json-ext@0.5.7': - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} - '@eslint/js@8.57.1': - resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} - '@humanwhocodes/config-array@0.13.0': - resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/source-map@0.3.11': - resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@rtsao/scc@1.1.0': - resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - - '@sinonjs/fake-timers@11.3.1': - resolution: {integrity: sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==} - - '@sinonjs/samsam@8.0.3': - resolution: {integrity: sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==} - - '@sinonjs/text-encoding@0.7.3': - resolution: {integrity: sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==} - - '@socket.io/component-emitter@3.1.2': - resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} - - '@types/cors@2.8.19': - resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} - - '@types/eslint-scope@3.7.7': - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - - '@types/eslint@9.6.1': - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - - '@types/node@25.0.9': - resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} - - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - - '@webassemblyjs/ast@1.14.1': - resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - - '@webassemblyjs/floating-point-hex-parser@1.13.2': - resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - - '@webassemblyjs/helper-api-error@1.13.2': - resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - - '@webassemblyjs/helper-buffer@1.14.1': - resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - - '@webassemblyjs/helper-numbers@1.13.2': - resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': - resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - - '@webassemblyjs/helper-wasm-section@1.14.1': - resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - - '@webassemblyjs/ieee754@1.13.2': - resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - - '@webassemblyjs/leb128@1.13.2': - resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - - '@webassemblyjs/utf8@1.13.2': - resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - - '@webassemblyjs/wasm-edit@1.14.1': - resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - - '@webassemblyjs/wasm-gen@1.14.1': - resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - - '@webassemblyjs/wasm-opt@1.14.1': - resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - - '@webassemblyjs/wasm-parser@1.14.1': - resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - - '@webassemblyjs/wast-printer@1.14.1': - resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - - '@webpack-cli/configtest@2.1.1': - resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - - '@webpack-cli/info@2.0.2': - resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - - '@webpack-cli/serve@2.0.5': - resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - webpack-dev-server: '*' - peerDependenciesMeta: - webpack-dev-server: - optional: true - - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - - accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - - acorn-import-phases@1.0.4: - resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} - engines: {node: '>=10.13.0'} - peerDependencies: - acorn: ^8.14.0 - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv-keywords@5.1.0: - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - - ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - - array-includes@3.1.9: - resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} - engines: {node: '>= 0.4'} - - array.prototype.findlastindex@1.2.6: - resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} - engines: {node: '>= 0.4'} - - array.prototype.flat@1.3.3: - resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} - engines: {node: '>= 0.4'} - - array.prototype.flatmap@1.3.3: - resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} - engines: {node: '>= 0.4'} - - arraybuffer.prototype.slice@1.0.4: - resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} - engines: {node: '>= 0.4'} - - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - babel-loader@9.2.1: - resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} - engines: {node: '>= 14.15.0'} - peerDependencies: - '@babel/core': ^7.12.0 - webpack: '>=5' - - babel-plugin-polyfill-corejs2@0.4.14: - resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-corejs3@0.13.0: - resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - babel-plugin-polyfill-regenerator@0.6.5: - resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - base64id@2.0.0: - resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} - engines: {node: ^4.5.0 || >= 5.9} - - baseline-browser-mapping@2.9.15: - resolution: {integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==} - hasBin: true - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - body-parser@1.20.4: - resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - caniuse-lite@1.0.30001764: - resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==} - chai@4.5.0: resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} @@ -1019,14 +751,6 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} - clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -1043,13 +767,6 @@ packages: resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1067,79 +784,19 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - common-path-prefix@3.0.0: - resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confusing-browser-globals@1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - - connect@3.7.0: - resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} - engines: {node: '>= 0.10.0'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - - core-js-compat@3.47.0: - resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} - - cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - custom-event@1.0.1: - resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} - - data-view-buffer@1.0.2: - resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} - engines: {node: '>= 0.4'} - - data-view-byte-length@1.0.2: - resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} - engines: {node: '>= 0.4'} - - data-view-byte-offset@1.0.1: - resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} - engines: {node: '>= 0.4'} - - date-format@4.0.14: - resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} - engines: {node: '>=4.0'} - - debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1149,10 +806,6 @@ packages: supports-color: optional: true - decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - deep-eql@4.1.4: resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} @@ -1160,508 +813,192 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - di@0.0.1: - resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} - - diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - - dom-serialize@2.2.1: - resolution: {integrity: sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - - engine.io-parser@5.2.3: - resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} - engines: {node: '>=10.0.0'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - engine.io@6.6.5: - resolution: {integrity: sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==} - engines: {node: '>=10.2.0'} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true - enhanced-resolve@5.18.4: - resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} - engines: {node: '>=10.13.0'} + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true - ent@2.2.2: - resolution: {integrity: sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==} - engines: {node: '>= 0.4'} + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} - envinfo@7.21.0: - resolution: {integrity: sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==} - engines: {node: '>=4'} + eslint-config-prettier@9.1.2: + resolution: {integrity: sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==} hasBin: true + peerDependencies: + eslint: '>=7.0.0' - es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} - engines: {node: '>= 0.4'} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - es-shim-unscopables@1.1.0: - resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} - engines: {node: '>= 0.4'} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-airbnb-base@15.0.0: - resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} - engines: {node: ^10.12.0 || >=12.0.0} - peerDependencies: - eslint: ^7.32.0 || ^8.2.0 - eslint-plugin-import: ^2.25.2 - - eslint-config-prettier@8.10.2: - resolution: {integrity: sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - - eslint-module-utils@2.12.1: - resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-es@3.0.1: - resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=4.19.1' - - eslint-plugin-import@2.32.0: - resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - - eslint-plugin-node@11.1.0: - resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} - engines: {node: '>=8.10.0'} - peerDependencies: - eslint: '>=5.16.0' - - eslint-plugin-prefer-import@0.0.1: - resolution: {integrity: sha512-2OKD3Bjgqkn0BvEGRwpEDhjXPSXvT3CXmWIrIavwafOkQE8FLTvFybEBT9dm7P0kHnjlNGv1AfNsL/i/GNDNHA==} - - eslint-plugin-prettier@4.2.5: - resolution: {integrity: sha512-9Ni+xgemM2IWLq6aXEpP2+V/V30GeA/46Ar629vcMqVPodFFWC9skHu/D1phvuqtS8bJCFnNf01/qcmqYEwNfg==} - engines: {node: '>=12.0.0'} - peerDependencies: - eslint: '>=7.28.0' - eslint-config-prettier: '*' - prettier: '>=2.0.0' - peerDependenciesMeta: - eslint-config-prettier: - optional: true - - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-utils@2.1.0: - resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} - engines: {node: '>=6'} - - eslint-visitor-keys@1.3.0: - resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} - engines: {node: '>=4'} - - eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.57.1: - resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. - hasBin: true - - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - execa@7.2.0: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - - fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - - fastq@1.20.1: - resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - - find-cache-dir@2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - - find-cache-dir@4.0.0: - resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} - engines: {node: '>=14.16'} - - find-up@3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - find-up@6.3.0: - resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - - fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - engines: {node: '>= 0.4'} - - functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - - generator-function@2.0.1: - resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} - engines: {node: '>= 0.4'} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-symbol-description@1.1.0: - resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} - engines: {node: '>= 0.4'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + get-tsconfig@4.14.0: + resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-bigints@1.1.0: - resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} - engines: {node: '>= 0.4'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.2.0: - resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - - http-proxy@1.18.1: - resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} - engines: {node: '>=8.0.0'} - human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + husky@8.0.3: resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} engines: {node: '>=14'} hasBin: true - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1670,70 +1007,10 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - interpret@3.1.1: - resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} - engines: {node: '>=10.13.0'} - - is-array-buffer@3.0.5: - resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} - engines: {node: '>= 0.4'} - - is-async-function@2.1.1: - resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} - engines: {node: '>= 0.4'} - - is-bigint@1.1.0: - resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} - engines: {node: '>= 0.4'} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} - - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-data-view@1.0.2: - resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} - engines: {node: '>= 0.4'} - - is-date-object@1.1.0: - resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} - engines: {node: '>= 0.4'} - - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-finalizationregistry@1.1.1: - resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} - engines: {node: '>= 0.4'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -1742,184 +1019,43 @@ packages: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - is-generator-function@1.1.2: - resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} - engines: {node: '>= 0.4'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - - is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - - is-number-object@1.1.1: - resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} - engines: {node: '>= 0.4'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - - is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - - is-regex@1.2.1: - resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} - engines: {node: '>= 0.4'} - - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - - is-shared-array-buffer@1.0.4: - resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} - engines: {node: '>= 0.4'} - is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-string@1.1.1: - resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} - engines: {node: '>= 0.4'} - - is-symbol@1.1.1: - resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} - engines: {node: '>= 0.4'} - - is-typed-array@1.1.15: - resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} - engines: {node: '>= 0.4'} - - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - - is-weakref@1.1.1: - resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} - engines: {node: '>= 0.4'} - - is-weakset@2.0.4: - resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} - engines: {node: '>= 0.4'} - - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - - isbinaryfile@4.0.10: - resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} - engines: {node: '>= 8.0.0'} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - - just-extend@6.2.0: - resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} - - karma-chrome-launcher@3.2.0: - resolution: {integrity: sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==} - - karma-firefox-launcher@2.1.3: - resolution: {integrity: sha512-LMM2bseebLbYjODBOVt7TCPP9OI2vZIXCavIXhkO9m+10Uj5l7u/SKoeRmYx8FYHTVGZSpk6peX+3BMHC1WwNw==} - - karma-mocha@2.0.1: - resolution: {integrity: sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==} - - karma-sinon-chai@2.0.2: - resolution: {integrity: sha512-SDgh6V0CUd+7ruL1d3yG6lFzmJNGRNQuEuCYXLaorruNP9nwQfA7hpsp4clx4CbOo5Gsajh3qUOT7CrVStUKMw==} - peerDependencies: - chai: '>=3.5.0' - sinon: '>=2.1.0' - sinon-chai: '>=2.9.0' - - karma-webpack@5.0.1: - resolution: {integrity: sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ==} - engines: {node: '>= 18'} - peerDependencies: - webpack: ^5.0.0 - - karma@6.4.4: - resolution: {integrity: sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==} - engines: {node: '>= 10'} - hasBin: true - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1942,64 +1078,26 @@ packages: enquirer: optional: true - loader-runner@4.3.1: - resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} - engines: {node: '>=6.11.5'} - - locate-path@3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + local-pkg@0.5.1: + resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} + engines: {node: '>=14'} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - log-update@4.0.0: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} engines: {node: '>=10'} - log4js@6.9.1: - resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} - engines: {node: '>=8.0'} - loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -2008,19 +1106,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -2029,51 +1114,27 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} - mocha@10.8.2: - resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} - engines: {node: '>= 14.0.0'} - hasBin: true + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - nise@5.1.9: - resolution: {integrity: sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==} - - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2082,49 +1143,10 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - - object.assign@4.1.7: - resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} - engines: {node: '>= 0.4'} - - object.entries@1.1.9: - resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} - engines: {node: '>= 0.4'} - - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.1: - resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} - engines: {node: '>= 0.4'} - - on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -2137,70 +1159,30 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - p-locate@3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - p-map@4.0.0: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2209,11 +1191,11 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - path-to-regexp@6.3.0: - resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} @@ -2225,217 +1207,83 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true - pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - - pkg-dir@3.0.0: - resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} - engines: {node: '>=6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - pkg-dir@7.0.0: - resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} - engines: {node: '>=14.16'} - - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-linter-helpers@1.0.1: - resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} - engines: {node: '>=6.0.0'} - prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true - punycode@1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qjobs@1.2.0: - resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} - engines: {node: '>=0.9'} - - qs@6.14.1: - resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} - engines: {node: '>=0.6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} - engines: {node: '>= 0.8'} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - rechoir@0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - - regenerate-unicode-properties@10.2.2: - resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} - engines: {node: '>=4'} - - regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - - regexpp@3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - - regexpu-core@6.4.0: - resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} - engines: {node: '>=4'} - - regjsgen@0.8.0: - resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - - regjsparser@0.13.0: - resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} - hasBin: true - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true + rollup-plugin-dts@6.4.1: + resolution: {integrity: sha512-l//F3Zf7ID5GoOfLfD8kroBjQKEKpy1qfhtAdnpibFZMffPaylrg1CoDC2vGkPeTeyxUe4bVFCln2EFuL7IGGg==} + engines: {node: '>=20'} + peerDependencies: + rollup: ^3.29.4 || ^4 + typescript: ^4.5 || ^5.0 || ^6.0 + + rollup-plugin-esbuild@6.2.1: + resolution: {integrity: sha512-jTNOMGoMRhs0JuueJrJqbW8tOwxumaWYq+V5i+PD+8ecSCVkuX27tGW7BXqDgoULQ55rO7IdNxPcnsWtshz3AA==} + engines: {node: '>=14.18.0'} + peerDependencies: + esbuild: '>=0.18.0' + rollup: ^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rollup@4.60.4: + resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safe-push-apply@1.0.0: - resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} - engines: {node: '>= 0.4'} - - safe-regex-test@1.1.0: - resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} - engines: {node: '>= 0.4'} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - schema-utils@4.3.3: - resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} - engines: {node: '>= 10.13.0'} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + semver@7.8.1: + resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} + engines: {node: '>=10'} hasBin: true - serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - - set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - - set-proto@1.0.0: - resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} - engines: {node: '>= 0.4'} - - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - - shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2444,34 +1292,15 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - sinon-chai@3.7.0: - resolution: {integrity: sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==} - peerDependencies: - chai: ^4.0.0 - sinon: '>=4.0.0' - - sinon@15.2.0: - resolution: {integrity: sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==} - deprecated: 16.1.1 + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} @@ -2485,16 +1314,9 @@ packages: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} - socket.io-adapter@2.5.6: - resolution: {integrity: sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==} - - socket.io-parser@4.2.5: - resolution: {integrity: sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==} - engines: {node: '>=10.0.0'} - - socket.io@4.8.3: - resolution: {integrity: sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==} - engines: {node: '>=10.2.0'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -2503,21 +1325,11 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - streamroller@3.1.5: - resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} - engines: {node: '>=8.0'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} @@ -2531,18 +1343,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2551,10 +1351,6 @@ packages: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} - strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} @@ -2563,63 +1359,45 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-literal@2.1.1: + resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - terser-webpack-plugin@5.3.16: - resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - terser@5.46.0: resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} engines: {node: '>=10'} hasBin: true - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tmp@0.2.5: - resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} - engines: {node: '>=14.14'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -2628,180 +1406,114 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - type-detect@4.1.0: resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - - typed-array-buffer@1.0.3: - resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} - engines: {node: '>= 0.4'} - - typed-array-byte-length@1.0.3: - resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} - engines: {node: '>= 0.4'} - - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} - engines: {node: '>= 0.4'} - - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} + typescript-eslint@8.60.0: + resolution: {integrity: sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - ua-parser-js@0.7.41: - resolution: {integrity: sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - - unicode-canonical-property-names-ecmascript@2.0.1: - resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} - engines: {node: '>=4'} - - unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - - unicode-match-property-value-ecmascript@2.2.1: - resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} - engines: {node: '>=4'} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} - unicode-property-aliases-ecmascript@2.2.0: - resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} - engines: {node: '>=4'} - - universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' + unplugin-utils@0.2.5: + resolution: {integrity: sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==} + engines: {node: '>=18.12.0'} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - - void-elements@2.0.1: - resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} - engines: {node: '>=0.10.0'} - - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} - engines: {node: '>=10.13.0'} + vite-node@1.6.1: + resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true - webpack-cli@5.1.4: - resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} - engines: {node: '>=14.15.0'} + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - '@webpack-cli/generators': '*' - webpack: 5.x.x - webpack-bundle-analyzer: '*' - webpack-dev-server: '*' + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 peerDependenciesMeta: - '@webpack-cli/generators': + '@types/node': optional: true - webpack-bundle-analyzer: + less: optional: true - webpack-dev-server: + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: optional: true - webpack-merge@4.2.2: - resolution: {integrity: sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==} - - webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - - webpack-sources@3.3.3: - resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} - engines: {node: '>=10.13.0'} - - webpack@5.104.1: - resolution: {integrity: sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA==} - engines: {node: '>=10.13.0'} + vitest@1.6.1: + resolution: {integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - webpack-cli: '*' + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.1 + '@vitest/ui': 1.6.1 + happy-dom: '*' + jsdom: '*' peerDependenciesMeta: - webpack-cli: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: optional: true - - which-boxed-primitive@1.1.1: - resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} - engines: {node: '>= 0.4'} - - which-builtin-type@1.2.1: - resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} - engines: {node: '>= 0.4'} - - which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} hasBin: true - wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workerpool@6.5.1: - resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} - wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -2810,45 +1522,11 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.8.2: resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} hasBin: true - yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - - yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2859,713 +1537,228 @@ packages: snapshots: - '@babel/code-frame@7.28.6': + '@babel/code-frame@7.29.7': dependencies: - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 + optional: true - '@babel/compat-data@7.28.6': {} - - '@babel/core@7.28.6': - dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) - '@babel/helpers': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/eslint-parser@7.28.6(@babel/core@7.28.6)(eslint@8.57.1)': - dependencies: - '@babel/core': 7.28.6 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.1 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - - '@babel/generator@7.28.6': - dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-annotate-as-pure@7.27.3': - dependencies: - '@babel/types': 7.28.6 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.28.6 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-member-expression-to-functions': 7.28.5 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.28.6 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-annotate-as-pure': 7.27.3 - regexpu-core: 6.4.0 - semver: 6.3.1 - - '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - debug: 4.4.3(supports-color@8.1.1) - lodash.debounce: 4.0.8 - resolve: 1.22.11 - transitivePeerDependencies: - - supports-color - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-member-expression-to-functions@7.28.5': - dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-optimise-call-expression@7.27.1': - dependencies: - '@babel/types': 7.28.6 - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-wrap-function': 7.28.6 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-replace-supers@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-member-expression-to-functions': 7.28.5 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-skip-transparent-expression-wrappers@7.27.1': - dependencies: - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helper-wrap-function@7.28.6': - dependencies: - '@babel/template': 7.28.6 - '@babel/traverse': 7.28.6 - '@babel/types': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/helpers@7.28.6': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.28.6 - - '@babel/parser@7.28.6': - dependencies: - '@babel/types': 7.28.6 - - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - - '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-transform-async-generator-functions@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.6) - transitivePeerDependencies: - - supports-color - - '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier@7.29.7': + optional: true - '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/aix-ppc64@0.21.5': + optional: true - '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/aix-ppc64@0.27.7': + optional: true - '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/android-arm64@0.21.5': + optional: true - '@babel/plugin-transform-classes@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/android-arm64@0.27.7': + optional: true - '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/template': 7.28.6 + '@esbuild/android-arm@0.21.5': + optional: true - '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/android-arm@0.27.7': + optional: true - '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/android-x64@0.21.5': + optional: true - '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/android-x64@0.27.7': + optional: true - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/darwin-arm64@0.21.5': + optional: true - '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/darwin-arm64@0.27.7': + optional: true - '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - transitivePeerDependencies: - - supports-color + '@esbuild/darwin-x64@0.21.5': + optional: true - '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/darwin-x64@0.27.7': + optional: true - '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/freebsd-arm64@0.21.5': + optional: true - '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color + '@esbuild/freebsd-arm64@0.27.7': + optional: true - '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/freebsd-x64@0.21.5': + optional: true - '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/freebsd-x64@0.27.7': + optional: true - '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-arm64@0.21.5': + optional: true - '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-arm64@0.27.7': + optional: true - '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-arm@0.21.5': + optional: true - '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-arm@0.27.7': + optional: true - '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-ia32@0.21.5': + optional: true - '@babel/plugin-transform-modules-systemjs@7.28.5(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-ia32@0.27.7': + optional: true - '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-loong64@0.21.5': + optional: true - '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-loong64@0.27.7': + optional: true - '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-mips64el@0.21.5': + optional: true - '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-mips64el@0.27.7': + optional: true - '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-ppc64@0.21.5': + optional: true - '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/traverse': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-ppc64@0.27.7': + optional: true - '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-replace-supers': 7.28.6(@babel/core@7.28.6) - transitivePeerDependencies: - - supports-color + '@esbuild/linux-riscv64@0.21.5': + optional: true - '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-riscv64@0.27.7': + optional: true - '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-s390x@0.21.5': + optional: true - '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/linux-s390x@0.27.7': + optional: true - '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-x64@0.21.5': + optional: true - '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-x64@0.27.7': + optional: true - '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/netbsd-arm64@0.27.7': + optional: true - '@babel/plugin-transform-regenerator@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/netbsd-x64@0.21.5': + optional: true - '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/netbsd-x64@0.27.7': + optional: true - '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/openbsd-arm64@0.27.7': + optional: true - '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/openbsd-x64@0.21.5': + optional: true - '@babel/plugin-transform-spread@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - transitivePeerDependencies: - - supports-color + '@esbuild/openbsd-x64@0.27.7': + optional: true - '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/openharmony-arm64@0.27.7': + optional: true - '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/sunos-x64@0.21.5': + optional: true - '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/sunos-x64@0.27.7': + optional: true - '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/win32-arm64@0.21.5': + optional: true - '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/win32-arm64@0.27.7': + optional: true - '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/win32-ia32@0.21.5': + optional: true - '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.6) - '@babel/helper-plugin-utils': 7.28.6 + '@esbuild/win32-ia32@0.27.7': + optional: true - '@babel/preset-env@7.28.6(@babel/core@7.28.6)': - dependencies: - '@babel/compat-data': 7.28.6 - '@babel/core': 7.28.6 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-option': 7.27.1 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.6) - '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.6) - '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-async-generator-functions': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-modules-systemjs': 7.28.5(@babel/core@7.28.6) - '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.6) - '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-regenerator': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.6) - '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.28.6) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.6) - babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.6) - babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.6) - babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.47.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color + '@esbuild/win32-x64@0.21.5': + optional: true - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.6)': - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.28.6 - esutils: 2.0.3 + '@esbuild/win32-x64@0.27.7': + optional: true - '@babel/register@7.28.6(@babel/core@7.28.6)': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4)': dependencies: - '@babel/core': 7.28.6 - clone-deep: 4.0.1 - find-cache-dir: 2.1.0 - make-dir: 2.1.0 - pirates: 4.0.7 - source-map-support: 0.5.21 + eslint: 9.39.4 + eslint-visitor-keys: 3.4.3 - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.28.6 - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@eslint-community/regexpp@4.12.2': {} - '@babel/traverse@7.28.6': + '@eslint/config-array@0.21.2': dependencies: - '@babel/code-frame': 7.28.6 - '@babel/generator': 7.28.6 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.28.6 - '@babel/template': 7.28.6 - '@babel/types': 7.28.6 - debug: 4.4.3(supports-color@8.1.1) + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color - '@babel/types@7.28.6': + '@eslint/config-helpers@0.4.2': dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@eslint/core': 0.17.0 - '@colors/colors@1.5.0': {} - - '@discoveryjs/json-ext@0.5.7': {} - - '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': + '@eslint/core@0.17.0': dependencies: - eslint: 8.57.1 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.2': {} + '@types/json-schema': 7.0.15 - '@eslint/eslintrc@2.1.4': + '@eslint/eslintrc@3.3.5': dependencies: - ajv: 6.12.6 - debug: 4.4.3(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.24.0 + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 js-yaml: 4.1.1 - minimatch: 3.1.2 + minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@8.57.1': {} + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} - '@humanwhocodes/config-array@0.13.0': + '@eslint/plugin-kit@0.4.1': dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.3(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.4.3': {} + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.10 '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -3583,6 +1776,7 @@ snapshots: dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 + optional: true '@jridgewell/sourcemap-codec@1.5.5': {} @@ -3591,211 +1785,235 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': - dependencies: - eslint-scope: 5.1.1 + '@rollup/rollup-android-arm-eabi@4.60.4': + optional: true - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + '@rollup/rollup-android-arm64@4.60.4': + optional: true - '@nodelib/fs.stat@2.0.5': {} + '@rollup/rollup-darwin-arm64@4.60.4': + optional: true - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 + '@rollup/rollup-darwin-x64@4.60.4': + optional: true - '@rtsao/scc@1.1.0': {} + '@rollup/rollup-freebsd-arm64@4.60.4': + optional: true - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 + '@rollup/rollup-freebsd-x64@4.60.4': + optional: true - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + optional: true - '@sinonjs/fake-timers@11.3.1': - dependencies: - '@sinonjs/commons': 3.0.1 + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + optional: true - '@sinonjs/samsam@8.0.3': - dependencies: - '@sinonjs/commons': 3.0.1 - type-detect: 4.1.0 + '@rollup/rollup-linux-arm64-gnu@4.60.4': + optional: true - '@sinonjs/text-encoding@0.7.3': {} + '@rollup/rollup-linux-arm64-musl@4.60.4': + optional: true - '@socket.io/component-emitter@3.1.2': {} + '@rollup/rollup-linux-loong64-gnu@4.60.4': + optional: true - '@types/cors@2.8.19': - dependencies: - '@types/node': 25.0.9 + '@rollup/rollup-linux-loong64-musl@4.60.4': + optional: true - '@types/eslint-scope@3.7.7': - dependencies: - '@types/eslint': 9.6.1 - '@types/estree': 1.0.8 + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + optional: true - '@types/eslint@9.6.1': - dependencies: - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 + '@rollup/rollup-linux-ppc64-musl@4.60.4': + optional: true - '@types/estree@1.0.8': {} + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + optional: true - '@types/json-schema@7.0.15': {} + '@rollup/rollup-linux-riscv64-musl@4.60.4': + optional: true - '@types/json5@0.0.29': {} + '@rollup/rollup-linux-s390x-gnu@4.60.4': + optional: true - '@types/node@25.0.9': - dependencies: - undici-types: 7.16.0 + '@rollup/rollup-linux-x64-gnu@4.60.4': + optional: true - '@ungap/structured-clone@1.3.0': {} + '@rollup/rollup-linux-x64-musl@4.60.4': + optional: true - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@rollup/rollup-openbsd-x64@4.60.4': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.4': + optional: true - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + '@rollup/rollup-win32-arm64-msvc@4.60.4': + optional: true - '@webassemblyjs/helper-api-error@1.13.2': {} + '@rollup/rollup-win32-ia32-msvc@4.60.4': + optional: true - '@webassemblyjs/helper-buffer@1.14.1': {} + '@rollup/rollup-win32-x64-gnu@4.60.4': + optional: true - '@webassemblyjs/helper-numbers@1.13.2': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.13.2 - '@webassemblyjs/helper-api-error': 1.13.2 - '@xtuc/long': 4.2.2 + '@rollup/rollup-win32-x64-msvc@4.60.4': + optional: true - '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + '@sinclair/typebox@0.27.10': {} - '@webassemblyjs/helper-wasm-section@1.14.1': + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@20.19.41': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/wasm-gen': 1.14.1 + undici-types: 6.21.0 - '@webassemblyjs/ieee754@1.13.2': + '@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@xtuc/ieee754': 1.2.0 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/type-utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.0 + eslint: 9.39.4 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@webassemblyjs/leb128@1.13.2': + '@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@xtuc/long': 4.2.2 + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.60.0 + debug: 4.4.3 + eslint: 9.39.4 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@webassemblyjs/utf8@1.13.2': {} + '@typescript-eslint/project-service@8.60.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3) + '@typescript-eslint/types': 8.60.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@webassemblyjs/wasm-edit@1.14.1': + '@typescript-eslint/scope-manager@8.60.0': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/helper-wasm-section': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-opt': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wast-printer': 1.14.1 - - '@webassemblyjs/wasm-gen@1.14.1': + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 + + '@typescript-eslint/tsconfig-utils@8.60.0(typescript@5.9.3)': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 + typescript: 5.9.3 - '@webassemblyjs/wasm-opt@1.14.1': + '@typescript-eslint/type-utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.4 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@webassemblyjs/wasm-parser@1.14.1': + '@typescript-eslint/types@8.60.0': {} + + '@typescript-eslint/typescript-estree@8.60.0(typescript@5.9.3)': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-api-error': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wast-printer@1.14.1': + '@typescript-eslint/project-service': 8.60.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@5.9.3) + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/visitor-keys': 8.60.0 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.8.1 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.60.0(eslint@9.39.4)(typescript@5.9.3)': dependencies: - '@webassemblyjs/ast': 1.14.1 - '@xtuc/long': 4.2.2 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) + '@typescript-eslint/scope-manager': 8.60.0 + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + eslint: 9.39.4 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.104.1)': + '@typescript-eslint/visitor-keys@8.60.0': dependencies: - webpack: 5.104.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.104.1) + '@typescript-eslint/types': 8.60.0 + eslint-visitor-keys: 5.0.1 - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.104.1)': + '@vitest/expect@1.6.1': dependencies: - webpack: 5.104.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.104.1) + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + chai: 4.5.0 - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.104.1)': + '@vitest/runner@1.6.1': dependencies: - webpack: 5.104.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.104.1) + '@vitest/utils': 1.6.1 + p-limit: 5.0.0 + pathe: 1.1.2 - '@xtuc/ieee754@1.2.0': {} + '@vitest/snapshot@1.6.1': + dependencies: + magic-string: 0.30.21 + pathe: 1.1.2 + pretty-format: 29.7.0 - '@xtuc/long@4.2.2': {} + '@vitest/spy@1.6.1': + dependencies: + tinyspy: 2.2.1 - accepts@1.3.8: + '@vitest/utils@1.6.1': dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 - acorn-import-phases@1.0.4(acorn@8.15.0): + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: - acorn: 8.15.0 + acorn: 8.16.0 - acorn-jsx@5.3.2(acorn@8.15.0): + acorn-walk@8.3.5: dependencies: acorn: 8.15.0 acorn@8.15.0: {} + acorn@8.16.0: {} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv-keywords@5.1.0(ajv@8.17.1): - dependencies: - ajv: 8.17.1 - fast-deep-equal: 3.1.3 - - ajv@6.12.6: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-colors@4.1.3: {} - ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -3808,188 +2026,40 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} + ansi-styles@5.2.0: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + ansi-styles@6.2.3: {} argparse@2.0.1: {} - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - - array-includes@3.1.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - is-string: 1.1.1 - math-intrinsics: 1.1.0 - - array.prototype.findlastindex@1.2.6: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-shim-unscopables: 1.1.0 - - array.prototype.flat@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-shim-unscopables: 1.1.0 - - array.prototype.flatmap@1.3.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-shim-unscopables: 1.1.0 - - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.5 - assertion-error@1.1.0: {} astral-regex@2.0.0: {} - async-function@1.0.0: {} - - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - babel-loader@9.2.1(@babel/core@7.28.6)(webpack@5.104.1): - dependencies: - '@babel/core': 7.28.6 - find-cache-dir: 4.0.0 - schema-utils: 4.3.3 - webpack: 5.104.1(webpack-cli@5.1.4) - - babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.6): - dependencies: - '@babel/compat-data': 7.28.6 - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - core-js-compat: 3.47.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.6): - dependencies: - '@babel/core': 7.28.6 - '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.6) - transitivePeerDependencies: - - supports-color - balanced-match@1.0.2: {} - base64-js@1.5.1: {} - - base64id@2.0.0: {} - - baseline-browser-mapping@2.9.15: {} - - binary-extensions@2.3.0: {} - - body-parser@1.20.4: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.14.1 - raw-body: 2.5.3 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color + balanced-match@4.0.4: {} brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.2: + brace-expansion@5.0.6: dependencies: - balanced-match: 1.0.2 + balanced-match: 4.0.4 braces@3.0.3: dependencies: fill-range: 7.1.1 - browser-stdout@1.3.1: {} - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.9.15 - caniuse-lite: 1.0.30001764 - electron-to-chromium: 1.5.267 - node-releases: 2.0.27 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - buffer-from@1.1.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - bytes@3.1.2: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 + buffer-from@1.1.2: + optional: true - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 + cac@6.7.14: {} callsites@3.1.0: {} - camelcase@6.3.0: {} - - caniuse-lite@1.0.30001764: {} - chai@4.5.0: dependencies: assertion-error: 1.1.0 @@ -4011,20 +2081,6 @@ snapshots: dependencies: get-func-name: 2.0.2 - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - chrome-trace-event@1.0.4: {} - clean-stack@2.2.0: {} cli-cursor@3.1.0: @@ -4039,440 +2095,169 @@ snapshots: cli-truncate@3.1.0: dependencies: slice-ansi: 5.0.0 - string-width: 5.1.2 - - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - clone-deep@4.0.1: - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - colorette@2.0.20: {} - - commander@10.0.1: {} - - commander@2.20.3: {} - - common-path-prefix@3.0.0: {} - - commondir@1.0.1: {} - - concat-map@0.0.1: {} - - confusing-browser-globals@1.0.11: {} - - connect@3.7.0: - dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 - parseurl: 1.3.3 - utils-merge: 1.0.1 - transitivePeerDependencies: - - supports-color - - content-type@1.0.5: {} - - convert-source-map@2.0.0: {} - - cookie@0.7.2: {} - - core-js-compat@3.47.0: - dependencies: - browserslist: 4.28.1 - - cors@2.8.5: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - custom-event@1.0.1: {} - - data-view-buffer@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - data-view-byte-offset@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-data-view: 1.0.2 - - date-format@4.0.14: {} - - debug@2.6.9: - dependencies: - ms: 2.0.0 - - debug@3.2.7: - dependencies: - ms: 2.1.3 - - debug@4.4.3(supports-color@8.1.1): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 8.1.1 - - decamelize@4.0.0: {} - - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - - deep-is@0.1.4: {} - - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - - depd@2.0.0: {} - - destroy@1.2.0: {} - - di@0.0.1: {} - - diff@5.2.0: {} - - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - - dom-serialize@2.2.1: - dependencies: - custom-event: 1.0.1 - ent: 2.2.2 - extend: 3.0.2 - void-elements: 2.0.1 - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - eastasianwidth@0.2.0: {} - - ee-first@1.1.1: {} - - electron-to-chromium@1.5.267: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - encodeurl@1.0.2: {} - - engine.io-parser@5.2.3: {} - - engine.io@6.6.5: - dependencies: - '@types/cors': 2.8.19 - '@types/node': 25.0.9 - accepts: 1.3.8 - base64id: 2.0.0 - cookie: 0.7.2 - cors: 2.8.5 - debug: 4.4.3(supports-color@8.1.1) - engine.io-parser: 5.2.3 - ws: 8.18.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - enhanced-resolve@5.18.4: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 + string-width: 5.1.2 - ent@2.2.2: + color-convert@2.0.1: dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - punycode: 1.4.1 - safe-regex-test: 1.1.0 - - envinfo@7.21.0: {} + color-name: 1.1.4 - es-abstract@1.24.1: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - data-view-buffer: 1.0.2 - data-view-byte-length: 1.0.2 - data-view-byte-offset: 1.0.1 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - get-symbol-description: 1.1.0 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.1.0 - is-array-buffer: 3.0.5 - is-callable: 1.2.7 - is-data-view: 1.0.2 - is-negative-zero: 2.0.3 - is-regex: 1.2.1 - is-set: 2.0.3 - is-shared-array-buffer: 1.0.4 - is-string: 1.1.1 - is-typed-array: 1.1.15 - is-weakref: 1.1.1 - math-intrinsics: 1.1.0 - object-inspect: 1.13.4 - object-keys: 1.1.1 - object.assign: 4.1.7 - own-keys: 1.0.1 - regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 - safe-push-apply: 1.0.0 - safe-regex-test: 1.1.0 - set-proto: 1.0.0 - stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.3 - typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-module-lexer@2.0.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 + color-name@1.1.4: {} - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 + colorette@2.0.20: {} - es-shim-unscopables@1.1.0: - dependencies: - hasown: 2.0.2 + commander@10.0.1: {} - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 + commander@2.20.3: + optional: true - escalade@3.2.0: {} + concat-map@0.0.1: {} - escape-html@1.0.3: {} + confbox@0.1.8: {} - escape-string-regexp@4.0.0: {} + convert-source-map@2.0.0: {} - eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.32.0(eslint@8.57.1))(eslint@8.57.1): - dependencies: - confusing-browser-globals: 1.0.11 - eslint: 8.57.1 - eslint-plugin-import: 2.32.0(eslint@8.57.1) - object.assign: 4.1.7 - object.entries: 1.1.9 - semver: 6.3.1 - - eslint-config-prettier@8.10.2(eslint@8.57.1): + cross-spawn@7.0.6: dependencies: - eslint: 8.57.1 + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - eslint-import-resolver-node@0.3.9: + debug@4.4.3: dependencies: - debug: 3.2.7 - is-core-module: 2.16.1 - resolve: 1.22.11 - transitivePeerDependencies: - - supports-color + ms: 2.1.3 - eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): + deep-eql@4.1.4: dependencies: - debug: 3.2.7 - optionalDependencies: - eslint: 8.57.1 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color + type-detect: 4.1.0 - eslint-plugin-es@3.0.1(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-utils: 2.1.0 - regexpp: 3.2.0 + deep-is@0.1.4: {} - eslint-plugin-import@2.32.0(eslint@8.57.1): - dependencies: - '@rtsao/scc': 1.1.0 - array-includes: 3.1.9 - array.prototype.findlastindex: 1.2.6 - array.prototype.flat: 1.3.3 - array.prototype.flatmap: 1.3.3 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.1 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) - hasown: 2.0.2 - is-core-module: 2.16.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.1 - semver: 6.3.1 - string.prototype.trimend: 1.0.9 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color + diff-sequences@29.6.3: {} - eslint-plugin-node@11.1.0(eslint@8.57.1): - dependencies: - eslint: 8.57.1 - eslint-plugin-es: 3.0.1(eslint@8.57.1) - eslint-utils: 2.1.0 - ignore: 5.3.2 - minimatch: 3.1.2 - resolve: 1.22.11 - semver: 6.3.1 + eastasianwidth@0.2.0: {} - eslint-plugin-prefer-import@0.0.1: {} + emoji-regex@8.0.0: {} - eslint-plugin-prettier@4.2.5(eslint-config-prettier@8.10.2(eslint@8.57.1))(eslint@8.57.1)(prettier@2.8.8): - dependencies: - eslint: 8.57.1 - prettier: 2.8.8 - prettier-linter-helpers: 1.0.1 + emoji-regex@9.2.2: {} + + es-module-lexer@1.7.0: {} + + esbuild@0.21.5: optionalDependencies: - eslint-config-prettier: 8.10.2(eslint@8.57.1) + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + escape-string-regexp@4.0.0: {} - eslint-scope@5.1.1: + eslint-config-prettier@9.1.2(eslint@9.39.4): dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 + eslint: 9.39.4 - eslint-scope@7.2.2: + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-utils@2.1.0: - dependencies: - eslint-visitor-keys: 1.3.0 - - eslint-visitor-keys@1.3.0: {} + eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@2.1.0: {} + eslint-visitor-keys@4.2.1: {} - eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@5.0.1: {} - eslint@8.57.1: + eslint@9.39.4: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4) '@eslint-community/regexpp': 4.12.2 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.1 - '@humanwhocodes/config-array': 0.13.0 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.3.0 - ajv: 6.12.6 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) - doctrine: 3.0.0 + debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.1 json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 transitivePeerDependencies: - supports-color - espree@9.6.1: + espree@10.4.0: dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 3.4.3 + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 esquery@1.7.0: dependencies: @@ -4482,15 +2267,13 @@ snapshots: dependencies: estraverse: 5.3.0 - estraverse@4.3.0: {} - estraverse@5.3.0: {} - esutils@2.0.3: {} - - eventemitter3@4.0.7: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 - events@3.3.0: {} + esutils@2.0.3: {} execa@7.2.0: dependencies: @@ -4504,513 +2287,123 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 3.0.0 - extend@3.0.2: {} + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 fast-deep-equal@3.1.3: {} - fast-diff@1.3.0: {} - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} - fast-uri@3.1.0: {} - - fastest-levenshtein@1.0.16: {} - - fastq@1.20.1: - dependencies: - reusify: 1.1.0 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 - file-entry-cache@6.0.1: + file-entry-cache@8.0.0: dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - finalhandler@1.1.2: - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - - find-cache-dir@2.1.0: - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - - find-cache-dir@4.0.0: - dependencies: - common-path-prefix: 3.0.0 - pkg-dir: 7.0.0 - - find-up@3.0.0: - dependencies: - locate-path: 3.0.0 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - find-up@6.3.0: - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - - flat-cache@3.2.0: + flat-cache@4.0.1: dependencies: flatted: 3.3.3 keyv: 4.5.4 - rimraf: 3.0.2 - - flat@5.0.2: {} flatted@3.3.3: {} - follow-redirects@1.15.11: {} - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - - fs-extra@8.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - generator-function@2.0.1: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - get-func-name@2.0.2: {} - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - get-stream@6.0.1: {} - get-symbol-description@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 + get-stream@8.0.1: {} - glob-parent@5.1.2: + get-tsconfig@4.14.0: dependencies: - is-glob: 4.0.3 + resolve-pkg-maps: 1.0.0 glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - glob@8.1.0: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - - gopd@1.2.0: {} - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - - has-bigints@1.1.0: {} + globals@14.0.0: {} has-flag@4.0.0: {} - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.1 - - has-proto@1.2.0: - dependencies: - dunder-proto: 1.0.1 - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - he@1.2.0: {} - - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - http-proxy@1.18.1: - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.11 - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - human-signals@4.3.1: {} - husky@8.0.3: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 + human-signals@5.0.0: {} - ieee754@1.2.1: {} + husky@8.0.3: {} ignore@5.3.2: {} + ignore@7.0.5: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - imurmurhash@0.1.4: {} indent-string@4.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - interpret@3.1.1: {} - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - is-async-function@2.1.1: - dependencies: - async-function: 1.0.0 - call-bound: 1.0.4 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - - is-bigint@1.1.0: - dependencies: - has-bigints: 1.1.0 - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-callable@1.2.7: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-data-view@1.0.2: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - is-typed-array: 1.1.15 - - is-date-object@1.1.0: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-docker@2.2.1: {} - is-extglob@2.1.1: {} - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.4 - is-fullwidth-code-point@3.0.0: {} is-fullwidth-code-point@4.0.0: {} - is-generator-function@1.1.2: - dependencies: - call-bound: 1.0.4 - generator-function: 2.0.1 - get-proto: 1.0.1 - has-tostringtag: 1.0.2 - safe-regex-test: 1.1.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - is-map@2.0.3: {} - - is-negative-zero@2.0.3: {} - - is-number-object@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-number@7.0.0: {} - is-path-inside@3.0.3: {} - - is-plain-obj@2.1.0: {} - - is-plain-object@2.0.4: - dependencies: - isobject: 3.0.1 - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 - is-stream@3.0.0: {} - is-string@1.1.1: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - - is-symbol@1.1.1: - dependencies: - call-bound: 1.0.4 - has-symbols: 1.1.0 - safe-regex-test: 1.1.0 - - is-typed-array@1.1.15: - dependencies: - which-typed-array: 1.1.20 - - is-unicode-supported@0.1.0: {} - - is-weakmap@2.0.2: {} - - is-weakref@1.1.1: - dependencies: - call-bound: 1.0.4 - - is-weakset@2.0.4: - dependencies: - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - - isarray@2.0.5: {} - - isbinaryfile@4.0.10: {} - isexe@2.0.0: {} - isobject@3.0.1: {} - - jest-worker@27.5.1: - dependencies: - '@types/node': 25.0.9 - merge-stream: 2.0.0 - supports-color: 8.1.1 + js-tokens@4.0.0: + optional: true - js-tokens@4.0.0: {} + js-tokens@9.0.1: {} js-yaml@4.1.1: dependencies: argparse: 2.0.1 - jsesc@3.1.0: {} - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} - json5@1.0.2: - dependencies: - minimist: 1.2.8 - - json5@2.2.3: {} - - jsonfile@4.0.0: - optionalDependencies: - graceful-fs: 4.2.11 - - just-extend@6.2.0: {} - - karma-chrome-launcher@3.2.0: - dependencies: - which: 1.3.1 - - karma-firefox-launcher@2.1.3: - dependencies: - is-wsl: 2.2.0 - which: 3.0.1 - - karma-mocha@2.0.1: - dependencies: - minimist: 1.2.8 - - karma-sinon-chai@2.0.2(chai@4.5.0)(sinon-chai@3.7.0(chai@4.5.0)(sinon@15.2.0))(sinon@15.2.0): - dependencies: - chai: 4.5.0 - sinon: 15.2.0 - sinon-chai: 3.7.0(chai@4.5.0)(sinon@15.2.0) - - karma-webpack@5.0.1(webpack@5.104.1): - dependencies: - glob: 7.2.3 - minimatch: 9.0.5 - webpack: 5.104.1(webpack-cli@5.1.4) - webpack-merge: 4.2.2 - - karma@6.4.4: - dependencies: - '@colors/colors': 1.5.0 - body-parser: 1.20.4 - braces: 3.0.3 - chokidar: 3.6.0 - connect: 3.7.0 - di: 0.0.1 - dom-serialize: 2.2.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - http-proxy: 1.18.1 - isbinaryfile: 4.0.10 - lodash: 4.17.21 - log4js: 6.9.1 - mime: 2.6.0 - minimatch: 3.1.2 - mkdirp: 0.5.6 - qjobs: 1.2.0 - range-parser: 1.2.1 - rimraf: 3.0.2 - socket.io: 4.8.3 - source-map: 0.6.1 - tmp: 0.2.5 - ua-parser-js: 0.7.41 - yargs: 16.2.0 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -5023,7 +2416,7 @@ snapshots: chalk: 5.2.0 cli-truncate: 3.1.0 commander: 10.0.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 execa: 7.2.0 lilconfig: 2.1.0 listr2: 5.0.8 @@ -5048,36 +2441,17 @@ snapshots: through: 2.3.8 wrap-ansi: 7.0.0 - loader-runner@4.3.1: {} - - locate-path@3.0.0: + local-pkg@0.5.1: dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 + mlly: 1.8.2 + pkg-types: 1.3.1 locate-path@6.0.0: dependencies: p-locate: 5.0.0 - locate-path@7.2.0: - dependencies: - p-locate: 6.0.0 - - lodash.debounce@4.0.8: {} - lodash.merge@4.6.2: {} - lodash@4.17.21: {} - - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - log-update@4.0.0: dependencies: ansi-escapes: 4.3.2 @@ -5085,32 +2459,13 @@ snapshots: slice-ansi: 4.0.0 wrap-ansi: 6.2.0 - log4js@6.9.1: - dependencies: - date-format: 4.0.14 - debug: 4.4.3(supports-color@8.1.1) - flatted: 3.3.3 - rfdc: 1.4.1 - streamroller: 3.1.5 - transitivePeerDependencies: - - supports-color - loupe@2.3.7: dependencies: get-func-name: 2.0.2 - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - make-dir@2.1.0: - dependencies: - pify: 4.0.1 - semver: 5.7.2 - - math-intrinsics@1.1.0: {} - - media-typer@0.3.0: {} + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 merge-stream@2.0.0: {} @@ -5119,78 +2474,30 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@2.6.0: {} - mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.2 - - minimatch@9.0.5: + minimatch@10.2.5: dependencies: - brace-expansion: 2.0.2 - - minimist@1.2.8: {} + brace-expansion: 5.0.6 - mkdirp@0.5.6: + minimatch@3.1.5: dependencies: - minimist: 1.2.8 + brace-expansion: 1.1.12 - mocha@10.8.2: + mlly@1.8.2: dependencies: - ansi-colors: 4.1.3 - browser-stdout: 1.3.1 - chokidar: 3.6.0 - debug: 4.4.3(supports-color@8.1.1) - diff: 5.2.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 8.1.0 - he: 1.2.0 - js-yaml: 4.1.1 - log-symbols: 4.1.0 - minimatch: 5.1.6 - ms: 2.1.3 - serialize-javascript: 6.0.2 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - workerpool: 6.5.1 - yargs: 16.2.0 - yargs-parser: 20.2.9 - yargs-unparser: 2.0.0 - - ms@2.0.0: {} + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 ms@2.1.3: {} - natural-compare@1.4.0: {} - - negotiator@0.6.3: {} - - neo-async@2.6.2: {} - - nise@5.1.9: - dependencies: - '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers': 11.3.1 - '@sinonjs/text-encoding': 0.7.3 - just-extend: 6.2.0 - path-to-regexp: 6.3.0 + nanoid@3.3.12: {} - node-releases@2.0.27: {} + natural-compare@1.4.0: {} normalize-path@3.0.0: {} @@ -5198,60 +2505,8 @@ snapshots: dependencies: path-key: 4.0.0 - object-assign@4.1.1: {} - object-inspect@1.13.4: {} - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - - object.entries@1.1.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - - object.groupby@1.0.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - - object.values@1.2.1: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - on-finished@2.3.0: - dependencies: - ee-first: 1.1.1 - - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -5269,67 +2524,35 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.3.0 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: + p-limit@5.0.0: dependencies: yocto-queue: 1.2.2 - p-locate@3.0.0: - dependencies: - p-limit: 2.3.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - p-locate@5.0.0: dependencies: p-limit: 3.1.0 - p-locate@6.0.0: - dependencies: - p-limit: 4.0.0 - p-map@4.0.0: dependencies: aggregate-error: 3.1.0 - p-try@2.2.0: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 - parseurl@1.3.3: {} - - path-exists@3.0.0: {} - path-exists@4.0.0: {} - path-exists@5.0.0: {} - - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-key@4.0.0: {} - path-parse@1.0.7: {} + pathe@1.1.2: {} - path-to-regexp@6.3.0: {} + pathe@2.0.3: {} pathval@1.1.1: {} @@ -5337,216 +2560,105 @@ snapshots: picomatch@2.3.1: {} - pidtree@0.6.0: {} - - pify@4.0.1: {} - - pirates@4.0.7: {} + picomatch@4.0.4: {} - pkg-dir@3.0.0: - dependencies: - find-up: 3.0.0 + pidtree@0.6.0: {} - pkg-dir@4.2.0: + pkg-types@1.3.1: dependencies: - find-up: 4.1.0 + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 - pkg-dir@7.0.0: + postcss@8.5.15: dependencies: - find-up: 6.3.0 - - possible-typed-array-names@1.1.0: {} + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 prelude-ls@1.2.1: {} - prettier-linter-helpers@1.0.1: - dependencies: - fast-diff: 1.3.0 - prettier@2.8.8: {} - punycode@1.4.1: {} - - punycode@2.3.1: {} - - qjobs@1.2.0: {} - - qs@6.14.1: - dependencies: - side-channel: 1.1.0 - - queue-microtask@1.2.3: {} - - randombytes@2.1.0: - dependencies: - safe-buffer: 5.2.1 - - range-parser@1.2.1: {} - - raw-body@2.5.3: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - rechoir@0.8.0: - dependencies: - resolve: 1.22.11 - - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - - regenerate-unicode-properties@10.2.2: - dependencies: - regenerate: 1.4.2 - - regenerate@1.4.2: {} - - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - get-proto: 1.0.1 - gopd: 1.2.0 - set-function-name: 2.0.2 - - regexpp@3.2.0: {} - - regexpu-core@6.4.0: - dependencies: - regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.2 - regjsgen: 0.8.0 - regjsparser: 0.13.0 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.1 - - regjsgen@0.8.0: {} - - regjsparser@0.13.0: + pretty-format@29.7.0: dependencies: - jsesc: 3.1.0 - - require-directory@2.1.1: {} + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 - require-from-string@2.0.2: {} - - requires-port@1.0.0: {} + punycode@2.3.1: {} - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 + react-is@18.3.1: {} resolve-from@4.0.0: {} - resolve-from@5.0.0: {} - - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 + resolve-pkg-maps@1.0.0: {} restore-cursor@3.1.0: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - reusify@1.1.0: {} - rfdc@1.4.1: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - rxjs@7.8.2: - dependencies: - tslib: 2.8.1 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - - safe-buffer@5.2.1: {} - - safe-push-apply@1.0.0: - dependencies: - es-errors: 1.3.0 - isarray: 2.0.5 - - safe-regex-test@1.1.0: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-regex: 1.2.1 - - safer-buffer@2.1.2: {} - - schema-utils@4.3.3: + rollup-plugin-dts@6.4.1(rollup@4.60.4)(typescript@5.9.3): dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - ajv-keywords: 5.1.0(ajv@8.17.1) - - semver@5.7.2: {} - - semver@6.3.1: {} + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + convert-source-map: 2.0.0 + magic-string: 0.30.21 + rollup: 4.60.4 + typescript: 5.9.3 + optionalDependencies: + '@babel/code-frame': 7.29.7 - serialize-javascript@6.0.2: + rollup-plugin-esbuild@6.2.1(esbuild@0.27.7)(rollup@4.60.4): dependencies: - randombytes: 2.1.0 + debug: 4.4.3 + es-module-lexer: 1.7.0 + esbuild: 0.27.7 + get-tsconfig: 4.14.0 + rollup: 4.60.4 + unplugin-utils: 0.2.5 + transitivePeerDependencies: + - supports-color - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - - set-function-name@2.0.2: + rollup@4.60.4: dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.4 + '@rollup/rollup-android-arm64': 4.60.4 + '@rollup/rollup-darwin-arm64': 4.60.4 + '@rollup/rollup-darwin-x64': 4.60.4 + '@rollup/rollup-freebsd-arm64': 4.60.4 + '@rollup/rollup-freebsd-x64': 4.60.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.4 + '@rollup/rollup-linux-arm-musleabihf': 4.60.4 + '@rollup/rollup-linux-arm64-gnu': 4.60.4 + '@rollup/rollup-linux-arm64-musl': 4.60.4 + '@rollup/rollup-linux-loong64-gnu': 4.60.4 + '@rollup/rollup-linux-loong64-musl': 4.60.4 + '@rollup/rollup-linux-ppc64-gnu': 4.60.4 + '@rollup/rollup-linux-ppc64-musl': 4.60.4 + '@rollup/rollup-linux-riscv64-gnu': 4.60.4 + '@rollup/rollup-linux-riscv64-musl': 4.60.4 + '@rollup/rollup-linux-s390x-gnu': 4.60.4 + '@rollup/rollup-linux-x64-gnu': 4.60.4 + '@rollup/rollup-linux-x64-musl': 4.60.4 + '@rollup/rollup-openbsd-x64': 4.60.4 + '@rollup/rollup-openharmony-arm64': 4.60.4 + '@rollup/rollup-win32-arm64-msvc': 4.60.4 + '@rollup/rollup-win32-ia32-msvc': 4.60.4 + '@rollup/rollup-win32-x64-gnu': 4.60.4 + '@rollup/rollup-win32-x64-msvc': 4.60.4 + fsevents: 2.3.3 - set-proto@1.0.0: + rxjs@7.8.2: dependencies: - dunder-proto: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - - setprototypeof@1.2.0: {} + tslib: 2.8.1 - shallow-clone@3.0.1: - dependencies: - kind-of: 6.0.3 + semver@7.8.1: {} shebang-command@2.0.0: dependencies: @@ -5554,49 +2666,11 @@ snapshots: shebang-regex@3.0.0: {} - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} signal-exit@3.0.7: {} - sinon-chai@3.7.0(chai@4.5.0)(sinon@15.2.0): - dependencies: - chai: 4.5.0 - sinon: 15.2.0 - - sinon@15.2.0: - dependencies: - '@sinonjs/commons': 3.0.1 - '@sinonjs/fake-timers': 10.3.0 - '@sinonjs/samsam': 8.0.3 - diff: 5.2.0 - nise: 5.1.9 - supports-color: 7.2.0 + signal-exit@4.1.0: {} slice-ansi@3.0.0: dependencies: @@ -5615,59 +2689,20 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 4.0.0 - socket.io-adapter@2.5.6: - dependencies: - debug: 4.4.3(supports-color@8.1.1) - ws: 8.18.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - socket.io-parser@4.2.5: - dependencies: - '@socket.io/component-emitter': 3.1.2 - debug: 4.4.3(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - socket.io@4.8.3: - dependencies: - accepts: 1.3.8 - base64id: 2.0.0 - cors: 2.8.5 - debug: 4.4.3(supports-color@8.1.1) - engine.io: 6.6.5 - socket.io-adapter: 2.5.6 - socket.io-parser: 4.2.5 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate + source-map-js@1.2.1: {} source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + optional: true - source-map@0.6.1: {} - - statuses@1.5.0: {} - - statuses@2.0.2: {} + source-map@0.6.1: + optional: true - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 + stackback@0.0.2: {} - streamroller@3.1.5: - dependencies: - date-format: 4.0.14 - debug: 4.4.3(supports-color@8.1.1) - fs-extra: 8.1.0 - transitivePeerDependencies: - - supports-color + std-env@3.10.0: {} string-argv@0.3.2: {} @@ -5683,29 +2718,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -5714,58 +2726,46 @@ snapshots: dependencies: ansi-regex: 6.2.2 - strip-bom@3.0.0: {} - strip-final-newline@3.0.0: {} strip-json-comments@3.1.1: {} - supports-color@7.2.0: + strip-literal@2.1.1: dependencies: - has-flag: 4.0.0 + js-tokens: 9.0.1 - supports-color@8.1.1: + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - - tapable@2.3.0: {} - - terser-webpack-plugin@5.3.16(webpack@5.104.1): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - serialize-javascript: 6.0.2 - terser: 5.46.0 - webpack: 5.104.1(webpack-cli@5.1.4) - terser@5.46.0: dependencies: '@jridgewell/source-map': 0.3.11 - acorn: 8.15.0 + acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 - - text-table@0.2.0: {} + optional: true through@2.3.8: {} - tmp@0.2.5: {} + tinybench@2.9.0: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - toidentifier@1.0.1: {} - - tsconfig-paths@3.15.0: + ts-api-utils@2.5.0(typescript@5.9.3): dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 + typescript: 5.9.3 tslib@2.8.1: {} @@ -5773,221 +2773,109 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} - type-detect@4.1.0: {} - type-fest@0.20.2: {} - type-fest@0.21.3: {} - type-is@1.6.18: - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - - typed-array-buffer@1.0.3: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - is-typed-array: 1.1.15 - - typed-array-byte-length@1.0.3: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - - typed-array-byte-offset@1.0.4: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - has-proto: 1.2.0 - is-typed-array: 1.1.15 - reflect.getprototypeof: 1.0.10 - - typed-array-length@1.0.7: - dependencies: - call-bind: 1.0.8 - for-each: 0.3.5 - gopd: 1.2.0 - is-typed-array: 1.1.15 - possible-typed-array-names: 1.1.0 - reflect.getprototypeof: 1.0.10 - - ua-parser-js@0.7.41: {} - - unbox-primitive@1.1.0: - dependencies: - call-bound: 1.0.4 - has-bigints: 1.1.0 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.1 - - undici-types@7.16.0: {} - - unicode-canonical-property-names-ecmascript@2.0.1: {} - - unicode-match-property-ecmascript@2.0.0: + typescript-eslint@8.60.0(eslint@9.39.4)(typescript@5.9.3): dependencies: - unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.2.0 - - unicode-match-property-value-ecmascript@2.2.1: {} + '@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@9.39.4)(typescript@5.9.3))(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/parser': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.60.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4)(typescript@5.9.3) + eslint: 9.39.4 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color - unicode-property-aliases-ecmascript@2.2.0: {} + typescript@5.9.3: {} - universalify@0.1.2: {} + ufo@1.6.4: {} - unpipe@1.0.0: {} + undici-types@6.21.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.1): + unplugin-utils@0.2.5: dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 uri-js@4.4.1: dependencies: punycode: 2.3.1 - utils-merge@1.0.1: {} - - vary@1.1.2: {} - - void-elements@2.0.1: {} - - watchpack@2.5.1: - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - - webpack-cli@5.1.4(webpack@5.104.1): - dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.104.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.104.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.104.1) - colorette: 2.0.20 - commander: 10.0.1 - cross-spawn: 7.0.6 - envinfo: 7.21.0 - fastest-levenshtein: 1.0.16 - import-local: 3.2.0 - interpret: 3.1.1 - rechoir: 0.8.0 - webpack: 5.104.1(webpack-cli@5.1.4) - webpack-merge: 5.10.0 - - webpack-merge@4.2.2: + vite-node@1.6.1(@types/node@20.19.41)(terser@5.46.0): dependencies: - lodash: 4.17.21 + cac: 6.7.14 + debug: 4.4.3 + pathe: 1.1.2 + picocolors: 1.1.1 + vite: 5.4.21(@types/node@20.19.41)(terser@5.46.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser - webpack-merge@5.10.0: + vite@5.4.21(@types/node@20.19.41)(terser@5.46.0): dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 - - webpack-sources@3.3.3: {} + esbuild: 0.21.5 + postcss: 8.5.15 + rollup: 4.60.4 + optionalDependencies: + '@types/node': 20.19.41 + fsevents: 2.3.3 + terser: 5.46.0 - webpack@5.104.1(webpack-cli@5.1.4): + vitest@1.6.1(@types/node@20.19.41)(terser@5.46.0): dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.15.0 - acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.28.1 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.4 - es-module-lexer: 2.0.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.1 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(webpack@5.104.1) - watchpack: 2.5.1 - webpack-sources: 3.3.3 + '@vitest/expect': 1.6.1 + '@vitest/runner': 1.6.1 + '@vitest/snapshot': 1.6.1 + '@vitest/spy': 1.6.1 + '@vitest/utils': 1.6.1 + acorn-walk: 8.3.5 + chai: 4.5.0 + debug: 4.4.3 + execa: 8.0.1 + local-pkg: 0.5.1 + magic-string: 0.30.21 + pathe: 1.1.2 + picocolors: 1.1.1 + std-env: 3.10.0 + strip-literal: 2.1.1 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.21(@types/node@20.19.41)(terser@5.46.0) + vite-node: 1.6.1(@types/node@20.19.41)(terser@5.46.0) + why-is-node-running: 2.3.0 optionalDependencies: - webpack-cli: 5.1.4(webpack@5.104.1) + '@types/node': 20.19.41 transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - - which-boxed-primitive@1.1.1: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.2 - is-number-object: 1.1.1 - is-string: 1.1.1 - is-symbol: 1.1.1 - - which-builtin-type@1.2.1: - dependencies: - call-bound: 1.0.4 - function.prototype.name: 1.1.8 - has-tostringtag: 1.0.2 - is-async-function: 2.1.1 - is-date-object: 1.1.0 - is-finalizationregistry: 1.1.1 - is-generator-function: 1.1.2 - is-regex: 1.2.1 - is-weakref: 1.1.1 - isarray: 2.0.5 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.20 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.4 - - which-typed-array@1.1.20: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - - which@1.3.1: - dependencies: - isexe: 2.0.0 + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser which@2.0.2: dependencies: isexe: 2.0.0 - which@3.0.1: + why-is-node-running@2.3.0: dependencies: - isexe: 2.0.0 - - wildcard@2.0.1: {} + siginfo: 2.0.0 + stackback: 0.0.2 word-wrap@1.2.5: {} - workerpool@6.5.1: {} - wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -6000,35 +2888,8 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrappy@1.0.2: {} - - ws@8.18.3: {} - - y18n@5.0.8: {} - - yallist@3.1.1: {} - yaml@2.8.2: {} - yargs-parser@20.2.9: {} - - yargs-unparser@2.0.0: - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - yocto-queue@0.1.0: {} yocto-queue@1.2.2: {} diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..4fb6019 --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,25 @@ +import esbuild from 'rollup-plugin-esbuild'; +import { dts } from 'rollup-plugin-dts'; + +const input = 'src/index.ts'; + +export default [ + { + input, + output: [ + { file: 'dist/js-xdr.mjs', format: 'es', sourcemap: true }, + { + file: 'dist/js-xdr.cjs', + format: 'cjs', + sourcemap: true, + exports: 'named' + } + ], + plugins: [esbuild({ target: 'es2022', sourceMap: true })] + }, + { + input, + output: { file: 'dist/js-xdr.d.ts', format: 'es' }, + plugins: [dts()] + } +]; diff --git a/test/.eslintrc.js b/test/.eslintrc.js deleted file mode 100644 index e1fd8b1..0000000 --- a/test/.eslintrc.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { - env: { - mocha: true, - es2022: true - }, - parserOptions: { ecmaVersion: 2022, sourceType: 'module' }, - globals: { - XDR: true, - chai: true, - sinon: true, - expect: true, - stub: true, - spy: true - }, - rules: { - 'no-unused-vars': 0, - 'node/no-unsupported-features/es-syntax': 0 - } -}; diff --git a/test/setup.js b/test/setup.js deleted file mode 100644 index 35394b9..0000000 --- a/test/setup.js +++ /dev/null @@ -1,23 +0,0 @@ -if (typeof global === 'undefined') { - // eslint-disable-next-line no-undef - window.global = window; -} -global['XDR'] = require('../src'); -global.chai = require('chai'); -global.sinon = require('sinon'); -global.chai.use(require('sinon-chai')); - -global.expect = global.chai.expect; - -exports.mochaHooks = { - beforeEach: function () { - this.sandbox = global.sinon.createSandbox(); - global.stub = this.sandbox.stub.bind(this.sandbox); - global.spy = this.sandbox.spy.bind(this.sandbox); - }, - afterEach: function () { - delete global.stub; - delete global.spy; - this.sandbox.restore(); - } -}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c26d7c0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022"], + "strict": true, + "noUncheckedIndexedAccess": true, + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "isolatedModules": true, + "allowImportingTsExtensions": false, + "noEmit": true, + "types": ["node"] + }, + "include": ["src/**/*", "test/**/*", "vitest.config.ts"] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..c0a3f71 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['test/unit/**/*.test.ts'] + } +}); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index ed33f2c..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,57 +0,0 @@ -const path = require('path'); -const webpack = require('webpack'); -const TerserPlugin = require('terser-webpack-plugin'); - -const browserBuild = !process.argv.includes('--mode=development'); - -module.exports = function () { - const mode = browserBuild ? 'production' : 'development'; - const config = { - mode, - devtool: 'source-map', - entry: { - xdr: [path.join(__dirname, '/src/browser.js')] - }, - output: { - path: path.join(__dirname, browserBuild ? './dist' : './lib'), - filename: '[name].js', - library: { - name: 'XDR', - type: 'umd' - }, - globalObject: 'this' - }, - module: { - rules: [ - { - test: /\.js$/, - loader: 'babel-loader', - exclude: /node_modules/ - } - ] - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(mode) - }) - ] - }; - if (browserBuild) { - config.optimization = { - minimize: true, - minimizer: [ - new TerserPlugin({ - parallel: true - }) - ] - }; - config.plugins.push( - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'] - }) - ); - } else { - config.target = 'node'; - } - return config; -}; From d188fc3ce1c1954d51a9c6bbd5eb8a08d7ccbeef Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 13:39:09 -0700 Subject: [PATCH 04/22] refactor: optimize Writer class to use static buffer and ensure capacity management --- src/core/writer.ts | 34 +++++++++++++++++++++++++++++----- test/unit/writer.test.ts | 14 ++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/core/writer.ts b/src/core/writer.ts index 73a18cb..2179213 100644 --- a/src/core/writer.ts +++ b/src/core/writer.ts @@ -1,15 +1,23 @@ import { paddingLength, viewFor } from './helpers.js'; +const INITIAL_BUFFER_SIZE = 8192; + export class Writer { - readonly #chunks: number[] = []; + #buffer = new Uint8Array(INITIAL_BUFFER_SIZE); + #offset = 0; writeBytes(bytes: Uint8Array): void { - this.#chunks.push(...bytes); + this.#ensureCapacity(bytes.length); + this.#buffer.set(bytes, this.#offset); + this.#offset += bytes.length; } writePadding(length: number): void { - for (let i = 0; i < paddingLength(length); i += 1) { - this.#chunks.push(0); + const padding = paddingLength(length); + if (padding > 0) { + this.#ensureCapacity(padding); + this.#buffer.fill(0, this.#offset, this.#offset + padding); + this.#offset += padding; } } @@ -50,6 +58,22 @@ export class Writer { } toUint8Array(): Uint8Array { - return Uint8Array.from(this.#chunks); + return this.#buffer.slice(0, this.#offset); + } + + #ensureCapacity(additionalBytes: number): void { + const requiredLength = this.#offset + additionalBytes; + if (requiredLength <= this.#buffer.length) { + return; + } + + let nextLength = this.#buffer.length; + while (nextLength < requiredLength) { + nextLength *= 2; + } + + const nextBuffer = new Uint8Array(nextLength); + nextBuffer.set(this.#buffer); + this.#buffer = nextBuffer; } } diff --git a/test/unit/writer.test.ts b/test/unit/writer.test.ts index 1736e08..034ccfb 100644 --- a/test/unit/writer.test.ts +++ b/test/unit/writer.test.ts @@ -37,6 +37,20 @@ describe('Writer', () => { expect(toArray(writer.toUint8Array())).toEqual([1, 2, 3, 4]); }); + it('writes byte chunks larger than the initial buffer', () => { + const writer = new Writer(); + const payload = new Uint8Array(200000); + payload[0] = 1; + payload[payload.length - 1] = 255; + + writer.writeBytes(payload); + + const output = writer.toUint8Array(); + expect(output).toHaveLength(payload.length); + expect(output[0]).toBe(1); + expect(output[output.length - 1]).toBe(255); + }); + it('pads to the next 4-byte boundary based on length', () => { const cases: Array<[number, number[]]> = [ [0, []], From 7525f2313b44d5f54f5af7c2452717bbfcdcf445 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 13:39:51 -0700 Subject: [PATCH 05/22] add missing exports --- src/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6546bbb..0785ca2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ // Bases (XdrValue, BytesValue, …) and the schema-builder primitives. -export { XdrError } from './core/error.js'; - +export { BaseType } from './core/xdr-type.js'; +export type { DecodeOptions } from './core/xdr-type.js'; +export type { Infer } from './core/xdr-type.js'; export { Writer } from './core/writer.js'; export { Reader } from './core/reader.js'; - +export { XdrError } from './core/error.js'; export type { XdrType } from './core/xdr-type.js'; -export { BaseType } from './core/xdr-type.js'; export { array } from './types/array.js'; export { bool } from './types/bool.js'; @@ -22,6 +22,6 @@ export { string } from './types/string.js'; export { struct } from './types/struct.js'; export { uint32 } from './types/uint32.js'; export { uint64 } from './types/uint64.js'; -export { union } from './types/union.js'; +export { union, case, field } from './types/union.js'; export { varOpaque } from './types/var-opaque.js'; export { void } from './types/void.js'; From 3ddf1bf094e22a8093f5e17f97d84e484bfe9a8b Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 14:17:05 -0700 Subject: [PATCH 06/22] add validateXdr method to XdrType interface and BaseType class --- src/core/xdr-type.ts | 10 ++++++++++ test/unit/bool.test.ts | 16 ++++++++++++++++ test/unit/reader.test.ts | 7 +++++++ 3 files changed, 33 insertions(+) diff --git a/src/core/xdr-type.ts b/src/core/xdr-type.ts index 4890f10..2db3be5 100644 --- a/src/core/xdr-type.ts +++ b/src/core/xdr-type.ts @@ -12,6 +12,7 @@ export interface XdrType { readonly kind: string; encode(value: T): Uint8Array; decode(input: Uint8Array, options?: DecodeOptions): T; + validateXdr(input: Uint8Array, options?: DecodeOptions): boolean; validate(value: unknown): value is T; _read(reader: Reader, path: string): T; _write(value: T, writer: Writer, path: string): void; @@ -40,6 +41,15 @@ export abstract class BaseType implements XdrType { return value; } + validateXdr(input: Uint8Array, options?: DecodeOptions): boolean { + try { + this.decode(input, options); + return true; + } catch { + return false; + } + } + validate(value: unknown): value is T { try { const writer = new Writer(); diff --git a/test/unit/bool.test.ts b/test/unit/bool.test.ts index c0c5dad..3e7e37a 100644 --- a/test/unit/bool.test.ts +++ b/test/unit/bool.test.ts @@ -46,4 +46,20 @@ describe('bool', () => { expect(schema.validate(undefined)).toBe(false); }); }); + + describe('validateXdr', () => { + it('accepts valid encoded XDR bytes', () => { + expect(schema.validateXdr(bytes([0, 0, 0, 0]))).toBe(true); + expect(schema.validateXdr(bytes([0, 0, 0, 1]))).toBe(true); + }); + + it('rejects invalid encoded XDR bytes', () => { + expect(schema.validateXdr(bytes([0, 0, 0, 2]))).toBe(false); + expect(schema.validateXdr(bytes([0, 0]))).toBe(false); + }); + + it('rejects encoded XDR bytes with trailing data', () => { + expect(schema.validateXdr(bytes([0, 0, 0, 1, 0]))).toBe(false); + }); + }); }); diff --git a/test/unit/reader.test.ts b/test/unit/reader.test.ts index f73730a..4613ba1 100644 --- a/test/unit/reader.test.ts +++ b/test/unit/reader.test.ts @@ -87,4 +87,11 @@ describe('Reader', () => { ); expect(nested.decode(wire, { maxDepth: 2 })).toBe(5); }); + + it('validateXdr honors the maxDepth option', () => { + const nested = option(option(int32())); + const wire = bytes([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5]); + expect(nested.validateXdr(wire, { maxDepth: 1 })).toBe(false); + expect(nested.validateXdr(wire, { maxDepth: 2 })).toBe(true); + }); }); From 7b0c982ac069d49e4ed1cc75772a88245bb1f531 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 15:29:22 -0700 Subject: [PATCH 07/22] add detailed JSDoc comments for XDR types and core classes --- src/core/error.ts | 6 ++++ src/core/reader.ts | 7 ++++ src/core/writer.ts | 8 +++++ src/core/xdr-type.ts | 72 ++++++++++++++++++++++++++++++++++++++++ src/types/array.ts | 25 ++++++++++++++ src/types/bool.ts | 9 +++++ src/types/double.ts | 9 +++++ src/types/enum.ts | 21 ++++++++++++ src/types/fixed-array.ts | 10 ++++++ src/types/float.ts | 9 +++++ src/types/int32.ts | 10 ++++++ src/types/int64.ts | 10 ++++++ src/types/lazy.ts | 19 +++++++++++ src/types/opaque.ts | 10 ++++++ src/types/option.ts | 10 ++++++ src/types/string.ts | 23 +++++++++---- src/types/struct.ts | 23 +++++++++++++ src/types/uint32.ts | 9 +++++ src/types/uint64.ts | 10 ++++++ src/types/union.ts | 58 ++++++++++++++++++++++++++++++++ src/types/var-opaque.ts | 9 +++++ src/types/void.ts | 9 +++++ 22 files changed, 369 insertions(+), 7 deletions(-) diff --git a/src/core/error.ts b/src/core/error.ts index 7cdfe58..5b255f1 100644 --- a/src/core/error.ts +++ b/src/core/error.ts @@ -1,3 +1,9 @@ +/** + * Error thrown for schema definition problems and XDR encode/decode failures. + * + * Catch this when you need to distinguish malformed XDR or invalid values from + * unrelated application errors. + */ export class XdrError extends Error { constructor(message: string) { super(message); diff --git a/src/core/reader.ts b/src/core/reader.ts index 4175c9e..738e95f 100644 --- a/src/core/reader.ts +++ b/src/core/reader.ts @@ -3,6 +3,13 @@ import { paddingLength, viewFor } from './helpers.js'; export const DEFAULT_MAX_DEPTH = 200; +/** + * Low-level reader for raw XDR bytes. + * + * `Reader` advances through one byte sequence, reads big-endian primitive + * values, verifies zero padding, and tracks nested schema depth. Schema authors + * use it from `_read`; application code usually calls `schema.decode(bytes)`. + */ export class Reader { #offset = 0; #depth = 0; diff --git a/src/core/writer.ts b/src/core/writer.ts index 2179213..6563114 100644 --- a/src/core/writer.ts +++ b/src/core/writer.ts @@ -2,6 +2,14 @@ import { paddingLength, viewFor } from './helpers.js'; const INITIAL_BUFFER_SIZE = 8192; +/** + * Low-level writer for raw XDR bytes. + * + * `Writer` appends big-endian primitive values to a growable byte buffer and + * can add the zero padding required by XDR's 4-byte alignment rules. Schema + * authors use it from `_write`; application code usually calls + * `schema.encode(value)`. + */ export class Writer { #buffer = new Uint8Array(INITIAL_BUFFER_SIZE); #offset = 0; diff --git a/src/core/xdr-type.ts b/src/core/xdr-type.ts index 2db3be5..9a36db9 100644 --- a/src/core/xdr-type.ts +++ b/src/core/xdr-type.ts @@ -3,23 +3,95 @@ import { Writer } from './writer.js'; export const UNBOUNDED_MAX_LENGTH = 4294967295; +/** + * Options for decoding XDR bytes. + */ export interface DecodeOptions { + /** + * Maximum number of nested schemas that may be entered while decoding. + * + * Lower this when decoding untrusted recursive data. If the limit is + * exceeded, `decode` throws and `validateXdr` returns `false`. + */ readonly maxDepth?: number; } +/** + * Runtime schema for one XDR type. + * + * `T` is the JavaScript value shape used by this schema. For example, + * `int32()` is `XdrType`, `string(64)` is `XdrType`, and + * `struct(...)` is `XdrType<{ ... }>` rather than a generated class instance. + */ export interface XdrType { + /** + * Schema name when the type was declared with one, such as a struct, union, + * or enum name. + */ readonly name: string | undefined; + /** + * Internal type kind used in diagnostics and schema introspection. + */ readonly kind: string; + /** + * Encodes a JavaScript value to raw XDR bytes. + * + * Throws `XdrError` if the value does not match this schema. + */ encode(value: T): Uint8Array; + /** + * Decodes raw XDR bytes into a JavaScript value. + * + * Decoding must consume the entire input. Trailing bytes, malformed padding, + * unknown enum values, and schema mismatches throw `XdrError`. + */ decode(input: Uint8Array, options?: DecodeOptions): T; + /** + * Returns whether raw XDR bytes can be decoded by this schema. + * + * This is the non-throwing form of `decode`; it validates encoded bytes, not + * a JavaScript value. + */ validateXdr(input: Uint8Array, options?: DecodeOptions): boolean; + /** + * Returns whether a JavaScript value can be encoded by this schema. + * + * This is value validation. Use `validateXdr` when you already have encoded + * XDR bytes. + */ validate(value: unknown): value is T; + /** + * Reads this schema from an existing streaming reader. + * + * Intended for schema composition; most callers should use `decode`. + */ _read(reader: Reader, path: string): T; + /** + * Writes this schema to an existing streaming writer. + * + * Intended for schema composition; most callers should use `encode`. + */ _write(value: T, writer: Writer, path: string): void; } +/** + * Extracts the JavaScript value type from a schema. + * + * @example + * ```ts + * const Color = struct('Color', { red: uint32(), green: uint32(), blue: uint32() }); + * type Color = Infer; + * ``` + */ export type Infer = T extends XdrType ? V : never; +/** + * Base implementation for concrete schema classes. + * + * Subclasses define streaming `_read` and `_write` behavior. `BaseType` + * supplies complete-buffer `encode`, `decode`, `validateXdr`, and `validate` + * implementations with consistent error handling. + */ export abstract class BaseType implements XdrType { abstract readonly kind: string; readonly name: string | undefined; diff --git a/src/types/array.ts b/src/types/array.ts index d49010f..dcdb58d 100644 --- a/src/types/array.ts +++ b/src/types/array.ts @@ -4,6 +4,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; import { assertArray, assertLength } from '../core/helpers.js'; +/** + * Reads and writes an XDR variable-length array body. + */ class ArrayType extends BaseType { readonly kind = 'array'; readonly element: XdrType; @@ -43,6 +46,16 @@ class ArrayType extends BaseType { } } +/** + * Creates a schema for an XDR variable-length array. + * + * Values are JavaScript arrays. On the wire, the array is encoded as a uint32 + * element count followed by each element. Encoding and decoding reject lengths + * greater than `maxLength`. + * + * Use `fixedArray` for XDR arrays with a compile-time length and no length + * prefix. + */ export function array>( element: T, maxLength: number @@ -50,6 +63,12 @@ export function array>( return new ArrayType(element, maxLength) as XdrType[]>; } +/** + * Reads `length` array elements without reading a length prefix. + * + * This is a schema-composition helper used by `array` and `fixedArray`; + * application code should normally use `schema.decode(bytes)`. + */ export function readArray( reader: Reader, length: number, @@ -63,6 +82,12 @@ export function readArray( return values; } +/** + * Writes array elements without writing a length prefix. + * + * This is a schema-composition helper used by `array` and `fixedArray`; + * application code should normally use `schema.encode(value)`. + */ export function writeArray( values: T[], writer: Writer, diff --git a/src/types/bool.ts b/src/types/bool.ts index 01adab7..737efea 100644 --- a/src/types/bool.ts +++ b/src/types/bool.ts @@ -3,6 +3,9 @@ import type { Reader } from '../core/reader.js'; import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; +/** + * Reads and writes XDR booleans as uint32 discriminants. + */ class BoolType extends BaseType { readonly kind = 'bool'; @@ -23,6 +26,12 @@ class BoolType extends BaseType { export const BOOL_TYPE = new BoolType(); +/** + * Creates a schema for the XDR boolean primitive. + * + * Values are JavaScript booleans. On the wire, `false` is encoded as `0` and + * `true` is encoded as `1`; decoding rejects any other discriminant. + */ export function bool(): XdrType { return BOOL_TYPE; } diff --git a/src/types/double.ts b/src/types/double.ts index 17cf450..cad7bf3 100644 --- a/src/types/double.ts +++ b/src/types/double.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertFiniteNumber } from '../core/helpers.js'; +/** + * Reads and writes XDR double-precision floating point values. + */ class DoubleType extends BaseType { readonly kind = 'double'; @@ -16,6 +19,12 @@ class DoubleType extends BaseType { } } +/** + * Creates a schema for the XDR double-precision floating point primitive. + * + * Values are finite JavaScript numbers encoded as IEEE-754 binary64 values. + * Encoding rejects `NaN`, `Infinity`, and `-Infinity`. + */ export function double(): XdrType { return new DoubleType(); } diff --git a/src/types/enum.ts b/src/types/enum.ts index 4d7846a..fd16ffd 100644 --- a/src/types/enum.ts +++ b/src/types/enum.ts @@ -23,6 +23,12 @@ const RESERVED_ENUM_MEMBER_NAMES = new Set([ '_write' ]); +/** + * Reads and writes XDR enum values. + * + * Runtime values are numeric discriminants; member names are metadata exposed + * on the public enum schema. + */ export class EnumType> extends BaseType< EnumMember > { @@ -61,6 +67,21 @@ export class EnumType> extends BaseType< } } +/** + * Creates a schema for an XDR enum. + * + * Values are the numeric wire discriminants. The returned schema also exposes + * each member name as a numeric property, so callers can use named constants + * while storing numbers in encoded data. Duplicate wire values and member names + * that collide with schema properties are rejected. + * + * @example + * ```ts + * const Color = enumType('Color', { red: 0, green: 1, blue: 2 }); + * Color.encode(Color.green); + * Color.decode(bytes); // 1 + * ``` + */ export function enumType< Name extends string, Values extends Record diff --git a/src/types/fixed-array.ts b/src/types/fixed-array.ts index b435ff2..61fce8c 100644 --- a/src/types/fixed-array.ts +++ b/src/types/fixed-array.ts @@ -5,6 +5,9 @@ import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; import { assertArray, assertLength } from '../core/helpers.js'; import { readArray, writeArray } from './array.js'; +/** + * Reads and writes XDR arrays with a fixed element count. + */ class FixedArrayType extends BaseType { readonly kind = 'fixedArray'; readonly element: XdrType; @@ -37,6 +40,13 @@ class FixedArrayType extends BaseType { } } +/** + * Creates a schema for an XDR fixed-length array. + * + * Values are JavaScript arrays whose length must exactly equal `length`. The + * wire format contains only the element bytes; unlike `array`, no count is + * encoded. + */ export function fixedArray>( element: T, length: number diff --git a/src/types/float.ts b/src/types/float.ts index 32bb71e..045558d 100644 --- a/src/types/float.ts +++ b/src/types/float.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertFiniteNumber } from '../core/helpers.js'; +/** + * Reads and writes XDR single-precision floating point values. + */ class FloatType extends BaseType { readonly kind = 'float'; @@ -16,6 +19,12 @@ class FloatType extends BaseType { } } +/** + * Creates a schema for the XDR single-precision floating point primitive. + * + * Values are finite JavaScript numbers encoded as IEEE-754 binary32 values. + * Encoding rejects `NaN`, `Infinity`, and `-Infinity`. + */ export function float(): XdrType { return new FloatType(); } diff --git a/src/types/int32.ts b/src/types/int32.ts index 6a04d51..7ecc93d 100644 --- a/src/types/int32.ts +++ b/src/types/int32.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertIntRange } from '../core/helpers.js'; +/** + * Reads and writes signed 32-bit XDR integers. + */ class IntType extends BaseType { readonly kind = 'int32'; @@ -16,6 +19,13 @@ class IntType extends BaseType { } } +/** + * Creates a schema for a signed 32-bit XDR integer. + * + * Values are JavaScript numbers in the inclusive range + * `-2147483648..2147483647`. Encoding rejects non-integers and out-of-range + * values. + */ export function int32(): XdrType { return new IntType(); } diff --git a/src/types/int64.ts b/src/types/int64.ts index fbbb604..0c02e3e 100644 --- a/src/types/int64.ts +++ b/src/types/int64.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertBigIntRange } from '../core/helpers.js'; +/** + * Reads and writes signed 64-bit XDR integers. + */ class HyperType extends BaseType { readonly kind = 'int64'; @@ -16,6 +19,13 @@ class HyperType extends BaseType { } } +/** + * Creates a schema for a signed 64-bit XDR integer. + * + * Values are native `bigint`s in the inclusive range + * `-(2n ** 63n)..(2n ** 63n - 1n)`. Encoding rejects numbers, strings, and + * out-of-range bigint values. + */ export function int64(): XdrType { return new HyperType(); } diff --git a/src/types/lazy.ts b/src/types/lazy.ts index fa3c00d..24ba357 100644 --- a/src/types/lazy.ts +++ b/src/types/lazy.ts @@ -2,6 +2,9 @@ import type { Reader } from '../core/reader.js'; import type { Writer } from '../core/writer.js'; import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; +/** + * Defers schema lookup until read/write time. + */ class LazyType extends BaseType { readonly kind = 'lazy'; readonly getSchema: () => XdrType; @@ -25,6 +28,22 @@ class LazyType extends BaseType { } } +/** + * Creates a schema that resolves another schema lazily. + * + * Use this when a schema needs to reference another schema that is declared + * later, including self-recursive structures. The callback runs when the value + * is encoded or decoded, not when the lazy schema is created. + * + * @example + * ```ts + * type Node = { value: number; next: Node | null }; + * const Node = struct('Node', { + * value: int32(), + * next: option(lazy(() => Node)), + * }); + * ``` + */ export function lazy>( getSchema: () => T ): XdrType> { diff --git a/src/types/opaque.ts b/src/types/opaque.ts index ae93a87..1650c22 100644 --- a/src/types/opaque.ts +++ b/src/types/opaque.ts @@ -4,6 +4,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertLength, assertUint8Array } from '../core/helpers.js'; +/** + * Reads and writes fixed-length XDR opaque byte sequences. + */ class OpaqueType extends BaseType { readonly kind = 'opaque'; @@ -30,6 +33,13 @@ class OpaqueType extends BaseType { } } +/** + * Creates a schema for an XDR fixed-length opaque byte sequence. + * + * Values are `Uint8Array`s whose length must exactly equal `length`. The wire + * format contains the raw bytes followed by zero padding to a 4-byte boundary; + * no length prefix is encoded. + */ export function opaque(length: number, name?: string): XdrType { return new OpaqueType(length, name); } diff --git a/src/types/option.ts b/src/types/option.ts index 3bc88e8..c34cc78 100644 --- a/src/types/option.ts +++ b/src/types/option.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; import { BOOL_TYPE } from './bool.js'; +/** + * Reads and writes XDR optional values. + */ class OptionType extends BaseType { readonly kind = 'option'; readonly element: XdrType; @@ -30,6 +33,13 @@ class OptionType extends BaseType { } } +/** + * Creates a schema for an XDR optional value. + * + * Values are represented as either the element value or `null`. The wire format + * writes a boolean presence flag first; when the flag is `true`, the element + * value follows. + */ export function option>( element: T ): XdrType | null> { diff --git a/src/types/string.ts b/src/types/string.ts index 55f8d23..e4fd6d0 100644 --- a/src/types/string.ts +++ b/src/types/string.ts @@ -5,14 +5,9 @@ import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertLength } from '../core/helpers.js'; /** - * XDR `string` — length-prefixed bytes, 4-byte padded. + * Reads and writes XDR `string` values as bytes. * - * Schema primitive: reads/writes raw `Uint8Array`. Charset handling is a - * higher-layer concern (see e.g. `values/xdr-string.ts` for a wrapper that - * exposes ergonomic string semantics on top of these bytes). Keeping this - * layer charset-free means the `types/` schema primitives have no dependency - * on the consumer-facing `values/` classes — the runtime can be lifted out - * of this repo into a standalone XDR library without modification. + * Charset handling is deliberately outside this schema layer. */ class StringType extends BaseType { readonly kind = 'string'; @@ -49,6 +44,20 @@ class StringType extends BaseType { } } +/** + * Creates a schema for an XDR string. + * + * Values are raw bytes in a `Uint8Array`, not JavaScript strings. The wire + * format is a uint32 byte length, the bytes, then zero padding to a 4-byte + * boundary. Convert text at the boundary with `TextEncoder` and `TextDecoder`. + * + * @example + * ```ts + * const Name = string(64); + * const encoded = Name.encode(new TextEncoder().encode('hello')); + * const value = new TextDecoder().decode(Name.decode(encoded)); + * ``` + */ function string_(maxLength: number): XdrType { return new StringType(maxLength); } diff --git a/src/types/struct.ts b/src/types/struct.ts index 4351274..1c0e0bd 100644 --- a/src/types/struct.ts +++ b/src/types/struct.ts @@ -4,6 +4,11 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; import { isPlainObject } from '../core/helpers.js'; +/** + * Reads and writes XDR structs. + * + * Runtime values are plain objects; there are no generated accessor classes. + */ class StructType< Shape extends Record> > extends BaseType<{ @@ -53,6 +58,24 @@ class StructType< } } +/** + * Creates a schema for an XDR struct. + * + * Values are plain JavaScript objects whose properties match the `fields` + * object. Fields are encoded in the insertion order of `fields`, so declare + * them in wire order. Encoding rejects missing fields and non-object values. + * + * @example + * ```ts + * const Color = struct('Color', { + * red: uint32(), + * green: uint32(), + * blue: uint32(), + * }); + * + * Color.encode({ red: 1, green: 2, blue: 3 }); + * ``` + */ export function struct< Name extends string, Shape extends Record> diff --git a/src/types/uint32.ts b/src/types/uint32.ts index 0d342cf..4b57353 100644 --- a/src/types/uint32.ts +++ b/src/types/uint32.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertIntRange } from '../core/helpers.js'; +/** + * Reads and writes unsigned 32-bit XDR integers. + */ class UIntType extends BaseType { readonly kind = 'uint32'; @@ -16,6 +19,12 @@ class UIntType extends BaseType { } } +/** + * Creates a schema for an unsigned 32-bit XDR integer. + * + * Values are JavaScript numbers in the inclusive range `0..4294967295`. + * Encoding rejects non-integers and out-of-range values. + */ export function uint32(): XdrType { return new UIntType(); } diff --git a/src/types/uint64.ts b/src/types/uint64.ts index f16eeeb..0a3c106 100644 --- a/src/types/uint64.ts +++ b/src/types/uint64.ts @@ -3,6 +3,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertBigIntRange } from '../core/helpers.js'; +/** + * Reads and writes unsigned 64-bit XDR integers. + */ class UHyperType extends BaseType { readonly kind = 'uint64'; @@ -16,6 +19,13 @@ class UHyperType extends BaseType { } } +/** + * Creates a schema for an unsigned 64-bit XDR integer. + * + * Values are native `bigint`s in the inclusive range + * `0n..(2n ** 64n - 1n)`. Encoding rejects numbers, strings, and out-of-range + * bigint values. + */ export function uint64(): XdrType { return new UHyperType(); } diff --git a/src/types/union.ts b/src/types/union.ts index 065a87a..3245339 100644 --- a/src/types/union.ts +++ b/src/types/union.ts @@ -4,13 +4,30 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type Infer, type XdrType } from '../core/xdr-type.js'; import { isPlainObject } from '../core/helpers.js'; +/** + * Named payload field for a non-void union arm. + * + * If a union case uses `field('code', int32())`, values for that case carry the + * payload as `{ type: discriminant, code: number }`. + */ export type Field> = { readonly kind: 'field'; readonly name: Name; readonly schema: T; }; type VoidArm = XdrType; + +/** + * Payload schema for a union arm. + * + * Use `void()` for arms with no payload, or `field(name, schema)` for arms that + * carry one named payload value. + */ export type UnionArm = VoidArm | Field>; + +/** + * Mapping between one discriminator value and the arm selected by that value. + */ export type UnionCase = { readonly name: Name; readonly discriminant: Disc; @@ -40,6 +57,12 @@ type UnionValue< const DEFAULT_CASE_NAME = 'default'; +/** + * Reads and writes XDR unions. + * + * Runtime values are plain tagged objects. There are no generated static arm + * constructors or accessor methods. + */ class UnionType< Switch extends XdrType, Cases extends readonly UnionCase, UnionArm>[], @@ -148,6 +171,12 @@ class UnionType< } } +/** + * Creates a named payload field for a non-void union arm. + * + * The field name becomes the payload property on the JavaScript value for that + * arm. It must not match the union's discriminator property. + */ export function field>( name: Name, schema: T @@ -155,6 +184,12 @@ export function field>( return { kind: 'field', name, schema }; } +/** + * Creates one discriminator-to-arm mapping for a union schema. + * + * The discriminator must be a value accepted by the `switchOn` schema. For enum + * switches, pass the enum member value such as `ResultType.ok`. + */ function case_< Name extends string, Disc extends string | number | boolean, @@ -165,6 +200,29 @@ function case_< export { case_ as case }; +/** + * Creates a schema for an XDR union. + * + * Values are plain tagged objects. The discriminator is stored under `type` by + * default, or under `switchKey` when provided. Void arms contain only the + * discriminator. Non-void arms also contain the payload property declared with + * `field`. + * + * @example + * ```ts + * const ResultType = enumType('ResultType', { ok: 0, error: 1 }); + * const Result = union('Result', { + * switchOn: ResultType, + * cases: [ + * case('ok', ResultType.ok, void()), + * case('error', ResultType.error, field('code', int32())), + * ], + * }); + * + * Result.encode({ type: ResultType.error, code: 7 }); + * Result.decode(bytes); // { type: 1, code: 7 } + * ``` + */ export function union< Name extends string, Switch extends XdrType, diff --git a/src/types/var-opaque.ts b/src/types/var-opaque.ts index 8be0133..170b2d6 100644 --- a/src/types/var-opaque.ts +++ b/src/types/var-opaque.ts @@ -4,6 +4,9 @@ import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; import { assertLength, assertUint8Array } from '../core/helpers.js'; +/** + * Reads and writes variable-length XDR opaque byte sequences. + */ class VarOpaqueType extends BaseType { readonly kind = 'varOpaque'; @@ -37,6 +40,12 @@ class VarOpaqueType extends BaseType { } } +/** + * Creates a schema for an XDR variable-length opaque byte sequence. + * + * Values are `Uint8Array`s with length at most `maxLength`. The wire format is + * a uint32 byte length, the raw bytes, then zero padding to a 4-byte boundary. + */ export function varOpaque( maxLength: number, name?: string diff --git a/src/types/void.ts b/src/types/void.ts index 192c274..b265fc0 100644 --- a/src/types/void.ts +++ b/src/types/void.ts @@ -2,6 +2,9 @@ import { XdrError } from '../core/error.js'; import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; +/** + * Reads and writes the XDR void type. + */ class VoidType extends BaseType { readonly kind = 'void'; @@ -16,6 +19,12 @@ class VoidType extends BaseType { } } +/** + * Creates a schema for the XDR void type. + * + * The only valid JavaScript value is `undefined`, and the wire representation + * is zero bytes. This is most often used for void union arms. + */ function void_(): XdrType { return new VoidType(); } From fa86cfd024e2d40d61bc3ecfe234d2a9a5c1cb84 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 16:04:45 -0700 Subject: [PATCH 08/22] update examples to the new xdr schema --- examples/enum.js | 27 ---------------------- examples/enum.mjs | 26 +++++++++++++++++++++ examples/linked_list.js | 13 ----------- examples/linked_list.mjs | 15 ++++++++++++ examples/struct.js | 30 ------------------------ examples/struct.mjs | 30 ++++++++++++++++++++++++ examples/typedef.js | 14 ------------ examples/typedef.mjs | 15 ++++++++++++ examples/union.js | 39 -------------------------------- examples/union.mjs | 49 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 135 insertions(+), 123 deletions(-) delete mode 100644 examples/enum.js create mode 100644 examples/enum.mjs delete mode 100644 examples/linked_list.js create mode 100644 examples/linked_list.mjs delete mode 100644 examples/struct.js create mode 100644 examples/struct.mjs delete mode 100644 examples/typedef.js create mode 100644 examples/typedef.mjs delete mode 100644 examples/union.js create mode 100644 examples/union.mjs diff --git a/examples/enum.js b/examples/enum.js deleted file mode 100644 index 9729765..0000000 --- a/examples/enum.js +++ /dev/null @@ -1,27 +0,0 @@ -import * as XDR from '../src'; - -let xdr = XDR.config((xdr) => { - xdr.enum('Color', { - red: 0, - green: 1, - blue: 2 - }); - - xdr.enum('ResultType', { - ok: 0, - error: 1 - }); -}); - -console.log(xdr); - -// -console.log(xdr.Color.members()); // { red: 0, green: 1, blue: 2, } - -console.log(xdr.Color.fromName('red')); - -console.log(xdr.Color.fromXDR(Buffer.from([0, 0, 0, 0]))); // Color.red -console.log(xdr.Color.red().toXDR()); // Buffer -console.log(xdr.Color.red().toXDR('hex')); // - -console.log(xdr.Color.red() !== xdr.ResultType.ok()); diff --git a/examples/enum.mjs b/examples/enum.mjs new file mode 100644 index 0000000..d00bd65 --- /dev/null +++ b/examples/enum.mjs @@ -0,0 +1,26 @@ +import { enumType } from '../dist/js-xdr.mjs'; + +const Color = enumType('Color', { + red: 0, + green: 1, + blue: 2 +}); + +const ResultType = enumType('ResultType', { + ok: 0, + error: 1 +}); + +console.log(Color.name); // Color +console.log(Object.fromEntries(Color.nameByValue)); // { '0': 'red', '1': 'green', '2': 'blue' } + +console.log(Color.red); // 0 +console.log(Color.decode(Uint8Array.from([0, 0, 0, 0]))); // 0 + +const encoded = Color.encode(Color.red); +console.log(encoded); // Uint8Array +console.log(Buffer.from(encoded).toString('hex')); // 00000000 + +// Enum members are plain numbers in v5, so equal wire values compare equal +// across enum schemas. +console.log(Color.red === ResultType.ok); // true diff --git a/examples/linked_list.js b/examples/linked_list.js deleted file mode 100644 index 512a224..0000000 --- a/examples/linked_list.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as XDR from '../src'; - -let xdr = XDR.config((xdr) => { - xdr.struct('IntList', [ - ['value', xdr.int()], - ['rest', xdr.option(xdr.lookup('IntList'))] - ]); -}); - -let n1 = new xdr.IntList({ value: 1 }); -let n2 = new xdr.IntList({ value: 3, rest: n1 }); - -console.log(n2.toXDR()); diff --git a/examples/linked_list.mjs b/examples/linked_list.mjs new file mode 100644 index 0000000..2da35b2 --- /dev/null +++ b/examples/linked_list.mjs @@ -0,0 +1,15 @@ +import { int32, lazy, option, struct } from '../dist/js-xdr.mjs'; + +const IntList = struct('IntList', { + value: int32(), + rest: option(lazy(() => IntList)) +}); + +const n1 = { value: 1, rest: null }; +const n2 = { value: 3, rest: n1 }; + +const encoded = IntList.encode(n2); +const parsed = IntList.decode(encoded); + +console.log(encoded); +console.log(parsed); diff --git a/examples/struct.js b/examples/struct.js deleted file mode 100644 index 9349e2a..0000000 --- a/examples/struct.js +++ /dev/null @@ -1,30 +0,0 @@ -import * as XDR from '../src'; - -let xdr = XDR.config((xdr) => { - xdr.struct('Signature', [ - ['publicKey', xdr.opaque(32)], - ['data', xdr.opaque(32)] - ]); - - xdr.struct('Envelope', [ - ['body', xdr.varOpaque(1000)], - ['timestamp', xdr.uint()], - ['signature', xdr.lookup('Signature')] - ]); -}); - -let sig = new xdr.Signature(); -sig.publicKey(Buffer.alloc(32)); -sig.data(Buffer.from('00000000000000000000000000000000')); - -let env = new xdr.Envelope({ - signature: sig, - body: Buffer.from('hello'), - timestamp: Math.floor(new Date() / 1000) -}); - -let output = env.toXDR(); -let parsed = xdr.Envelope.fromXDR(output); - -console.log(env); -console.log(parsed); diff --git a/examples/struct.mjs b/examples/struct.mjs new file mode 100644 index 0000000..a13acc7 --- /dev/null +++ b/examples/struct.mjs @@ -0,0 +1,30 @@ +import { opaque, struct, uint32, varOpaque } from '../dist/js-xdr.mjs'; + +const Signature = struct('Signature', { + publicKey: opaque(32), + data: opaque(32) +}); + +const Envelope = struct('Envelope', { + body: varOpaque(1000), + timestamp: uint32(), + signature: Signature +}); + +const sig = { + publicKey: Buffer.alloc(32), + data: Buffer.from('00000000000000000000000000000000') +}; + +const env = { + signature: sig, + body: Buffer.from('hello'), + timestamp: Math.floor(Date.now() / 1000) +}; + +const output = Envelope.encode(env); +const parsed = Envelope.decode(output); + +console.log(env); +console.log(output); +console.log(parsed); diff --git a/examples/typedef.js b/examples/typedef.js deleted file mode 100644 index 5c05f73..0000000 --- a/examples/typedef.js +++ /dev/null @@ -1,14 +0,0 @@ -import * as XDR from '../src'; - -let xdr = XDR.config((xdr) => { - xdr.struct('Signature', [ - ['publicKey', xdr.opaque(32)], - ['data', xdr.opaque(32)] - ]); - - xdr.typedef('SignatureTypedef', xdr.lookup('Signature')); - xdr.typedef('IntTypedef', xdr.int()); -}); - -console.log(xdr.SignatureTypedef === xdr.Signature); -console.log(xdr.IntTypedef === XDR.Int); diff --git a/examples/typedef.mjs b/examples/typedef.mjs new file mode 100644 index 0000000..d46eb0a --- /dev/null +++ b/examples/typedef.mjs @@ -0,0 +1,15 @@ +import { int32, opaque, struct } from '../dist/js-xdr.mjs'; + +const Signature = struct('Signature', { + publicKey: opaque(32), + data: opaque(32) +}); + +// v5 has no typedef registry. Use normal JavaScript aliases. +const SignatureTypedef = Signature; +const IntTypedef = int32(); +const AlsoInt = IntTypedef; + +console.log(SignatureTypedef === Signature); // true +console.log(AlsoInt === IntTypedef); // true +console.log(IntTypedef.validate(123)); // true diff --git a/examples/union.js b/examples/union.js deleted file mode 100644 index 8beb6a8..0000000 --- a/examples/union.js +++ /dev/null @@ -1,39 +0,0 @@ -import * as XDR from '../src'; - -let xdr = XDR.config((xdr) => { - xdr.union('Result', { - switchOn: xdr.lookup('ResultType'), - switches: [ - ['ok', xdr.void()], - ['error', 'message'] - ], - // defaultArm: xdr.void(), - arms: { - message: xdr.string(100) - } - }); - - xdr.enum('ResultType', { - ok: 0, - error: 1, - nonsense: 2 - }); -}); - -let r = xdr.Result.ok(); -r.set('error', 'this is an error'); -r.message(); // => "this is an error" -r.get('message'); // => "this is an error" - -r.set(xdr.ResultType.ok()); -r.get(); // => undefined - -// r.set("nonsense"); -r.get(); // => undefined - -let output = r.toXDR(); -let parsed = xdr.Result.fromXDR(output); - -console.log(r); -console.log(r.arm()); -console.log(parsed); diff --git a/examples/union.mjs b/examples/union.mjs new file mode 100644 index 0000000..6e9a7c9 --- /dev/null +++ b/examples/union.mjs @@ -0,0 +1,49 @@ +import { + case as xdrCase, + enumType, + field, + int32, + string, + union, + void as xdrVoid +} from '../dist/js-xdr.mjs'; + +const ResultType = enumType('ResultType', { + ok: 0, + error: 1, + nonsense: 2 +}); + +const Result = union('Result', { + switchOn: ResultType, + cases: [ + xdrCase('ok', ResultType.ok, xdrVoid()), + xdrCase('error', ResultType.error, field('message', string(100))) + ] +}); + +const message = new TextEncoder().encode('this is an error'); +const errorResult = { type: ResultType.error, message }; + +console.log(errorResult.type); // 1 +console.log(new TextDecoder().decode(errorResult.message)); // this is an error + +const errorBytes = Result.encode(errorResult); +const parsedError = Result.decode(errorBytes); + +console.log(parsedError); +console.log(new TextDecoder().decode(parsedError.message)); + +const okResult = { type: ResultType.ok }; +const okBytes = Result.encode(okResult); +const parsedOk = Result.decode(okBytes); + +console.log(parsedOk); // { type: 0 } + +const Tagged = union('Tagged', { + switchOn: int32(), + cases: [xdrCase('known', 1, field('value', int32()))], + defaultArm: field('unknown', int32()) +}); + +console.log(Tagged.decode(Uint8Array.from([0, 0, 0, 99, 0, 0, 0, 7]))); From acd054e3c05be7c7edcd97fb66935f726c213ce9 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 16:05:21 -0700 Subject: [PATCH 09/22] add migration guide and update changelog / readme --- CHANGELOG.md | 23 +++ MIGRATION.md | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 61 +++----- 3 files changed, 434 insertions(+), 39 deletions(-) create mode 100644 MIGRATION.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 7613b90..acee41c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,29 @@ project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased +A complete rewrite of the library. The runtime `xdr.config(...)` schema-definition DSL has been replaced with a set of statically-typed, explicitly-declared schema builders, and the entire source has been migrated from JavaScript to TypeScript. See [MIGRATION.md](./MIGRATION.md) for a step-by-step upgrade guide. + +### Breaking Change +* **Removed the dynamic `config` / `TypeBuilder` DSL.** Schemas are no longer built at runtime by resolving a graph of `Reference`s inside `xdr.config(...)`. Instead, you compose schemas directly from exported builder functions: `array`, `bool`, `double`, `enumType`, `fixedArray`, `float`, `int32`, `int64`, `lazy`, `opaque`, `option`, `string`, `struct`, `uint32`, `uint64`, `union`, `varOpaque`, and `void`. Forward/recursive references that the old DSL resolved automatically are now expressed explicitly with `lazy(() => schema)`. +* **Renamed the encode/decode API.** `toXDR()` / `fromXDR()` → `encode()` / `decode()`. The `format` argument (`'raw' | 'hex' | 'base64'`) has been dropped — `encode` always returns a `Uint8Array` and `decode` always takes one. Callers that relied on hex/base64 strings or `Buffer` output must convert at the boundary. +* **Updated validation APIs.** `validateXDR(input, format)` is now `validateXdr(bytes, options)` and accepts raw `Uint8Array` bytes only; callers that used hex/base64 validation must convert at the boundary first. The new `validate(value)` method checks whether a JavaScript value can be encoded by the schema. +* **`encode()` returns `Uint8Array` instead of `Buffer`.** +* **Renamed the low-level streaming types.** `XdrReader` → `Reader` and `XdrWriter` → `Writer`. +* **Consolidated the error types.** `XdrReaderError`, `XdrWriterError`, `XdrDefinitionError`, and `XdrNotImplementedDefinitionError` are replaced by a single `XdrError`. +* **Renamed/reshaped the numeric types.** `Int`/`UnsignedInt` → `int32`/`uint32` (return JS `number`); `Hyper`/`UnsignedHyper`/`LargeInt` → `int64`/`uint64` (return `bigint`, with range-checked encoding). The `Quadruple` type has been removed (it was already unsupported and threw on use). +* **New package layout.** `main`/`module`/`browser` fields are replaced by an `exports` map exposing dual ESM (`dist/js-xdr.mjs`) and CommonJS (`dist/js-xdr.cjs`) builds plus generated type declarations (`dist/js-xdr.d.ts`). Output is now `dist/` only (the `lib/` build is gone), the package is marked `sideEffects: false`, and Node `>=20` is required. + +### Added +* **First-class TypeScript types.** Schemas carry full type information; `Infer` yields the encoded/decoded value type, and `struct`/`union`/`enumType` produce strongly-typed object, tagged-union, and named-member types. +* **`lazy(() => schema)`** builder for defining recursive and forward-referencing schemas. +* **`BaseType` / `XdrType`** are exported as the base class and interface for all schemas, along with a `DecodeOptions` `{ maxDepth }` option preserved from the prior recursion-depth guard. +* **`enumType` reserved-name and duplicate-value validation** — throws if a member name collides with a schema property (`name`, `kind`, `encode`, …) or if two members share a wire value. + +### Changed +* **Build chain modernized:** Webpack + Babel → Rollup + esbuild; output is a clean dual ESM/CJS bundle with `.d.ts` emission via `rollup-plugin-dts`. +* **Test framework replaced:** Mocha + Karma + Sinon + Chai → Vitest; the full unit suite was rewritten in TypeScript (`*.test.ts`). +* **Linting modernized:** ESLint 8 (airbnb-base config) → ESLint 9 flat config (`eslint.config.mjs`) with `typescript-eslint`; added `pnpm lint` and `pnpm typecheck` scripts. + ## [v4.0.0](https://github.com/stellar/js-xdr/compare/v3.1.2...v4.0.0) ### Breaking Change diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..7c62cd1 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,389 @@ +# Migration guide: v4 → v5 + +v5 is a ground-up rewrite. If you only consume generated schemas through a +package such as `@stellar/stellar-base` or `@stellar/stellar-sdk`, most schema +changes should be handled by that package's code generator. Upgrade that package +first, then use this guide only for code that builds XDR schemas or calls +`@stellar/js-xdr` directly. + +Two things changed at the conceptual level; everything else follows from them: + +1. **Schemas are plain values built from standalone functions**, not entries in + a runtime registry created by `xdr.config(...)`. +2. **Decoded values are plain JavaScript data**, not class instances with + accessor methods. There is no `color.red()` / `result.switch()` anymore; read + and write ordinary objects, numbers, arrays, `Uint8Array`s, `bigint`s, and + `null`. + +## Migration checklist + +1. Replace imports of generated classes and static type objects with schema + builder imports from `@stellar/js-xdr`. +2. Replace `xdr.config(...)`, `xdr.lookup(...)`, and `xdr.typedef(...)` with + explicitly declared schema constants. +3. Replace generated constructors, setters, getters, and union arm constructors + with plain JavaScript values. +4. Replace `toXDR(...)` / `fromXDR(...)` calls with `encode(...)` / + `decode(...)`. +5. Move hex, base64, and `Buffer` conversion to your application boundary. +6. Update validation calls: encoded bytes use `validateXdr(bytes)`; JavaScript + values use `validate(value)`. +7. Preserve old fixture bytes in tests and assert that v5 `decode` reads them + and v5 `encode` produces the same bytes for equivalent values. + +## Package / environment + +| v4 | v5 | +| --- | --- | +| `main: lib/xdr.js`, `browser: dist/xdr.js`, `module: src/index.js` | `exports` map with ESM (`dist/js-xdr.mjs`) + CJS (`dist/js-xdr.cjs`) + types (`dist/js-xdr.d.ts`) | +| `Buffer` in, `Buffer` out | `Uint8Array` in, `Uint8Array` out | +| Node `>=20` | Node `>=20` (unchanged) | + +`encode()` returns a `Uint8Array`. If you need a `Buffer`, hex, or base64, +convert at the boundary. The old `format` argument is gone. + +```ts +const bytes = Result.encode(value); +const asBuffer = Buffer.from(bytes); +const asBase64 = Buffer.from(bytes).toString('base64'); +const asHex = Buffer.from(bytes).toString('hex'); +``` + +## Defining schemas + +The `xdr.config(...)` DSL, `xdr.lookup(...)`, `xdr.typedef(...)`, and the central +type registry are removed. Define each schema as a value and reference it +directly. Define dependencies before the schemas that use them; for forward or +recursive references, wrap the reference in `lazy(() => ...)`. + +`typedef` no longer creates a registry entry. Use a normal variable alias: + +```ts +const Signature = opaque(32); +``` + +**Before (v4):** + +```js +import * as XDR from '@stellar/js-xdr'; + +const types = XDR.config((xdr) => { + xdr.enum('ResultType', { ok: 0, error: 1 }); + + xdr.struct('Color', [ + ['red', xdr.uint()], + ['green', xdr.uint()], + ['blue', xdr.uint()] + ]); + + xdr.union('Result', { + switchOn: xdr.lookup('ResultType'), + switches: [ + ['ok', XDR.Void], + ['error', 'code'] + ], + arms: { code: xdr.int() } + }); + + xdr.typedef('Signature', xdr.opaque(32)); +}); +``` + +**After (v5):** + +```ts +import { + enumType, struct, union, uint32, int32, opaque, + void as xdrVoid, field, case as xdrCase +} from '@stellar/js-xdr'; + +const ResultType = enumType('ResultType', { ok: 0, error: 1 }); + +const Color = struct('Color', { + red: uint32(), + green: uint32(), + blue: uint32() +}); + +const Result = union('Result', { + switchOn: ResultType, + cases: [ + xdrCase('ok', ResultType.ok, xdrVoid()), + xdrCase('error', ResultType.error, field('code', int32())) + ] +}); + +const Signature = opaque(32); +``` + +Notes: +- Struct fields are an **object** (`{ name: schema }`), not an array of pairs. + JavaScript property insertion order is the wire order. +- A union case is `case(name, discriminant, arm)`. The arm is either `void()` or + `field(payloadName, schema)`. +- Enum members are plain numbers: `ResultType.ok` is `0`, not + `ResultType.ok()`. +- A `defaultArm` is still supported: + `union(name, { switchOn, cases, defaultArm })`. +- The discriminator key on union values defaults to `type`; override it with + `switchKey`. + +### Type mapping + +| v4 | v5 | v5 value type | +| --- | --- | --- | +| `xdr.int()` / `XDR.Int` | `int32()` | `number` | +| `xdr.uint()` / `XDR.UnsignedInt` | `uint32()` | `number` | +| `XDR.Hyper` | `int64()` | `bigint` | +| `XDR.UnsignedHyper` | `uint64()` | `bigint` | +| `XDR.Float` | `float()` | `number` | +| `XDR.Double` | `double()` | `number` | +| `XDR.Quadruple` | removed | - | +| `XDR.Bool` | `bool()` | `boolean` | +| `new XDR.String(n)` | `string(maxLength)` | `Uint8Array` | +| `xdr.opaque(n)` | `opaque(length)` | `Uint8Array` | +| `xdr.varOpaque(n)` | `varOpaque(maxLength)` | `Uint8Array` | +| `xdr.array(child, n)` fixed | `fixedArray(element, length)` | `T[]` | +| `xdr.varArray(child, max)` variable | `array(element, maxLength)` | `T[]` | +| `xdr.option(child)` | `option(element)` | `T \| null` | +| `XDR.Void` | `void()` | `undefined` | +| `xdr.enum(...)` | `enumType(...)` | member number | +| `xdr.struct(...)` | `struct(...)` | plain object | +| `xdr.union(...)` | `union(...)` | tagged object | +| name lookup / forward ref | `lazy(() => schema)` | inferred | + +Watch out for two renames: +- **`array` is now the variable-length type** (was `varArray`); the fixed-length + one is `fixedArray` (was `array`). +- **`int64`/`uint64` are native `bigint`s**. There is no `Hyper` wrapper class, + so `.toBigInt()`, `.toString()`, and `Hyper.fromString(...)` no longer exist. + +### Strings are bytes + +`string(maxLength)` reads and writes a `Uint8Array`, not a JavaScript string. +Charset handling moved out of this layer. Encode/decode text yourself: + +```ts +const Name = string(64); +const bytes = Name.encode(new TextEncoder().encode('hello')); +const text = new TextDecoder().decode(Name.decode(bytes)); +``` + +## Working with values + +This is the largest behavioral change. v4 returned class instances whose fields +were accessor methods. v5 reads and writes plain JavaScript values. + +### Struct values + +**Before (v4):** + +```js +const c = new types.Color({ red: 1, green: 2, blue: 3 }); +c.red(); // 1 +c.red(9); // setter +const buf = c.toXDR(); // Buffer +``` + +**After (v5):** + +```ts +const c = { red: 1, green: 2, blue: 3 }; +c.red; // 1 +c.red = 9; +const bytes = Color.encode(c); // Uint8Array +``` + +There are no generated constructors, field getter methods, or field setter +methods. Encoding rejects missing fields and non-object values. + +### Union values + +v4 generated static constructors and instance accessors for union arms. v5 uses +plain tagged objects. + +**Before (v4):** + +```js +const ok = types.Result.ok(); +ok.switch(); // ResultType.ok() + +const err = types.Result.error(7); +err.switch(); // ResultType.error() +err.code(); // 7 +``` + +**After (v5):** + +```ts +const ok = { type: ResultType.ok }; + +const err = { type: ResultType.error, code: 7 }; +err.type; // 1 +err.code; // 7 +``` + +Union rules: +- A void arm is just the discriminator object: `{ type: ResultType.ok }`. +- A payload arm includes the discriminator plus the field name declared with + `field(payloadName, schema)`. +- The discriminator key defaults to `type`. +- Use `switchKey` to use a different discriminator property. + +```ts +const Custom = union('Custom', { + switchOn: ResultType, + switchKey: 'kind', + cases: [ + xdrCase('ok', ResultType.ok, xdrVoid()), + xdrCase('error', ResultType.error, field('code', int32())) + ] +}); + +Custom.encode({ kind: ResultType.error, code: 7 }); +``` + +Default arms still work: + +```ts +const Tagged = union('Tagged', { + switchOn: int32(), + cases: [xdrCase('known', 1, field('value', int32()))], + defaultArm: field('unknown', int32()) +}); + +Tagged.decode(bytes); // { type: 99, unknown: ... } for an unknown discriminator +``` + +### Optional values + +`option(child)` returns the child value or `null`. There is no wrapper object. + +```ts +const MaybeCode = option(int32()); +MaybeCode.encode(7); +MaybeCode.encode(null); +``` + +## Encoding, decoding, and validation + +| v4 | v5 | +| --- | --- | +| `T.toXDR(value)` / `value.toXDR()` | `T.encode(value)` -> `Uint8Array` | +| `T.fromXDR(input)` | `T.decode(bytes)` | +| `T.validateXDR(input)` | `T.validateXdr(bytes)` | +| `T.isValid(value)` | `T.validate(value)` | +| `T.toXDR(value, 'base64' \| 'hex')` | no `format` arg; convert at the boundary | + +```ts +// v4: const b64 = Result.toXDR(value, 'base64'); +const b64 = Buffer.from(Result.encode(value)).toString('base64'); + +// v4: const value = Result.fromXDR(b64, 'base64'); +const value = Result.decode(Buffer.from(b64, 'base64')); +``` + +`validateXdr(bytes)` checks whether encoded XDR bytes can be decoded by the +schema and fully consume the input. It accepts raw `Uint8Array` bytes only. If +you have hex or base64, convert first: + +```ts +const bytes = Buffer.from(b64, 'base64'); +if (Result.validateXdr(bytes)) { + const result = Result.decode(bytes); +} +``` + +`validate(value)` checks whether a JavaScript value can be encoded by the schema: + +```ts +Result.validate({ type: ResultType.error, code: 7 }); // true +Result.validate({ type: ResultType.error }); // false +``` + +The recursion-depth guard is now a decode option rather than a constructor +argument: + +```ts +Result.decode(bytes, { maxDepth: 100 }); +Result.validateXdr(bytes, { maxDepth: 100 }); +``` + +## Errors + +`XdrReaderError`, `XdrWriterError`, `XdrDefinitionError`, and +`XdrNotImplementedDefinitionError` are replaced by a single `XdrError`. + +```ts +import { XdrError } from '@stellar/js-xdr'; + +try { + Result.decode(bytes); +} catch (error) { + if (error instanceof XdrError) { + // Malformed XDR, trailing bytes, unknown enum value, invalid padding, + // invalid schema value, or schema definition problem. + } +} +``` + +If your old code distinguished reader, writer, and definition errors with +`instanceof`, replace that branching with message- or operation-level handling. + +## Low-level Reader / Writer + +Most consumers should use `schema.encode(value)` and `schema.decode(bytes)`. +If you used the raw streaming primitives, update the names and output method: + +| v4 | v5 | +| --- | --- | +| `XdrReader` | `Reader` | +| `XdrWriter` | `Writer` | +| `writer.finalize()` | `writer.toUint8Array()` | +| `writer.writeInt32BE(value)` | `writer.writeInt32(value)` | +| `writer.writeUInt32BE(value)` | `writer.writeUint32(value)` | +| `writer.writeBigInt64BE(value)` | `writer.writeBigInt64(value)` | +| `writer.writeBigUInt64BE(value)` | `writer.writeBigUint64(value)` | +| `writer.writeFloatBE(value)` | `writer.writeFloat32(value)` | +| `writer.writeDoubleBE(value)` | `writer.writeFloat64(value)` | + +Reader methods now take a `path` string used in diagnostics, for example +`reader.readInt32('Result.code')`. + +## TypeScript + +Schemas are fully typed. Derive the value type of any schema with `Infer`: + +```ts +import type { Infer } from '@stellar/js-xdr'; + +type Color = Infer; // { red: number; green: number; blue: number } +``` + +`struct`, `union`, `enumType`, `array`, and `option` preserve value types through +composition, so prefer deriving types from schemas instead of duplicating object +shapes by hand. + +For very large XDR definitions, or definitions with cyclic references, deriving +all value types through `Infer` can put significant pressure on the TypeScript +compiler and language server. In those cases, prefer explicit hand-written value +types at module boundaries and use `Infer` selectively for smaller local schemas. + +## Verifying your migration + +Use existing XDR fixtures to prove that the wire format is unchanged: + +```ts +const oldBytes = Buffer.from(oldBase64, 'base64'); +const value = Result.decode(oldBytes); +expect(Result.encode(value)).toEqual(Uint8Array.from(oldBytes)); +``` + +Recommended checks: +- Decode old fixture bytes with the new schema. +- Re-encode the decoded value and compare bytes exactly. +- Add tests for invalid enum values, invalid padding, and trailing bytes if your + code accepts untrusted XDR. +- Add tests for boundary conversions if your public API still accepts hex, + base64, or `Buffer`. +- For recursive schemas, add at least one `maxDepth` test. diff --git a/README.md b/README.md index 3e92b62..badaa7d 100644 --- a/README.md +++ b/README.md @@ -23,60 +23,43 @@ npm install --save @stellar/js-xdr ## Usage -You can find some [examples here](examples/). +> **Upgrading from v4?** The schema-definition API changed completely in v5. +> See the [migration guide](MIGRATION.md). -First, let's import the library: +Schemas are built by composing the exported builder functions. Each builder +returns a schema with `encode(value)` → `Uint8Array` and `decode(bytes)` → value: ```javascript -var xdr = require('@stellar/js-xdr'); -// or -import xdr from '@stellar/js-xdr'; -``` - -Now, let's look at how to decode some primitive types: +import { bool, int32, uint32, int64 } from '@stellar/js-xdr'; -```javascript // booleans -xdr.Bool.fromXDR([0, 0, 0, 0]); // returns false -xdr.Bool.fromXDR([0, 0, 0, 1]); // returns true - -// the inverse of `fromXDR` is `toXDR`, which returns a Buffer -xdr.Bool.toXDR(true); // returns Buffer.from([0,0,0,1]) - -// XDR ints and unsigned ints can be safely represented as -// a javascript number +bool().decode(Uint8Array.from([0, 0, 0, 0])); // returns false +bool().decode(Uint8Array.from([0, 0, 0, 1])); // returns true -xdr.Int.fromXDR([0xff, 0xff, 0xff, 0xff]); // returns -1 -xdr.UnsignedInt.fromXDR([0xff, 0xff, 0xff, 0xff]); // returns 4294967295 +// the inverse of `decode` is `encode`, which returns a Uint8Array +bool().encode(true); // returns Uint8Array.from([0, 0, 0, 1]) -// XDR Hypers, however, cannot be safely represented in the 53-bits -// of precision we get with a JavaScript `Number`, so we allow creation from big-endian arrays of numbers, strings, or bigints. -var result = xdr.Hyper.fromXDR([0, 0, 0, 0, 0, 0, 0, 0]); // returns an instance of xdr.Hyper -result = new xdr.Hyper(0); // equivalent +// XDR ints and unsigned ints are represented as a JavaScript number +int32().decode(Uint8Array.from([0xff, 0xff, 0xff, 0xff])); // returns -1 +uint32().decode(Uint8Array.from([0xff, 0xff, 0xff, 0xff])); // returns 4294967295 -// convert the hyper to a string -result.toString(); // return '0' - -// math! -var ten = result.toBigInt() + 10; -var minusone = result.toBigInt() - 1; - -// construct a number from a string -var big = xdr.Hyper.fromString('1099511627776'); - -// encode the hyper back into xdr -big.toXDR(); // +// XDR hypers cannot be safely represented in a JavaScript `Number`, so +// `int64`/`uint64` use native `bigint` values +int64().encode(1099511627776n); // Uint8Array(8) [0, 0, 1, 0, 0, 0, 0, 0] +int64().decode(Uint8Array.from([0, 0, 1, 0, 0, 0, 0, 0])); // returns 1099511627776n ``` +Compound types (`struct`, `union`, `enumType`, `array`, …) are composed the same +way — see the [migration guide](MIGRATION.md) and [examples](examples/) for the +full set of builders. + ## Caveats There are a couple of caveats to be aware of with this library: -1. We do not support quadruple precision floating point values. Attempting to - read or write these values will throw errors. +1. Quadruple precision floating point values are not supported. 2. NaN is not handled perfectly for floats and doubles. There are several forms - of NaN as defined by IEEE754 and the browser polyfill for node's Buffer - class seems to handle them poorly. + of NaN as defined by IEEE754, and they are not all round-tripped faithfully. ## Code generation From 4c20625d48c29f334554d44d2f2c53a0f79a22a2 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 16:05:41 -0700 Subject: [PATCH 10/22] remove xdrgen codegen files --- Gemfile | 8 -------- Gemfile.lock | 46 ---------------------------------------------- 2 files changed, 54 deletions(-) delete mode 100644 Gemfile delete mode 100644 Gemfile.lock diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 59037c7..0000000 --- a/Gemfile +++ /dev/null @@ -1,8 +0,0 @@ -source 'https://rubygems.org' - -group :development do - gem "xdrgen", git: "git@github.com:stellar/xdrgen.git" - # gem "xdrgen", path: "../xdrgen" - gem "pry" -end - diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 17f2848..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,46 +0,0 @@ -GIT - remote: git@github.com:stellar/xdrgen.git - revision: 80e38ef2a96489f6b501d4db3a350406e5aa3bab - specs: - xdrgen (0.1.1) - activesupport (~> 6) - memoist (~> 0.11.0) - slop (~> 3.4) - treetop (~> 1.5.3) - -GEM - remote: https://rubygems.org/ - specs: - activesupport (6.1.7.6) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - coderay (1.1.3) - concurrent-ruby (1.2.2) - i18n (1.14.1) - concurrent-ruby (~> 1.0) - memoist (0.11.0) - method_source (1.0.0) - minitest (5.19.0) - polyglot (0.3.5) - pry (0.14.2) - coderay (~> 1.1) - method_source (~> 1.0) - slop (3.6.0) - treetop (1.5.3) - polyglot (~> 0.3) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - zeitwerk (2.6.11) - -PLATFORMS - ruby - -DEPENDENCIES - pry - xdrgen! - -BUNDLED WITH - 2.4.6 From 6166c521f40a4ef77ba9c4204d6e80c25ae5dc26 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 16:08:04 -0700 Subject: [PATCH 11/22] remove legacy configs that are no longer used --- .travis.yml | 25 ------------------------- bower.json | 9 --------- 2 files changed, 34 deletions(-) delete mode 100644 .travis.yml delete mode 100644 bower.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 980df79..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: node_js -node_js: - - 10 - - 11 - - 12 -cache: - directories: - - node_modules -services: - - xvfb -script: yarn test -notifications: - slack: - secure: Bu3OZ0Cdy8eq0IMoLJmadDba8Yyb9ajobKocfp8V7/vfOjpIVXdFrGMqfckkZ22uiWxHCsYEX1ahQ77zTjbO3tNq1CTmSgEAWaqqMVz1iIVNhSoeHRfYDa9r1sKFpJv1KEz+j/8i2phcR5MDE6cGK+byJmjfjcnkP1XoNiupuck= -before_deploy: - - yarn build -deploy: - provider: npm - email: npm@stellar.org - api_key: $NPM_TOKEN - skip_cleanup: true - on: - tags: true - repo: stellar/js-xdr - branch: master diff --git a/bower.json b/bower.json deleted file mode 100644 index 774c412..0000000 --- a/bower.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "js-xdr", - "version": "0.0.1", - "private": false, - "main": "dist/xdr.js", - "dependencies": {}, - "devDependencies": {}, - "ignore": [] -} \ No newline at end of file From 309c5ac5f60bbb356abc3b7e8705c2b24388d55f Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Wed, 27 May 2026 16:31:24 -0700 Subject: [PATCH 12/22] update husky to v9 --- .husky/pre-commit | 3 --- package.json | 4 ++-- pnpm-lock.yaml | 12 ++++++------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index a5a29d9..cb2c84d 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - pnpm lint-staged diff --git a/package.json b/package.json index be0c596..72ce81b 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "typecheck": "tsc --noEmit", "test-generate": "bundle exec xdrgen -o generated -n test -l javascript examples/test.x", "fmt": "prettier --write '**/*.{js,ts,json}'", - "prepare": "pnpm build", + "prepare": "husky", "clean": "rm -rf dist" }, "repository": { @@ -63,7 +63,7 @@ "esbuild": "^0.27.1", "eslint": "^9.39.4", "eslint-config-prettier": "^9.1.2", - "husky": "^8.0.3", + "husky": "^9.1.7", "lint-staged": "13.2.2", "prettier": "^2.8.7", "rollup": "^4.53.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45fee2f..1d2300b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,8 +24,8 @@ importers: specifier: ^9.1.2 version: 9.1.2(eslint@9.39.4) husky: - specifier: ^8.0.3 - version: 8.0.3 + specifier: ^9.1.7 + version: 9.1.7 lint-staged: specifier: 13.2.2 version: 13.2.2 @@ -982,9 +982,9 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} hasBin: true ignore@5.3.2: @@ -2354,7 +2354,7 @@ snapshots: human-signals@5.0.0: {} - husky@8.0.3: {} + husky@9.1.7: {} ignore@5.3.2: {} From 070a969e2e7efe31031cf3f3d1d401baf8cf375c Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Thu, 28 May 2026 08:21:36 -0700 Subject: [PATCH 13/22] expose nameByValue on EnumSchema --- src/types/enum.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/types/enum.ts b/src/types/enum.ts index fd16ffd..b8b7bfc 100644 --- a/src/types/enum.ts +++ b/src/types/enum.ts @@ -6,11 +6,17 @@ import { BaseType, type XdrType } from '../core/xdr-type.js'; export type EnumMember> = Values[keyof Values]; +export type EnumName> = Extract< + keyof Values, + string +>; + export type EnumSchema< Name extends string, Values extends Record > = XdrType> & { readonly name: Name; + readonly nameByValue: ReadonlyMap>; } & Values; const RESERVED_ENUM_MEMBER_NAMES = new Set([ @@ -20,7 +26,8 @@ const RESERVED_ENUM_MEMBER_NAMES = new Set([ 'decode', 'validate', '_read', - '_write' + '_write', + 'nameByValue' ]); /** @@ -35,18 +42,18 @@ export class EnumType> extends BaseType< readonly kind = 'enum'; // Maps wire value → declared member name. Public so the generic toJson // walker can render numeric enums as their string names. - readonly nameByValue: ReadonlyMap; + readonly nameByValue: ReadonlyMap>; readonly #valuesSet = new Set(); constructor(name: string, values: Values) { super(name); - const nameByValue = new Map(); + const nameByValue = new Map>(); for (const [memberName, memberValue] of Object.entries(values)) { if (this.#valuesSet.has(memberValue)) { throw new XdrError(`${name}: duplicate enum value ${memberValue}`); } this.#valuesSet.add(memberValue); - nameByValue.set(memberValue, memberName); + nameByValue.set(memberValue, memberName as EnumName); } this.nameByValue = nameByValue; } From fa8e38de6f4d9f949345db7d4e3a4e2d496d2772 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Thu, 28 May 2026 08:22:14 -0700 Subject: [PATCH 14/22] convert examples to typescript --- examples/{enum.mjs => enum.ts} | 2 +- examples/{linked_list.mjs => linked_list.ts} | 8 ++++++-- examples/{struct.mjs => struct.ts} | 2 +- examples/{typedef.mjs => typedef.ts} | 0 examples/{union.mjs => union.ts} | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) rename examples/{enum.mjs => enum.ts} (93%) rename examples/{linked_list.mjs => linked_list.ts} (55%) rename examples/{struct.mjs => struct.ts} (88%) rename examples/{typedef.mjs => typedef.ts} (100%) rename examples/{union.mjs => union.ts} (89%) diff --git a/examples/enum.mjs b/examples/enum.ts similarity index 93% rename from examples/enum.mjs rename to examples/enum.ts index d00bd65..3c5b5ec 100644 --- a/examples/enum.mjs +++ b/examples/enum.ts @@ -1,4 +1,4 @@ -import { enumType } from '../dist/js-xdr.mjs'; +import { enumType } from '../src/index.js'; const Color = enumType('Color', { red: 0, diff --git a/examples/linked_list.mjs b/examples/linked_list.ts similarity index 55% rename from examples/linked_list.mjs rename to examples/linked_list.ts index 2da35b2..e3fb7ee 100644 --- a/examples/linked_list.mjs +++ b/examples/linked_list.ts @@ -1,6 +1,10 @@ -import { int32, lazy, option, struct } from '../dist/js-xdr.mjs'; +import { int32, lazy, option, struct, XdrType } from '../src/index.js'; -const IntList = struct('IntList', { +type IntListWire = { + value: number; + rest: IntListWire | null; +}; +const IntList: XdrType = struct('IntList', { value: int32(), rest: option(lazy(() => IntList)) }); diff --git a/examples/struct.mjs b/examples/struct.ts similarity index 88% rename from examples/struct.mjs rename to examples/struct.ts index a13acc7..027acd8 100644 --- a/examples/struct.mjs +++ b/examples/struct.ts @@ -1,4 +1,4 @@ -import { opaque, struct, uint32, varOpaque } from '../dist/js-xdr.mjs'; +import { opaque, struct, uint32, varOpaque } from '../src/index.js'; const Signature = struct('Signature', { publicKey: opaque(32), diff --git a/examples/typedef.mjs b/examples/typedef.ts similarity index 100% rename from examples/typedef.mjs rename to examples/typedef.ts diff --git a/examples/union.mjs b/examples/union.ts similarity index 89% rename from examples/union.mjs rename to examples/union.ts index 6e9a7c9..a05e115 100644 --- a/examples/union.mjs +++ b/examples/union.ts @@ -6,7 +6,7 @@ import { string, union, void as xdrVoid -} from '../dist/js-xdr.mjs'; +} from '../src/index.js'; const ResultType = enumType('ResultType', { ok: 0, @@ -32,6 +32,7 @@ const errorBytes = Result.encode(errorResult); const parsedError = Result.decode(errorBytes); console.log(parsedError); +// @ts-expect-error TypeScript doesn't know about the discriminated union here, so `message` is still a `Uint8Array`. console.log(new TextDecoder().decode(parsedError.message)); const okResult = { type: ResultType.ok }; From 138961d2ef4a07d341d4731aeda85b2386f2efcd Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Thu, 28 May 2026 08:26:23 -0700 Subject: [PATCH 15/22] bump node version to 22 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 72ce81b..b67782f 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "4.0.0", "description": "Read/write XDR encoded data structures (RFC 4506)", "engines": { - "node": ">=20.0.0", + "node": ">=22.0.0", "pnpm": ">=9.0.0" }, "main": "./dist/js-xdr.cjs", @@ -59,7 +59,7 @@ }, "devDependencies": { "@eslint/js": "^9.39.4", - "@types/node": "^20.12.0", + "@types/node": "^22.0.0", "esbuild": "^0.27.1", "eslint": "^9.39.4", "eslint-config-prettier": "^9.1.2", From cf85afff5b071ca0dc65120e9a35ed6dbe39b927 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Thu, 28 May 2026 09:12:08 -0700 Subject: [PATCH 16/22] add tests to validate new wire encode/decodes the same --- package.json | 2 + pnpm-lock.yaml | 37 ++++--- test/fixtures/generate-v4-compat.cjs | 137 +++++++++++++++++++++++ test/fixtures/v4-compat.json | 56 ++++++++++ test/unit/v4-compat.test.ts | 156 +++++++++++++++++++++++++++ 5 files changed, 374 insertions(+), 14 deletions(-) create mode 100644 test/fixtures/generate-v4-compat.cjs create mode 100644 test/fixtures/v4-compat.json create mode 100644 test/unit/v4-compat.test.ts diff --git a/package.json b/package.json index b67782f..f4ad855 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "lint": "eslint .", "typecheck": "tsc --noEmit", "test-generate": "bundle exec xdrgen -o generated -n test -l javascript examples/test.x", + "fixtures:generate-v4": "node test/fixtures/generate-v4-compat.cjs", "fmt": "prettier --write '**/*.{js,ts,json}'", "prepare": "husky", "clean": "rm -rf dist" @@ -64,6 +65,7 @@ "eslint": "^9.39.4", "eslint-config-prettier": "^9.1.2", "husky": "^9.1.7", + "js-xdr-v4": "npm:@stellar/js-xdr@4.0.0", "lint-staged": "13.2.2", "prettier": "^2.8.7", "rollup": "^4.53.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d2300b..7e25d39 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^9.39.4 version: 9.39.4 '@types/node': - specifier: ^20.12.0 - version: 20.19.41 + specifier: ^22.0.0 + version: 22.19.19 esbuild: specifier: ^0.27.1 version: 0.27.7 @@ -26,6 +26,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + js-xdr-v4: + specifier: npm:@stellar/js-xdr@4.0.0 + version: '@stellar/js-xdr@4.0.0' lint-staged: specifier: 13.2.2 version: 13.2.2 @@ -49,7 +52,7 @@ importers: version: 8.60.0(eslint@9.39.4)(typescript@5.9.3) vitest: specifier: ^1.6.0 - version: 1.6.1(@types/node@20.19.41)(terser@5.46.0) + version: 1.6.1(@types/node@22.19.19)(terser@5.46.0) packages: @@ -564,14 +567,18 @@ packages: '@sinclair/typebox@0.27.10': resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + '@stellar/js-xdr@4.0.0': + resolution: {integrity: sha512-+NmNa7Tk5BI5XFdy/6xGTqAN4J9a9KgCrCGhj2uEUTCBhLkch0M+QbKzNH8zEnejWe0p8w+0q5hUVX6L3OzoVA==} + engines: {node: '>=20.0.0', pnpm: '>=9.0.0'} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@20.19.41': - resolution: {integrity: sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ==} + '@types/node@22.19.19': + resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} '@typescript-eslint/eslint-plugin@8.60.0': resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==} @@ -1862,11 +1869,13 @@ snapshots: '@sinclair/typebox@0.27.10': {} + '@stellar/js-xdr@4.0.0': {} + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} - '@types/node@20.19.41': + '@types/node@22.19.19': dependencies: undici-types: 6.21.0 @@ -2803,13 +2812,13 @@ snapshots: dependencies: punycode: 2.3.1 - vite-node@1.6.1(@types/node@20.19.41)(terser@5.46.0): + vite-node@1.6.1(@types/node@22.19.19)(terser@5.46.0): dependencies: cac: 6.7.14 debug: 4.4.3 pathe: 1.1.2 picocolors: 1.1.1 - vite: 5.4.21(@types/node@20.19.41)(terser@5.46.0) + vite: 5.4.21(@types/node@22.19.19)(terser@5.46.0) transitivePeerDependencies: - '@types/node' - less @@ -2821,17 +2830,17 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@20.19.41)(terser@5.46.0): + vite@5.4.21(@types/node@22.19.19)(terser@5.46.0): dependencies: esbuild: 0.21.5 postcss: 8.5.15 rollup: 4.60.4 optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 22.19.19 fsevents: 2.3.3 terser: 5.46.0 - vitest@1.6.1(@types/node@20.19.41)(terser@5.46.0): + vitest@1.6.1(@types/node@22.19.19)(terser@5.46.0): dependencies: '@vitest/expect': 1.6.1 '@vitest/runner': 1.6.1 @@ -2850,11 +2859,11 @@ snapshots: strip-literal: 2.1.1 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 5.4.21(@types/node@20.19.41)(terser@5.46.0) - vite-node: 1.6.1(@types/node@20.19.41)(terser@5.46.0) + vite: 5.4.21(@types/node@22.19.19)(terser@5.46.0) + vite-node: 1.6.1(@types/node@22.19.19)(terser@5.46.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 20.19.41 + '@types/node': 22.19.19 transitivePeerDependencies: - less - lightningcss diff --git a/test/fixtures/generate-v4-compat.cjs b/test/fixtures/generate-v4-compat.cjs new file mode 100644 index 0000000..df18886 --- /dev/null +++ b/test/fixtures/generate-v4-compat.cjs @@ -0,0 +1,137 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +const fs = require('node:fs'); +const path = require('node:path'); +const XDR = require('js-xdr-v4'); +const { version } = require('js-xdr-v4/package.json'); + +const outputPath = path.join(__dirname, 'v4-compat.json'); + +const types = XDR.config((xdr) => { + xdr.enum('Color', { + red: 0, + green: 1, + blue: 2 + }); + + xdr.struct('CompatRecord', [ + ['i', xdr.int()], + ['u', xdr.uint()], + ['h', xdr.hyper()], + ['uh', xdr.uhyper()], + ['ok', xdr.bool()], + ['f', xdr.float()], + ['d', xdr.double()], + ['name', xdr.string(16)], + ['fixed', xdr.opaque(3)], + ['varBytes', xdr.varOpaque(8)], + ['fixedInts', xdr.array(xdr.int(), 3)], + ['varInts', xdr.varArray(xdr.int(), 4)], + ['maybe', xdr.option(xdr.int())], + ['color', xdr.lookup('Color')] + ]); + + xdr.enum('ResultType', { + ok: 0, + error: 1 + }); + + xdr.union('Result', { + switchOn: xdr.lookup('ResultType'), + switches: [ + ['ok', xdr.void()], + ['error', 'message'] + ], + arms: { + message: xdr.string(100) + } + }); + + xdr.struct('IntList', [ + ['value', xdr.int()], + ['rest', xdr.option(xdr.lookup('IntList'))] + ]); +}); + +function toHex(value) { + return Buffer.from(value).toString('hex'); +} + +const compatRecord = new types.CompatRecord({ + i: -1, + u: 4294967295, + h: new XDR.Hyper(-1234567890123n), + uh: new XDR.UnsignedHyper(1234567890123n), + ok: true, + f: 1.5, + d: -2.25, + name: 'hi', + fixed: Buffer.from([1, 2, 3]), + varBytes: Buffer.from([4, 5, 6, 7]), + fixedInts: [1, 2, 3], + varInts: [4, 5], + maybe: 9, + color: types.Color.blue() +}); + +const resultOk = types.Result.ok(); +const resultError = types.Result.error('this is an error'); + +const listTail = new types.IntList({ value: 1, rest: null }); +const linkedList = new types.IntList({ value: 3, rest: listTail }); + +const fixture = { + generatedBy: { + package: '@stellar/js-xdr', + alias: 'js-xdr-v4', + version, + script: 'test/fixtures/generate-v4-compat.cjs' + }, + cases: { + compatRecord: { + schema: 'CompatRecord', + hex: toHex(compatRecord.toXDR()), + value: { + i: -1, + u: 4294967295, + h: '-1234567890123', + uh: '1234567890123', + ok: true, + f: 1.5, + d: -2.25, + name: toHex(Buffer.from('hi')), + fixed: '010203', + varBytes: '04050607', + fixedInts: [1, 2, 3], + varInts: [4, 5], + maybe: 9, + color: 2 + } + }, + resultOk: { + schema: 'Result', + hex: toHex(resultOk.toXDR()), + value: { type: 0 } + }, + resultError: { + schema: 'Result', + hex: toHex(resultError.toXDR()), + value: { + type: 1, + message: toHex(Buffer.from('this is an error')) + } + }, + linkedList: { + schema: 'IntList', + hex: toHex(linkedList.toXDR()), + value: { + value: 3, + rest: { + value: 1, + rest: null + } + } + } + } +}; + +fs.writeFileSync(outputPath, `${JSON.stringify(fixture, null, 2)}\n`); diff --git a/test/fixtures/v4-compat.json b/test/fixtures/v4-compat.json new file mode 100644 index 0000000..a004549 --- /dev/null +++ b/test/fixtures/v4-compat.json @@ -0,0 +1,56 @@ +{ + "generatedBy": { + "package": "@stellar/js-xdr", + "alias": "js-xdr-v4", + "version": "4.0.0", + "script": "test/fixtures/generate-v4-compat.cjs" + }, + "cases": { + "compatRecord": { + "schema": "CompatRecord", + "hex": "fffffffffffffffffffffee08e04fb350000011f71fb04cb000000013fc00000c0020000000000000000000268690000010203000000000404050607000000010000000200000003000000020000000400000005000000010000000900000002", + "value": { + "i": -1, + "u": 4294967295, + "h": "-1234567890123", + "uh": "1234567890123", + "ok": true, + "f": 1.5, + "d": -2.25, + "name": "6869", + "fixed": "010203", + "varBytes": "04050607", + "fixedInts": [1, 2, 3], + "varInts": [4, 5], + "maybe": 9, + "color": 2 + } + }, + "resultOk": { + "schema": "Result", + "hex": "00000000", + "value": { + "type": 0 + } + }, + "resultError": { + "schema": "Result", + "hex": "00000001000000107468697320697320616e206572726f72", + "value": { + "type": 1, + "message": "7468697320697320616e206572726f72" + } + }, + "linkedList": { + "schema": "IntList", + "hex": "00000003000000010000000100000000", + "value": { + "value": 3, + "rest": { + "value": 1, + "rest": null + } + } + } + } +} diff --git a/test/unit/v4-compat.test.ts b/test/unit/v4-compat.test.ts new file mode 100644 index 0000000..fccff09 --- /dev/null +++ b/test/unit/v4-compat.test.ts @@ -0,0 +1,156 @@ +import { describe, expect, it } from 'vitest'; +import { + array, + bool, + case as xdrCase, + double, + enumType, + field, + fixedArray, + float, + int32, + int64, + lazy, + opaque, + option, + string, + struct, + uint32, + uint64, + union, + varOpaque, + void as xdrVoid, + type XdrType +} from '../../src/index.js'; +import fixture from '../fixtures/v4-compat.json'; + +type IntListValue = { + readonly value: number; + readonly rest: IntListValue | null; +}; + +const Color = enumType('Color', { + red: 0, + green: 1, + blue: 2 +}); + +const CompatRecord = struct('CompatRecord', { + i: int32(), + u: uint32(), + h: int64(), + uh: uint64(), + ok: bool(), + f: float(), + d: double(), + name: string(16), + fixed: opaque(3), + varBytes: varOpaque(8), + fixedInts: fixedArray(int32(), 3), + varInts: array(int32(), 4), + maybe: option(int32()), + color: Color +}); + +const ResultType = enumType('ResultType', { + ok: 0, + error: 1 +}); + +const Result = union('Result', { + switchOn: ResultType, + cases: [ + xdrCase('ok', ResultType.ok, xdrVoid()), + xdrCase('error', ResultType.error, field('message', string(100))) + ] +}); + +const IntList: XdrType = struct('IntList', { + value: int32(), + rest: option(lazy(() => IntList)) +}) as XdrType; + +function fromHex(hex: string): Uint8Array { + return Uint8Array.from(Buffer.from(hex, 'hex')); +} + +function toHex(bytes: Uint8Array): string { + return Buffer.from(bytes).toString('hex'); +} + +function normalizeCompatRecord(value: ReturnType) { + return { + i: value.i, + u: value.u, + h: value.h.toString(), + uh: value.uh.toString(), + ok: value.ok, + f: value.f, + d: value.d, + name: toHex(value.name), + fixed: toHex(value.fixed), + varBytes: toHex(value.varBytes), + fixedInts: value.fixedInts, + varInts: value.varInts, + maybe: value.maybe, + color: value.color + }; +} + +describe('v4 wire compatibility fixtures', () => { + it('records how the fixture bytes were generated', () => { + expect(fixture.generatedBy).toEqual({ + package: '@stellar/js-xdr', + alias: 'js-xdr-v4', + version: '4.0.0', + script: 'test/fixtures/generate-v4-compat.cjs' + }); + }); + + it('decodes and re-encodes a v4 struct covering primitive and container types', () => { + const testCase = fixture.cases.compatRecord; + const bytes = fromHex(testCase.hex); + + const decoded = CompatRecord.decode(bytes); + + expect(normalizeCompatRecord(decoded)).toEqual(testCase.value); + expect(toHex(CompatRecord.encode(decoded))).toBe(testCase.hex); + }); + + it('decodes and re-encodes a v4 union void arm', () => { + const testCase = fixture.cases.resultOk; + const bytes = fromHex(testCase.hex); + + const decoded = Result.decode(bytes); + + expect(decoded).toEqual(testCase.value); + expect(toHex(Result.encode(decoded))).toBe(testCase.hex); + }); + + it('decodes and re-encodes a v4 union payload arm', () => { + const testCase = fixture.cases.resultError; + const bytes = fromHex(testCase.hex); + + const decoded = Result.decode(bytes); + const errorResult = decoded as { + readonly type: number; + message: Uint8Array; + }; + + expect({ + type: errorResult.type, + message: toHex(errorResult.message) + }).toEqual(testCase.value); + expect(toHex(Result.encode(decoded))).toBe(testCase.hex); + }); + + it('decodes and re-encodes a v4 recursive structure', () => { + const testCase = fixture.cases.linkedList; + const bytes = fromHex(testCase.hex); + + const decoded = IntList.decode(bytes); + + expect(decoded).toEqual(testCase.value); + expect(toHex(IntList.encode(decoded))).toBe(testCase.hex); + }); +}); From af7335f2f31ca6bc7291146f048168c2cf3f2d98 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Fri, 29 May 2026 14:38:25 -0700 Subject: [PATCH 17/22] address copilot feedback -tighten isPlainObject to reject class instances -validate enum member values are valid int32 integers --- examples/typedef.ts | 2 +- src/core/helpers.ts | 6 +++++- src/types/enum.ts | 7 +++++++ test/unit/enum.test.ts | 16 ++++++++++++++++ test/unit/struct.test.ts | 23 +++++++++++++++++++++++ test/unit/union.test.ts | 11 +++++++++++ 6 files changed, 63 insertions(+), 2 deletions(-) diff --git a/examples/typedef.ts b/examples/typedef.ts index d46eb0a..8bcfe96 100644 --- a/examples/typedef.ts +++ b/examples/typedef.ts @@ -1,4 +1,4 @@ -import { int32, opaque, struct } from '../dist/js-xdr.mjs'; +import { int32, opaque, struct } from '../src/index.js'; const Signature = struct('Signature', { publicKey: opaque(32), diff --git a/src/core/helpers.ts b/src/core/helpers.ts index 63e4d10..2511868 100644 --- a/src/core/helpers.ts +++ b/src/core/helpers.ts @@ -11,7 +11,11 @@ export function paddingLength(length: number): number { export function isPlainObject( value: unknown ): value is Record { - return typeof value === 'object' && value !== null && !Array.isArray(value); + if (typeof value !== 'object' || value === null) { + return false; + } + const proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null; } export function assertLength(value: number, name: string): void { diff --git a/src/types/enum.ts b/src/types/enum.ts index b8b7bfc..0c121b7 100644 --- a/src/types/enum.ts +++ b/src/types/enum.ts @@ -1,4 +1,5 @@ import { XdrError } from '../core/error.js'; +import { assertIntRange } from '../core/helpers.js'; import type { Reader } from '../core/reader.js'; import type { Writer } from '../core/writer.js'; import { BaseType, type XdrType } from '../core/xdr-type.js'; @@ -49,6 +50,12 @@ export class EnumType> extends BaseType< super(name); const nameByValue = new Map>(); for (const [memberName, memberValue] of Object.entries(values)) { + assertIntRange( + memberValue, + -2147483648, + 2147483647, + `${name}.${memberName}` + ); if (this.#valuesSet.has(memberValue)) { throw new XdrError(`${name}: duplicate enum value ${memberValue}`); } diff --git a/test/unit/enum.test.ts b/test/unit/enum.test.ts index 3981ba7..a5f2698 100644 --- a/test/unit/enum.test.ts +++ b/test/unit/enum.test.ts @@ -54,5 +54,21 @@ describe('enum', () => { expect(() => enumType('Bad', { name: 0 })).toThrow(/reserved/i); expect(() => enumType('Bad', { decode: 1 })).toThrow(/reserved/i); }); + + it('rejects member values outside the int32 range', () => { + // 4294967295 would silently encode as -1 via DataView.setInt32. + expect(() => enumType('TooBig', { a: 4294967295 })).toThrow(/range/i); + expect(() => enumType('TooSmall', { a: -2147483649 })).toThrow(/range/i); + }); + + it('rejects non-integer member values', () => { + expect(() => enumType('Frac', { a: 1.5 })).toThrow(/integer/i); + }); + + it('accepts the int32 boundary values', () => { + expect(() => + enumType('Bounds', { lo: -2147483648, hi: 2147483647 }) + ).not.toThrow(); + }); }); }); diff --git a/test/unit/struct.test.ts b/test/unit/struct.test.ts index 7f5c922..1bbcb9c 100644 --- a/test/unit/struct.test.ts +++ b/test/unit/struct.test.ts @@ -33,6 +33,29 @@ describe('struct', () => { expect(() => encodeInvalid(Range, [])).toThrow(/expected plain object/i); }); + it('rejects class instances rather than treating them as plain objects', () => { + expect(() => encodeInvalid(Range, new Date())).toThrow( + /expected plain object/i + ); + expect(() => encodeInvalid(Range, new Map())).toThrow( + /expected plain object/i + ); + expect(() => encodeInvalid(Range, new Uint8Array(4))).toThrow( + /expected plain object/i + ); + }); + + it('accepts objects with a null prototype', () => { + const value = Object.assign(Object.create(null), { + begin: 1, + end: 2, + inclusive: true + }); + expect(toArray(Range.encode(value))).toEqual([ + 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 + ]); + }); + it('propagates field validation errors', () => { expect(() => Range.encode({ begin: 2147483648, end: 0, inclusive: false }) diff --git a/test/unit/union.test.ts b/test/unit/union.test.ts index 082e8d4..d489efa 100644 --- a/test/unit/union.test.ts +++ b/test/unit/union.test.ts @@ -37,6 +37,17 @@ describe('union', () => { it('throws when the value has no discriminator key', () => { expect(() => encodeInvalid(Asset, {})).toThrow(/expected union object/i); }); + + it('rejects class instances rather than treating them as plain objects', () => { + // Carries the discriminator key, so it is only rejected by the + // plain-object check itself (not the missing-key fallback). + class FakeAsset { + type = 0; + } + expect(() => encodeInvalid(Asset, new FakeAsset())).toThrow( + /expected union object/i + ); + }); }); describe('decode', () => { From 9b7352c3879e6451cfd12a0bacfc3b870395a254 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Fri, 29 May 2026 14:52:07 -0700 Subject: [PATCH 18/22] prep for rc.1 --- .github/workflows/npm-publish.yml | 4 ++-- .github/workflows/tests.yml | 2 +- CHANGELOG.md | 4 ++-- package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index a29f523..93ea209 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -16,7 +16,7 @@ jobs: - name: Install Node uses: actions/setup-node@v3 with: - node-version: '20.x' + node-version: '22.x' registry-url: 'https://registry.npmjs.org' always-auth: true @@ -35,6 +35,6 @@ jobs: run: pnpm build && pnpm test - name: Publish to npm - run: pnpm publish --access public --provenance --no-git-checks + run: pnpm publish --access public --provenance --no-git-checks --tag ${{ github.event.release.prerelease && 'rc' || 'latest' }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e427242..b21e7e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: - name: Use Node.js 20 uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 - name: Install pnpm uses: pnpm/action-setup@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index acee41c..27fb44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## Unreleased +## [v5.0.0-rc.1](https://github.com/stellar/js-xdr/compare/v4.0.0...v5.0.0) A complete rewrite of the library. The runtime `xdr.config(...)` schema-definition DSL has been replaced with a set of statically-typed, explicitly-declared schema builders, and the entire source has been migrated from JavaScript to TypeScript. See [MIGRATION.md](./MIGRATION.md) for a step-by-step upgrade guide. @@ -15,7 +15,7 @@ A complete rewrite of the library. The runtime `xdr.config(...)` schema-definiti * **Renamed the low-level streaming types.** `XdrReader` → `Reader` and `XdrWriter` → `Writer`. * **Consolidated the error types.** `XdrReaderError`, `XdrWriterError`, `XdrDefinitionError`, and `XdrNotImplementedDefinitionError` are replaced by a single `XdrError`. * **Renamed/reshaped the numeric types.** `Int`/`UnsignedInt` → `int32`/`uint32` (return JS `number`); `Hyper`/`UnsignedHyper`/`LargeInt` → `int64`/`uint64` (return `bigint`, with range-checked encoding). The `Quadruple` type has been removed (it was already unsupported and threw on use). -* **New package layout.** `main`/`module`/`browser` fields are replaced by an `exports` map exposing dual ESM (`dist/js-xdr.mjs`) and CommonJS (`dist/js-xdr.cjs`) builds plus generated type declarations (`dist/js-xdr.d.ts`). Output is now `dist/` only (the `lib/` build is gone), the package is marked `sideEffects: false`, and Node `>=20` is required. +* **New package layout.** `main`/`module`/`browser` fields are replaced by an `exports` map exposing dual ESM (`dist/js-xdr.mjs`) and CommonJS (`dist/js-xdr.cjs`) builds plus generated type declarations (`dist/js-xdr.d.ts`). Output is now `dist/` only (the `lib/` build is gone), the package is marked `sideEffects: false`, and Node `>=22` is required. ### Added * **First-class TypeScript types.** Schemas carry full type information; `Infer` yields the encoded/decoded value type, and `struct`/`union`/`enumType` produce strongly-typed object, tagged-union, and named-member types. diff --git a/package.json b/package.json index f4ad855..1a5125a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@stellar/js-xdr", - "version": "4.0.0", + "version": "5.0.0-rc.1", "description": "Read/write XDR encoded data structures (RFC 4506)", "engines": { "node": ">=22.0.0", From e1db4dba6a477f2625dd354d1d6ec857ff7d1c40 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Mon, 1 Jun 2026 09:38:19 -0700 Subject: [PATCH 19/22] add xdr test object with multi nested structure for compat testing --- test/fixtures/generate-v4-compat.cjs | 85 ++++++++++++++++++++++++++++ test/fixtures/v4-compat.json | 42 ++++++++++++++ test/unit/v4-compat.test.ts | 60 ++++++++++++++++++++ 3 files changed, 187 insertions(+) diff --git a/test/fixtures/generate-v4-compat.cjs b/test/fixtures/generate-v4-compat.cjs index df18886..d697ce8 100644 --- a/test/fixtures/generate-v4-compat.cjs +++ b/test/fixtures/generate-v4-compat.cjs @@ -50,6 +50,47 @@ const types = XDR.config((xdr) => { ['value', xdr.int()], ['rest', xdr.option(xdr.lookup('IntList'))] ]); + + // A deeply nested composite: Scene -> Layer -> [Shape (union)] -> Polygon + // -> [Point]. Exercises wire compatibility for several layers of nested + // structs, unions, arrays, and options. + xdr.struct('Point', [ + ['x', xdr.int()], + ['y', xdr.int()] + ]); + + xdr.struct('Polygon', [ + ['vertices', xdr.varArray(xdr.lookup('Point'), 8)], + ['closed', xdr.bool()] + ]); + + xdr.enum('ShapeKind', { + dot: 0, + poly: 1 + }); + + xdr.union('Shape', { + switchOn: xdr.lookup('ShapeKind'), + switches: [ + ['dot', 'center'], + ['poly', 'polygon'] + ], + arms: { + center: xdr.lookup('Point'), + polygon: xdr.lookup('Polygon') + } + }); + + xdr.struct('Layer', [ + ['label', xdr.string(8)], + ['shapes', xdr.varArray(xdr.lookup('Shape'), 4)] + ]); + + xdr.struct('Scene', [ + ['name', xdr.string(16)], + ['root', xdr.lookup('Layer')], + ['fallback', xdr.option(xdr.lookup('Shape'))] + ]); }); function toHex(value) { @@ -79,6 +120,26 @@ const resultError = types.Result.error('this is an error'); const listTail = new types.IntList({ value: 1, rest: null }); const linkedList = new types.IntList({ value: 3, rest: listTail }); +const scene = new types.Scene({ + name: 'demo', + root: new types.Layer({ + label: 'base', + shapes: [ + types.Shape.dot(new types.Point({ x: 1, y: 2 })), + types.Shape.poly( + new types.Polygon({ + vertices: [ + new types.Point({ x: 3, y: 4 }), + new types.Point({ x: 5, y: 6 }) + ], + closed: true + }) + ) + ] + }), + fallback: types.Shape.dot(new types.Point({ x: 7, y: 8 })) +}); + const fixture = { generatedBy: { package: '@stellar/js-xdr', @@ -130,6 +191,30 @@ const fixture = { rest: null } } + }, + scene: { + schema: 'Scene', + hex: toHex(scene.toXDR()), + value: { + name: toHex(Buffer.from('demo')), + root: { + label: toHex(Buffer.from('base')), + shapes: [ + { type: 0, center: { x: 1, y: 2 } }, + { + type: 1, + polygon: { + vertices: [ + { x: 3, y: 4 }, + { x: 5, y: 6 } + ], + closed: true + } + } + ] + }, + fallback: { type: 0, center: { x: 7, y: 8 } } + } } } }; diff --git a/test/fixtures/v4-compat.json b/test/fixtures/v4-compat.json index a004549..4be7ec2 100644 --- a/test/fixtures/v4-compat.json +++ b/test/fixtures/v4-compat.json @@ -51,6 +51,48 @@ "rest": null } } + }, + "scene": { + "schema": "Scene", + "hex": "0000000464656d6f0000000462617365000000020000000000000001000000020000000100000002000000030000000400000005000000060000000100000001000000000000000700000008", + "value": { + "name": "64656d6f", + "root": { + "label": "62617365", + "shapes": [ + { + "type": 0, + "center": { + "x": 1, + "y": 2 + } + }, + { + "type": 1, + "polygon": { + "vertices": [ + { + "x": 3, + "y": 4 + }, + { + "x": 5, + "y": 6 + } + ], + "closed": true + } + } + ] + }, + "fallback": { + "type": 0, + "center": { + "x": 7, + "y": 8 + } + } + } } } } diff --git a/test/unit/v4-compat.test.ts b/test/unit/v4-compat.test.ts index fccff09..2317b5b 100644 --- a/test/unit/v4-compat.test.ts +++ b/test/unit/v4-compat.test.ts @@ -70,6 +70,42 @@ const IntList: XdrType = struct('IntList', { rest: option(lazy(() => IntList)) }) as XdrType; +// A deeply nested composite: Scene -> Layer -> [Shape (union)] -> Polygon -> +// [Point]. Several layers of nested structs, unions, arrays, and options. +const Point = struct('Point', { + x: int32(), + y: int32() +}); + +const Polygon = struct('Polygon', { + vertices: array(Point, 8), + closed: bool() +}); + +const ShapeKind = enumType('ShapeKind', { + dot: 0, + poly: 1 +}); + +const Shape = union('Shape', { + switchOn: ShapeKind, + cases: [ + xdrCase('dot', ShapeKind.dot, field('center', Point)), + xdrCase('poly', ShapeKind.poly, field('polygon', Polygon)) + ] +}); + +const Layer = struct('Layer', { + label: string(8), + shapes: array(Shape, 4) +}); + +const Scene = struct('Scene', { + name: string(16), + root: Layer, + fallback: option(Shape) +}); + function fromHex(hex: string): Uint8Array { return Uint8Array.from(Buffer.from(hex, 'hex')); } @@ -97,6 +133,20 @@ function normalizeCompatRecord(value: ReturnType) { }; } +// Renders the byte-valued (string) fields nested in a decoded Scene as hex so +// it can be compared against the JSON fixture; numeric/struct/union fields pass +// through unchanged. +function normalizeScene(value: ReturnType) { + return { + name: toHex(value.name), + root: { + label: toHex(value.root.label), + shapes: value.root.shapes + }, + fallback: value.fallback + }; +} + describe('v4 wire compatibility fixtures', () => { it('records how the fixture bytes were generated', () => { expect(fixture.generatedBy).toEqual({ @@ -153,4 +203,14 @@ describe('v4 wire compatibility fixtures', () => { expect(decoded).toEqual(testCase.value); expect(toHex(IntList.encode(decoded))).toBe(testCase.hex); }); + + it('decodes and re-encodes a v4 deeply nested struct/union/array composite', () => { + const testCase = fixture.cases.scene; + const bytes = fromHex(testCase.hex); + + const decoded = Scene.decode(bytes); + + expect(normalizeScene(decoded)).toEqual(testCase.value); + expect(toHex(Scene.encode(decoded))).toBe(testCase.hex); + }); }); From e287a55b0c8ec6946d0928acbbe686295bad09a4 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Mon, 1 Jun 2026 10:10:51 -0700 Subject: [PATCH 20/22] bump vitest to v4.1.0 and add vite as its no longer bundled with vitest --- package.json | 3 +- pnpm-lock.yaml | 750 +++++++++++++------------------------------------ 2 files changed, 191 insertions(+), 562 deletions(-) diff --git a/package.json b/package.json index 1a5125a..daae180 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "rollup-plugin-esbuild": "^6.2.1", "typescript": "^5.6.0", "typescript-eslint": "^8.60.0", - "vitest": "^1.6.0" + "vite": "^7.0.0", + "vitest": "^4.1.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e25d39..61d0867 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,9 +50,12 @@ importers: typescript-eslint: specifier: ^8.60.0 version: 8.60.0(eslint@9.39.4)(typescript@5.9.3) + vite: + specifier: ^7.0.0 + version: 7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2) vitest: - specifier: ^1.6.0 - version: 1.6.1(@types/node@22.19.19)(terser@5.46.0) + specifier: ^4.1.0 + version: 4.1.7(@types/node@22.19.19)(vite@7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2)) packages: @@ -64,204 +67,102 @@ packages: resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.27.7': resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.27.7': resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.27.7': resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.27.7': resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.27.7': resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.27.7': resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.27.7': resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.7': resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.27.7': resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.27.7': resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.27.7': resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.27.7': resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.27.7': resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.27.7': resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.27.7': resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.27.7': resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.27.7': resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} engines: {node: '>=18'} @@ -274,12 +175,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.7': resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} engines: {node: '>=18'} @@ -292,12 +187,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.7': resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} engines: {node: '>=18'} @@ -310,48 +199,24 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.27.7': resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.27.7': resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.27.7': resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.27.7': resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} engines: {node: '>=18'} @@ -416,10 +281,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -473,66 +334,79 @@ packages: resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.4': resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.4': resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.4': resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.4': resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.4': resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.4': resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.4': resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.4': resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.4': resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.4': resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.4': resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.4': resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.60.4': resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} @@ -564,13 +438,19 @@ packages: cpu: [x64] os: [win32] - '@sinclair/typebox@0.27.10': - resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@stellar/js-xdr@4.0.0': resolution: {integrity: sha512-+NmNa7Tk5BI5XFdy/6xGTqAN4J9a9KgCrCGhj2uEUTCBhLkch0M+QbKzNH8zEnejWe0p8w+0q5hUVX6L3OzoVA==} engines: {node: '>=20.0.0', pnpm: '>=9.0.0'} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -639,35 +519,40 @@ packages: resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitest/expect@1.6.1': - resolution: {integrity: sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==} + '@vitest/expect@4.1.7': + resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==} + + '@vitest/mocker@4.1.7': + resolution: {integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.7': + resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==} - '@vitest/runner@1.6.1': - resolution: {integrity: sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==} + '@vitest/runner@4.1.7': + resolution: {integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==} - '@vitest/snapshot@1.6.1': - resolution: {integrity: sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==} + '@vitest/snapshot@4.1.7': + resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==} - '@vitest/spy@1.6.1': - resolution: {integrity: sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==} + '@vitest/spy@4.1.7': + resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==} - '@vitest/utils@1.6.1': - resolution: {integrity: sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==} + '@vitest/utils@4.1.7': + resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.5: - resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} - engines: {node: '>=0.4.0'} - - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} @@ -696,10 +581,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -707,8 +588,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} @@ -735,17 +617,13 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -755,9 +633,6 @@ packages: resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -794,9 +669,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -813,17 +685,9 @@ packages: supports-color: optional: true - deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -836,10 +700,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} esbuild@0.27.7: resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} @@ -909,9 +771,9 @@ packages: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -955,17 +817,10 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - get-tsconfig@4.14.0: resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} @@ -985,10 +840,6 @@ packages: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} @@ -1044,9 +895,6 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -1085,10 +933,6 @@ packages: enquirer: optional: true - local-pkg@0.5.1: - resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} - engines: {node: '>=14'} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1100,9 +944,6 @@ packages: resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} engines: {node: '>=10'} - loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -1128,9 +969,6 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - mlly@1.8.2: - resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1154,6 +992,9 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -1170,10 +1011,6 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} - p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -1198,15 +1035,9 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1223,9 +1054,6 @@ packages: engines: {node: '>=0.10'} hasBin: true - pkg-types@1.3.1: - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - postcss@8.5.15: resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} @@ -1239,17 +1067,10 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1305,10 +1126,6 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} @@ -1335,8 +1152,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} @@ -1366,9 +1183,6 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@2.1.1: - resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1384,16 +1198,16 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@1.2.3: + resolution: {integrity: sha512-g62dB+w1/OEFnPvmX0yd/HnetYITOL+1nJW7kitOycOeAvmbWC/nu0fwmmQ/kupNojqExzyC/T++pST/jRJ2mQ==} + engines: {node: '>=18'} + tinyglobby@0.2.16: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} - tinypool@0.8.4: - resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} - engines: {node: '>=14.0.0'} - - tinyspy@2.2.1: - resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} to-regex-range@5.0.1: @@ -1413,10 +1227,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} - type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -1433,9 +1243,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.4: - resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} - undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -1446,27 +1253,27 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - vite-node@1.6.1: - resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.4.21: - resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} - engines: {node: ^18.0.0 || >=20.0.0} + vite@7.3.3: + resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + jiti: + optional: true less: optional: true lightningcss: @@ -1481,24 +1288,44 @@ packages: optional: true terser: optional: true + tsx: + optional: true + yaml: + optional: true - vitest@1.6.1: - resolution: {integrity: sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@4.1.7: + resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 1.6.1 - '@vitest/ui': 1.6.1 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.7 + '@vitest/browser-preview': 4.1.7 + '@vitest/browser-webdriverio': 4.1.7 + '@vitest/coverage-istanbul': 4.1.7 + '@vitest/coverage-v8': 4.1.7 + '@vitest/ui': 4.1.7 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@opentelemetry/api': + optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -1538,10 +1365,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-queue@1.2.2: - resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} - engines: {node: '>=12.20'} - snapshots: '@babel/code-frame@7.29.7': @@ -1554,150 +1377,81 @@ snapshots: '@babel/helper-validator-identifier@7.29.7': optional: true - '@esbuild/aix-ppc64@0.21.5': - optional: true - '@esbuild/aix-ppc64@0.27.7': optional: true - '@esbuild/android-arm64@0.21.5': - optional: true - '@esbuild/android-arm64@0.27.7': optional: true - '@esbuild/android-arm@0.21.5': - optional: true - '@esbuild/android-arm@0.27.7': optional: true - '@esbuild/android-x64@0.21.5': - optional: true - '@esbuild/android-x64@0.27.7': optional: true - '@esbuild/darwin-arm64@0.21.5': - optional: true - '@esbuild/darwin-arm64@0.27.7': optional: true - '@esbuild/darwin-x64@0.21.5': - optional: true - '@esbuild/darwin-x64@0.27.7': optional: true - '@esbuild/freebsd-arm64@0.21.5': - optional: true - '@esbuild/freebsd-arm64@0.27.7': optional: true - '@esbuild/freebsd-x64@0.21.5': - optional: true - '@esbuild/freebsd-x64@0.27.7': optional: true - '@esbuild/linux-arm64@0.21.5': - optional: true - '@esbuild/linux-arm64@0.27.7': optional: true - '@esbuild/linux-arm@0.21.5': - optional: true - '@esbuild/linux-arm@0.27.7': optional: true - '@esbuild/linux-ia32@0.21.5': - optional: true - '@esbuild/linux-ia32@0.27.7': optional: true - '@esbuild/linux-loong64@0.21.5': - optional: true - '@esbuild/linux-loong64@0.27.7': optional: true - '@esbuild/linux-mips64el@0.21.5': - optional: true - '@esbuild/linux-mips64el@0.27.7': optional: true - '@esbuild/linux-ppc64@0.21.5': - optional: true - '@esbuild/linux-ppc64@0.27.7': optional: true - '@esbuild/linux-riscv64@0.21.5': - optional: true - '@esbuild/linux-riscv64@0.27.7': optional: true - '@esbuild/linux-s390x@0.21.5': - optional: true - '@esbuild/linux-s390x@0.27.7': optional: true - '@esbuild/linux-x64@0.21.5': - optional: true - '@esbuild/linux-x64@0.27.7': optional: true '@esbuild/netbsd-arm64@0.27.7': optional: true - '@esbuild/netbsd-x64@0.21.5': - optional: true - '@esbuild/netbsd-x64@0.27.7': optional: true '@esbuild/openbsd-arm64@0.27.7': optional: true - '@esbuild/openbsd-x64@0.21.5': - optional: true - '@esbuild/openbsd-x64@0.27.7': optional: true '@esbuild/openharmony-arm64@0.27.7': optional: true - '@esbuild/sunos-x64@0.21.5': - optional: true - '@esbuild/sunos-x64@0.27.7': optional: true - '@esbuild/win32-arm64@0.21.5': - optional: true - '@esbuild/win32-arm64@0.27.7': optional: true - '@esbuild/win32-ia32@0.21.5': - optional: true - '@esbuild/win32-ia32@0.27.7': optional: true - '@esbuild/win32-x64@0.21.5': - optional: true - '@esbuild/win32-x64@0.27.7': optional: true @@ -1763,10 +1517,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.10 - '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -1867,10 +1617,17 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.60.4': optional: true - '@sinclair/typebox@0.27.10': {} + '@standard-schema/spec@1.1.0': {} '@stellar/js-xdr@4.0.0': {} + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} @@ -1970,44 +1727,50 @@ snapshots: '@typescript-eslint/types': 8.60.0 eslint-visitor-keys: 5.0.1 - '@vitest/expect@1.6.1': - dependencies: - '@vitest/spy': 1.6.1 - '@vitest/utils': 1.6.1 - chai: 4.5.0 - - '@vitest/runner@1.6.1': + '@vitest/expect@4.1.7': dependencies: - '@vitest/utils': 1.6.1 - p-limit: 5.0.0 - pathe: 1.1.2 + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.7 + '@vitest/utils': 4.1.7 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/snapshot@1.6.1': + '@vitest/mocker@4.1.7(vite@7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2))': dependencies: + '@vitest/spy': 4.1.7 + estree-walker: 3.0.3 magic-string: 0.30.21 - pathe: 1.1.2 - pretty-format: 29.7.0 + optionalDependencies: + vite: 7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2) - '@vitest/spy@1.6.1': + '@vitest/pretty-format@4.1.7': dependencies: - tinyspy: 2.2.1 + tinyrainbow: 3.1.0 - '@vitest/utils@1.6.1': + '@vitest/runner@4.1.7': dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 + '@vitest/utils': 4.1.7 + pathe: 2.0.3 - acorn-jsx@5.3.2(acorn@8.16.0): + '@vitest/snapshot@4.1.7': dependencies: - acorn: 8.16.0 + '@vitest/pretty-format': 4.1.7 + '@vitest/utils': 4.1.7 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.7': {} - acorn-walk@8.3.5: + '@vitest/utils@4.1.7': dependencies: - acorn: 8.15.0 + '@vitest/pretty-format': 4.1.7 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 - acorn@8.15.0: {} + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 acorn@8.16.0: {} @@ -2035,13 +1798,11 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@5.2.0: {} - ansi-styles@6.2.3: {} argparse@2.0.1: {} - assertion-error@1.1.0: {} + assertion-error@2.0.1: {} astral-regex@2.0.0: {} @@ -2065,19 +1826,9 @@ snapshots: buffer-from@1.1.2: optional: true - cac@6.7.14: {} - callsites@3.1.0: {} - chai@4.5.0: - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 + chai@6.2.2: {} chalk@4.1.2: dependencies: @@ -2086,10 +1837,6 @@ snapshots: chalk@5.2.0: {} - check-error@1.0.3: - dependencies: - get-func-name: 2.0.2 - clean-stack@2.2.0: {} cli-cursor@3.1.0: @@ -2121,8 +1868,6 @@ snapshots: concat-map@0.0.1: {} - confbox@0.1.8: {} - convert-source-map@2.0.0: {} cross-spawn@7.0.6: @@ -2135,14 +1880,8 @@ snapshots: dependencies: ms: 2.1.3 - deep-eql@4.1.4: - dependencies: - type-detect: 4.1.0 - deep-is@0.1.4: {} - diff-sequences@29.6.3: {} - eastasianwidth@0.2.0: {} emoji-regex@8.0.0: {} @@ -2151,31 +1890,7 @@ snapshots: es-module-lexer@1.7.0: {} - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 + es-module-lexer@2.1.0: {} esbuild@0.27.7: optionalDependencies: @@ -2296,17 +2011,7 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 3.0.0 - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 + expect-type@1.3.0: {} fast-deep-equal@3.1.3: {} @@ -2341,12 +2046,8 @@ snapshots: fsevents@2.3.3: optional: true - get-func-name@2.0.2: {} - get-stream@6.0.1: {} - get-stream@8.0.1: {} - get-tsconfig@4.14.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -2361,8 +2062,6 @@ snapshots: human-signals@4.3.1: {} - human-signals@5.0.0: {} - husky@9.1.7: {} ignore@5.3.2: {} @@ -2397,8 +2096,6 @@ snapshots: js-tokens@4.0.0: optional: true - js-tokens@9.0.1: {} - js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -2450,11 +2147,6 @@ snapshots: through: 2.3.8 wrap-ansi: 7.0.0 - local-pkg@0.5.1: - dependencies: - mlly: 1.8.2 - pkg-types: 1.3.1 - locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -2468,10 +2160,6 @@ snapshots: slice-ansi: 4.0.0 wrap-ansi: 6.2.0 - loupe@2.3.7: - dependencies: - get-func-name: 2.0.2 - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2495,13 +2183,6 @@ snapshots: dependencies: brace-expansion: 1.1.12 - mlly@1.8.2: - dependencies: - acorn: 8.16.0 - pathe: 2.0.3 - pkg-types: 1.3.1 - ufo: 1.6.4 - ms@2.1.3: {} nanoid@3.3.12: {} @@ -2516,6 +2197,8 @@ snapshots: object-inspect@1.13.4: {} + obug@2.1.1: {} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -2537,10 +2220,6 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@5.0.0: - dependencies: - yocto-queue: 1.2.2 - p-locate@5.0.0: dependencies: p-limit: 3.1.0 @@ -2559,12 +2238,8 @@ snapshots: path-key@4.0.0: {} - pathe@1.1.2: {} - pathe@2.0.3: {} - pathval@1.1.1: {} - picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -2573,12 +2248,6 @@ snapshots: pidtree@0.6.0: {} - pkg-types@1.3.1: - dependencies: - confbox: 0.1.8 - mlly: 1.8.2 - pathe: 2.0.3 - postcss@8.5.15: dependencies: nanoid: 3.3.12 @@ -2589,16 +2258,8 @@ snapshots: prettier@2.8.8: {} - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - punycode@2.3.1: {} - react-is@18.3.1: {} - resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -2679,8 +2340,6 @@ snapshots: signal-exit@3.0.7: {} - signal-exit@4.1.0: {} - slice-ansi@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -2711,7 +2370,7 @@ snapshots: stackback@0.0.2: {} - std-env@3.10.0: {} + std-env@4.1.0: {} string-argv@0.3.2: {} @@ -2739,10 +2398,6 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@2.1.1: - dependencies: - js-tokens: 9.0.1 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -2759,14 +2414,14 @@ snapshots: tinybench@2.9.0: {} + tinyexec@1.2.3: {} + tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinypool@0.8.4: {} - - tinyspy@2.2.1: {} + tinyrainbow@3.1.0: {} to-regex-range@5.0.1: dependencies: @@ -2782,8 +2437,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-detect@4.1.0: {} - type-fest@0.21.3: {} typescript-eslint@8.60.0(eslint@9.39.4)(typescript@5.9.3): @@ -2799,8 +2452,6 @@ snapshots: typescript@5.9.3: {} - ufo@1.6.4: {} - undici-types@6.21.0: {} unplugin-utils@0.2.5: @@ -2812,67 +2463,46 @@ snapshots: dependencies: punycode: 2.3.1 - vite-node@1.6.1(@types/node@22.19.19)(terser@5.46.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - pathe: 1.1.2 - picocolors: 1.1.1 - vite: 5.4.21(@types/node@22.19.19)(terser@5.46.0) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - vite@5.4.21(@types/node@22.19.19)(terser@5.46.0): + vite@7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2): dependencies: - esbuild: 0.21.5 + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 postcss: 8.5.15 rollup: 4.60.4 + tinyglobby: 0.2.16 optionalDependencies: '@types/node': 22.19.19 fsevents: 2.3.3 terser: 5.46.0 + yaml: 2.8.2 - vitest@1.6.1(@types/node@22.19.19)(terser@5.46.0): - dependencies: - '@vitest/expect': 1.6.1 - '@vitest/runner': 1.6.1 - '@vitest/snapshot': 1.6.1 - '@vitest/spy': 1.6.1 - '@vitest/utils': 1.6.1 - acorn-walk: 8.3.5 - chai: 4.5.0 - debug: 4.4.3 - execa: 8.0.1 - local-pkg: 0.5.1 + vitest@4.1.7(@types/node@22.19.19)(vite@7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2)): + dependencies: + '@vitest/expect': 4.1.7 + '@vitest/mocker': 4.1.7(vite@7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2)) + '@vitest/pretty-format': 4.1.7 + '@vitest/runner': 4.1.7 + '@vitest/snapshot': 4.1.7 + '@vitest/spy': 4.1.7 + '@vitest/utils': 4.1.7 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 magic-string: 0.30.21 - pathe: 1.1.2 - picocolors: 1.1.1 - std-env: 3.10.0 - strip-literal: 2.1.1 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinypool: 0.8.4 - vite: 5.4.21(@types/node@22.19.19)(terser@5.46.0) - vite-node: 1.6.1(@types/node@22.19.19)(terser@5.46.0) + tinyexec: 1.2.3 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 7.3.3(@types/node@22.19.19)(terser@5.46.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.19.19 transitivePeerDependencies: - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser + - msw which@2.0.2: dependencies: @@ -2900,5 +2530,3 @@ snapshots: yaml@2.8.2: {} yocto-queue@0.1.0: {} - - yocto-queue@1.2.2: {} From 15ef1f0749ddcf500e47d8fe71deffbfae06ac3d Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Mon, 1 Jun 2026 10:11:24 -0700 Subject: [PATCH 21/22] add pnpm workspace and define min release age for dependencies --- pnpm-workspace.yaml | 1 + 1 file changed, 1 insertion(+) create mode 100644 pnpm-workspace.yaml diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..4ff9cc2 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1 @@ +minimumReleaseAge: 4320 From 3093db2ef630f6e703d303344394ff821de2f697 Mon Sep 17 00:00:00 2001 From: Ryan Yang Date: Mon, 1 Jun 2026 10:17:50 -0700 Subject: [PATCH 22/22] fix naming of node 20 -> 22 and bump required pnpm version to 10 --- .github/workflows/tests.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b21e7e7..1e6f558 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js 20 + - name: Use Node.js 22 uses: actions/setup-node@v3 with: node-version: 22 @@ -20,7 +20,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 with: - version: 9 + version: 10 - name: Install Dependencies run: pnpm install --frozen-lockfile diff --git a/package.json b/package.json index daae180..e8e55b9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Read/write XDR encoded data structures (RFC 4506)", "engines": { "node": ">=22.0.0", - "pnpm": ">=9.0.0" + "pnpm": ">=10.0.0" }, "main": "./dist/js-xdr.cjs", "module": "./dist/js-xdr.mjs",