WIP: bootstrap and partial real Solana watcher implementation

This commit is contained in:
2026-08-16 09:17:45 +00:00
commit dc23412c3f
7232 changed files with 1687637 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
{
"main": "../../cjs/index.cjs",
"module": "../../esm/index.js"
}

View File

@@ -0,0 +1,7 @@
import type { TSESTree } from '@typescript-eslint/utils';
/**
* Yields all statement nodes in a block, including nested blocks.
*
* You can use it to find all return statements in a function body.
*/
export declare function walkStatements(body: readonly TSESTree.Statement[]): Generator<TSESTree.Statement>;

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publicKey = publicKey;
exports.privateKey = privateKey;
function publicKey(name) {
return name;
}
function privateKey(node) {
return `#private@@${node.name}`;
}

View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleScope = void 0;
const ScopeBase_1 = require("./ScopeBase");
const ScopeType_1 = require("./ScopeType");
class ModuleScope extends ScopeBase_1.ScopeBase {
constructor(scopeManager, upperScope, block) {
super(scopeManager, ScopeType_1.ScopeType.module, upperScope, block, false);
}
}
exports.ModuleScope = ModuleScope;

View File

@@ -0,0 +1,12 @@
"use strict";
function _set_prototype_of(o, p) {
exports._ = _set_prototype_of = Object.setPrototypeOf || function setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _set_prototype_of(o, p);
}
exports._ = _set_prototype_of;

View File

@@ -0,0 +1,176 @@
/**
* Internal Merkle-Damgard hash utils.
* @module
*/
import { type Input, Hash, abytes, aexists, aoutput, clean, createView, toBytes } from './utils.ts';
/** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */
export function setBigUint64(
view: DataView,
byteOffset: number,
value: bigint,
isLE: boolean
): void {
if (typeof view.setBigUint64 === 'function') return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(0xffffffff);
const wh = Number((value >> _32n) & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
/** Choice: a ? b : c */
export function Chi(a: number, b: number, c: number): number {
return (a & b) ^ (~a & c);
}
/** Majority function, true if any two inputs is true. */
export function Maj(a: number, b: number, c: number): number {
return (a & b) ^ (a & c) ^ (b & c);
}
/**
* Merkle-Damgard hash construction base class.
* Could be used to create MD5, RIPEMD, SHA1, SHA2.
*/
export abstract class HashMD<T extends HashMD<T>> extends Hash<T> {
protected abstract process(buf: DataView, offset: number): void;
protected abstract get(): number[];
protected abstract set(...args: number[]): void;
abstract destroy(): void;
protected abstract roundClean(): void;
readonly blockLen: number;
readonly outputLen: number;
readonly padOffset: number;
readonly isLE: boolean;
// For partial updates less than block size
protected buffer: Uint8Array;
protected view: DataView;
protected finished = false;
protected length = 0;
protected pos = 0;
protected destroyed = false;
constructor(blockLen: number, outputLen: number, padOffset: number, isLE: boolean) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data: Input): this {
aexists(this);
data = toBytes(data);
abytes(data);
const { view, buffer, blockLen } = this;
const len = data.length;
for (let pos = 0; pos < len; ) {
const take = Math.min(blockLen - this.pos, len - pos);
// Fast path: we have at least one block in input, cast it to view and process
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out: Uint8Array): void {
aexists(this);
aoutput(out, this);
this.finished = true;
// Padding
// We can avoid allocation of buffer for padding completely if it
// was previously not allocated here. But it won't change performance.
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
// append the bit '1' to the message
buffer[pos++] = 0b10000000;
clean(this.buffer.subarray(pos));
// we have less than padOffset left in buffer, so we cannot put length in
// current block, need process it and pad again
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
// Pad until full block byte with zeros
for (let i = pos; i < blockLen; i++) buffer[i] = 0;
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
// So we just write lowest 64 bits of that value.
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
// NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
if (len % 4) throw new Error('_sha2: outputLen should be aligned to 32bit');
const outLen = len / 4;
const state = this.get();
if (outLen > state.length) throw new Error('_sha2: outputLen bigger than state');
for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);
}
digest(): Uint8Array {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to?: T): T {
to ||= new (this.constructor as any)() as T;
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.destroyed = destroyed;
to.finished = finished;
to.length = length;
to.pos = pos;
if (length % blockLen) to.buffer.set(buffer);
return to;
}
clone(): T {
return this._cloneInto();
}
}
/**
* Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.
* Check out `test/misc/sha2-gen-iv.js` for recomputation guide.
*/
/** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */
export const SHA256_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
]);
/** Initial SHA224 state. Bits 32..64 of frac part of sqrt of primes 23..53 */
export const SHA224_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
]);
/** Initial SHA384 state. Bits 0..64 of frac part of sqrt of primes 23..53 */
export const SHA384_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([
0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,
0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,
]);
/** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */
export const SHA512_IV: Uint32Array = /* @__PURE__ */ Uint32Array.from([
0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
]);

View File

@@ -0,0 +1 @@
{"version":3,"file":"symbolFlags.js","sourceRoot":"","sources":["../../src/enums/symbolFlags.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,221 @@
import type { $ZodCheck, $ZodStringFormats } from "./checks.js";
import { $constructor } from "./core.js";
import type { $ZodType } from "./schemas.js";
import type { StandardSchemaV1 } from "./standard-schema.js";
import * as util from "./util.js";
export interface $ZodIssueBase {
readonly code?: string;
readonly input?: unknown;
readonly path: PropertyKey[];
readonly message: string;
}
export type $ZodInvalidTypeExpected = "string" | "number" | "int" | "boolean" | "bigint" | "symbol" | "undefined" | "null" | "never" | "void" | "date" | "array" | "object" | "tuple" | "record" | "map" | "set" | "file" | "nonoptional" | "nan" | "function" | (string & {});
export interface $ZodIssueInvalidType<Input = unknown> extends $ZodIssueBase {
readonly code: "invalid_type";
readonly expected: $ZodInvalidTypeExpected;
readonly input?: Input;
}
export interface $ZodIssueTooBig<Input = unknown> extends $ZodIssueBase {
readonly code: "too_big";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly maximum: number | bigint;
readonly inclusive?: boolean;
readonly exact?: boolean;
readonly input?: Input;
}
export interface $ZodIssueTooSmall<Input = unknown> extends $ZodIssueBase {
readonly code: "too_small";
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
readonly minimum: number | bigint;
/** True if the allowable range includes the minimum */
readonly inclusive?: boolean;
/** True if the allowed value is fixed (e.g.` z.length(5)`), not a range (`z.minLength(5)`) */
readonly exact?: boolean;
readonly input?: Input;
}
export interface $ZodIssueInvalidStringFormat extends $ZodIssueBase {
readonly code: "invalid_format";
readonly format: $ZodStringFormats | (string & {});
readonly pattern?: string;
readonly input?: string;
}
export interface $ZodIssueNotMultipleOf<Input extends number | bigint = number | bigint> extends $ZodIssueBase {
readonly code: "not_multiple_of";
readonly divisor: number;
readonly input?: Input;
}
export interface $ZodIssueUnrecognizedKeys extends $ZodIssueBase {
readonly code: "unrecognized_keys";
readonly keys: string[];
readonly input?: Record<string, unknown>;
}
interface $ZodIssueInvalidUnionNoMatch extends $ZodIssueBase {
readonly code: "invalid_union";
readonly errors: $ZodIssue[][];
readonly input?: unknown;
readonly discriminator?: string | undefined;
readonly options?: util.Primitive[];
readonly inclusive?: true;
}
interface $ZodIssueInvalidUnionMultipleMatch extends $ZodIssueBase {
readonly code: "invalid_union";
readonly errors: [];
readonly input?: unknown;
readonly discriminator?: string | undefined;
readonly inclusive: false;
}
export type $ZodIssueInvalidUnion = $ZodIssueInvalidUnionNoMatch | $ZodIssueInvalidUnionMultipleMatch;
export interface $ZodIssueInvalidKey<Input = unknown> extends $ZodIssueBase {
readonly code: "invalid_key";
readonly origin: "map" | "record";
readonly issues: $ZodIssue[];
readonly input?: Input;
}
export interface $ZodIssueInvalidElement<Input = unknown> extends $ZodIssueBase {
readonly code: "invalid_element";
readonly origin: "map" | "set";
readonly key: unknown;
readonly issues: $ZodIssue[];
readonly input?: Input;
}
export interface $ZodIssueInvalidValue<Input = unknown> extends $ZodIssueBase {
readonly code: "invalid_value";
readonly values: util.Primitive[];
readonly input?: Input;
}
export interface $ZodIssueCustom extends $ZodIssueBase {
readonly code: "custom";
readonly params?: Record<string, any> | undefined;
readonly input?: unknown;
}
export interface $ZodIssueStringCommonFormats extends $ZodIssueInvalidStringFormat {
format: Exclude<$ZodStringFormats, "regex" | "jwt" | "starts_with" | "ends_with" | "includes">;
}
export interface $ZodIssueStringInvalidRegex extends $ZodIssueInvalidStringFormat {
format: "regex";
pattern: string;
}
export interface $ZodIssueStringInvalidJWT extends $ZodIssueInvalidStringFormat {
format: "jwt";
algorithm?: string;
}
export interface $ZodIssueStringStartsWith extends $ZodIssueInvalidStringFormat {
format: "starts_with";
prefix: string;
}
export interface $ZodIssueStringEndsWith extends $ZodIssueInvalidStringFormat {
format: "ends_with";
suffix: string;
}
export interface $ZodIssueStringIncludes extends $ZodIssueInvalidStringFormat {
format: "includes";
includes: string;
}
export type $ZodStringFormatIssues = $ZodIssueStringCommonFormats | $ZodIssueStringInvalidRegex | $ZodIssueStringInvalidJWT | $ZodIssueStringStartsWith | $ZodIssueStringEndsWith | $ZodIssueStringIncludes;
export type $ZodIssue = $ZodIssueInvalidType | $ZodIssueTooBig | $ZodIssueTooSmall | $ZodIssueInvalidStringFormat | $ZodIssueNotMultipleOf | $ZodIssueUnrecognizedKeys | $ZodIssueInvalidUnion | $ZodIssueInvalidKey | $ZodIssueInvalidElement | $ZodIssueInvalidValue | $ZodIssueCustom;
export type $ZodIssueCode = $ZodIssue["code"];
export type $ZodInternalIssue<T extends $ZodIssueBase = $ZodIssue> = T extends any ? RawIssue<T> : never;
type RawIssue<T extends $ZodIssueBase> = T extends any ? util.Flatten<util.MakePartial<T, "message" | "path"> & {
/** The input data */
readonly input: unknown;
/** The schema or check that originated this issue. */
readonly inst?: $ZodType | $ZodCheck;
/** If `true`, Zod will continue executing checks/refinements after this issue. */
readonly continue?: boolean | undefined;
} & Record<string, unknown>> : never;
export type $ZodRawIssue<T extends $ZodIssueBase = $ZodIssue> = $ZodInternalIssue<T>;
export interface $ZodErrorMap<T extends $ZodIssueBase = $ZodIssue> {
(issue: $ZodRawIssue<T>): {
message: string;
} | string | undefined | null;
}
export interface $ZodError<T = unknown> extends Error {
type: T;
issues: $ZodIssue[];
_zod: {
output: T;
def: $ZodIssue[];
};
stack?: string;
name: string;
}
export declare const $ZodError: $constructor<$ZodError>;
interface $ZodRealError<T = any> extends $ZodError<T> {
}
export declare const $ZodRealError: $constructor<$ZodRealError>;
export type $ZodFlattenedError<T, U = string> = _FlattenedError<T, U>;
type _FlattenedError<T, U = string> = {
formErrors: U[];
fieldErrors: {
[P in keyof T]?: U[];
};
};
export declare function flattenError<T>(error: $ZodError<T>): _FlattenedError<T>;
export declare function flattenError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): _FlattenedError<T, U>;
type _ZodFormattedError<T, U = string> = T extends [any, ...any[]] ? {
[K in keyof T]?: $ZodFormattedError<T[K], U>;
} : T extends any[] ? {
[k: number]: $ZodFormattedError<T[number], U>;
} : T extends object ? util.Flatten<{
[K in keyof T]?: $ZodFormattedError<T[K], U>;
}> : any;
export type $ZodFormattedError<T, U = string> = {
_errors: U[];
} & util.Flatten<_ZodFormattedError<T, U>>;
export declare function formatError<T>(error: $ZodError<T>): $ZodFormattedError<T>;
export declare function formatError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError<T, U>;
export type $ZodErrorTree<T, U = string> = T extends util.Primitive ? {
errors: U[];
} : T extends [any, ...any[]] ? {
errors: U[];
items?: {
[K in keyof T]?: $ZodErrorTree<T[K], U>;
};
} : T extends any[] ? {
errors: U[];
items?: Array<$ZodErrorTree<T[number], U>>;
} : T extends object ? {
errors: U[];
properties?: {
[K in keyof T]?: $ZodErrorTree<T[K], U>;
};
} : {
errors: U[];
};
export declare function treeifyError<T>(error: $ZodError<T>): $ZodErrorTree<T>;
export declare function treeifyError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodErrorTree<T, U>;
/** Format a ZodError as a human-readable string in the following form.
*
* From
*
* ```ts
* ZodError {
* issues: [
* {
* expected: 'string',
* code: 'invalid_type',
* path: [ 'username' ],
* message: 'Invalid input: expected string'
* },
* {
* expected: 'number',
* code: 'invalid_type',
* path: [ 'favoriteNumbers', 1 ],
* message: 'Invalid input: expected number'
* }
* ];
* }
* ```
*
* to
*
* ```
* username
* ✖ Expected number, received string at "username
* favoriteNumbers[0]
* ✖ Invalid input: expected number
* ```
*/
export declare function toDotPath(_path: readonly (string | number | symbol | StandardSchemaV1.PathSegment)[]): string;
export declare function prettifyError(error: StandardSchemaV1.FailureResult): string;
export {};

View File

@@ -0,0 +1,170 @@
# fast-safe-stringify
Safe and fast serialization alternative to [JSON.stringify][].
Gracefully handles circular structures instead of throwing in most cases.
It could return an error string if the circular object is too complex to analyze,
e.g. in case there are proxies involved.
Provides a deterministic ("stable") version as well that will also gracefully
handle circular structures. See the example below for further information.
## Usage
The same as [JSON.stringify][].
`stringify(value[, replacer[, space[, options]]])`
```js
const safeStringify = require('fast-safe-stringify')
const o = { a: 1 }
o.o = o
console.log(safeStringify(o))
// '{"a":1,"o":"[Circular]"}'
console.log(JSON.stringify(o))
// TypeError: Converting circular structure to JSON
function replacer(key, value) {
console.log('Key:', JSON.stringify(key), 'Value:', JSON.stringify(value))
// Remove the circular structure
if (value === '[Circular]') {
return
}
return value
}
// those are also defaults limits when no options object is passed into safeStringify
// configure it to lower the limit.
const options = {
depthLimit: Number.MAX_SAFE_INTEGER,
edgesLimit: Number.MAX_SAFE_INTEGER
};
const serialized = safeStringify(o, replacer, 2, options)
// Key: "" Value: {"a":1,"o":"[Circular]"}
// Key: "a" Value: 1
// Key: "o" Value: "[Circular]"
console.log(serialized)
// {
// "a": 1
// }
```
Using the deterministic version also works the same:
```js
const safeStringify = require('fast-safe-stringify')
const o = { b: 1, a: 0 }
o.o = o
console.log(safeStringify(o))
// '{"b":1,"a":0,"o":"[Circular]"}'
console.log(safeStringify.stableStringify(o))
// '{"a":0,"b":1,"o":"[Circular]"}'
console.log(JSON.stringify(o))
// TypeError: Converting circular structure to JSON
```
A faster and side-effect free implementation is available in the
[safe-stable-stringify][] module. However it is still considered experimental
due to a new and more complex implementation.
### Replace strings constants
- `[Circular]` - when same reference is found
- `[...]` - when some limit from options object is reached
## Differences to JSON.stringify
In general the behavior is identical to [JSON.stringify][]. The [`replacer`][]
and [`space`][] options are also available.
A few exceptions exist to [JSON.stringify][] while using [`toJSON`][] or
[`replacer`][]:
### Regular safe stringify
- Manipulating a circular structure of the passed in value in a `toJSON` or the
`replacer` is not possible! It is possible for any other value and property.
- In case a circular structure is detected and the [`replacer`][] is used it
will receive the string `[Circular]` as the argument instead of the circular
object itself.
### Deterministic ("stable") safe stringify
- Manipulating the input object either in a [`toJSON`][] or the [`replacer`][]
function will not have any effect on the output. The output entirely relies on
the shape the input value had at the point passed to the stringify function!
- In case a circular structure is detected and the [`replacer`][] is used it
will receive the string `[Circular]` as the argument instead of the circular
object itself.
A side effect free variation without these limitations can be found as well
([`safe-stable-stringify`][]). It is also faster than the current
implementation. It is still considered experimental due to a new and more
complex implementation.
## Benchmarks
Although not JSON, the Node.js `util.inspect` method can be used for similar
purposes (e.g. logging) and also handles circular references.
Here we compare `fast-safe-stringify` with some alternatives:
(Lenovo T450s with a i7-5600U CPU using Node.js 8.9.4)
```md
fast-safe-stringify: simple object x 1,121,497 ops/sec ±0.75% (97 runs sampled)
fast-safe-stringify: circular x 560,126 ops/sec ±0.64% (96 runs sampled)
fast-safe-stringify: deep x 32,472 ops/sec ±0.57% (95 runs sampled)
fast-safe-stringify: deep circular x 32,513 ops/sec ±0.80% (92 runs sampled)
util.inspect: simple object x 272,837 ops/sec ±1.48% (90 runs sampled)
util.inspect: circular x 116,896 ops/sec ±1.19% (95 runs sampled)
util.inspect: deep x 19,382 ops/sec ±0.66% (92 runs sampled)
util.inspect: deep circular x 18,717 ops/sec ±0.63% (96 runs sampled)
json-stringify-safe: simple object x 233,621 ops/sec ±0.97% (94 runs sampled)
json-stringify-safe: circular x 110,409 ops/sec ±1.85% (95 runs sampled)
json-stringify-safe: deep x 8,705 ops/sec ±0.87% (96 runs sampled)
json-stringify-safe: deep circular x 8,336 ops/sec ±2.20% (93 runs sampled)
```
For stable stringify comparisons, see the performance benchmarks in the
[`safe-stable-stringify`][] readme.
## Protip
Whether `fast-safe-stringify` or alternatives are used: if the use case
consists of deeply nested objects without circular references the following
pattern will give best results.
Shallow or one level nested objects on the other hand will slow down with it.
It is entirely dependant on the use case.
```js
const stringify = require('fast-safe-stringify')
function tryJSONStringify (obj) {
try { return JSON.stringify(obj) } catch (_) {}
}
const serializedString = tryJSONStringify(deep) || stringify(deep)
```
## Acknowledgements
Sponsored by [nearForm](http://nearform.com)
## License
MIT
[`replacer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20replacer%20parameter
[`safe-stable-stringify`]: https://github.com/BridgeAR/safe-stable-stringify
[`space`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20space%20argument
[`toJSON`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior
[benchmark]: https://github.com/epoberezkin/fast-json-stable-stringify/blob/67f688f7441010cfef91a6147280cc501701e83b/benchmark
[JSON.stringify]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 20152016 Sebastian Mayr
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,29 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("object augmentation", () => {
const Animal = z
.object({
species: z.string(),
})
.augment({
population: z.number(),
});
// overwrites `species`
const ModifiedAnimal = Animal.augment({
species: z.array(z.string()),
});
ModifiedAnimal.parse({
species: ["asd"],
population: 1324,
});
const bad = () =>
ModifiedAnimal.parse({
species: "asdf",
population: 1324,
} as any);
expect(bad).toThrow();
});

View File

@@ -0,0 +1,82 @@
import * as BufferLayout from '@solana/buffer-layout';
import {Buffer} from 'buffer';
import * as Layout from './layout';
import {PublicKey} from './publickey';
import type {FeeCalculator} from './fee-calculator';
import {FeeCalculatorLayout} from './fee-calculator';
import {toBuffer} from './utils/to-buffer';
/**
* See https://github.com/solana-labs/solana/blob/0ea2843ec9cdc517572b8e62c959f41b55cf4453/sdk/src/nonce_state.rs#L29-L32
*
* @internal
*/
const NonceAccountLayout = BufferLayout.struct<
Readonly<{
authorizedPubkey: Uint8Array;
feeCalculator: Readonly<{
lamportsPerSignature: number;
}>;
nonce: Uint8Array;
state: number;
version: number;
}>
>([
BufferLayout.u32('version'),
BufferLayout.u32('state'),
Layout.publicKey('authorizedPubkey'),
Layout.publicKey('nonce'),
BufferLayout.struct<Readonly<{lamportsPerSignature: number}>>(
[FeeCalculatorLayout],
'feeCalculator',
),
]);
export const NONCE_ACCOUNT_LENGTH = NonceAccountLayout.span;
/**
* A durable nonce is a 32 byte value encoded as a base58 string.
*/
export type DurableNonce = string;
type NonceAccountArgs = {
authorizedPubkey: PublicKey;
nonce: DurableNonce;
feeCalculator: FeeCalculator;
};
/**
* NonceAccount class
*/
export class NonceAccount {
authorizedPubkey: PublicKey;
nonce: DurableNonce;
feeCalculator: FeeCalculator;
/**
* @internal
*/
constructor(args: NonceAccountArgs) {
this.authorizedPubkey = args.authorizedPubkey;
this.nonce = args.nonce;
this.feeCalculator = args.feeCalculator;
}
/**
* Deserialize NonceAccount from the account data.
*
* @param buffer account data
* @return NonceAccount
*/
static fromAccountData(
buffer: Buffer | Uint8Array | Array<number>,
): NonceAccount {
const nonceAccount = NonceAccountLayout.decode(toBuffer(buffer), 0);
return new NonceAccount({
authorizedPubkey: new PublicKey(nonceAccount.authorizedPubkey),
nonce: new PublicKey(nonceAccount.nonce).toString(),
feeCalculator: nonceAccount.feeCalculator,
});
}
}

View File

@@ -0,0 +1,300 @@
declare module "node:stream/web" {
import { TextDecoderCommon, TextDecoderOptions, TextEncoderCommon } from "node:util";
type CompressionFormat = "brotli" | "deflate" | "deflate-raw" | "gzip";
type ReadableStreamController<T> = ReadableStreamDefaultController<T> | ReadableByteStreamController;
type ReadableStreamReader<T> = ReadableStreamDefaultReader<T> | ReadableStreamBYOBReader;
type ReadableStreamReaderMode = "byob";
type ReadableStreamReadResult<T> = ReadableStreamReadValueResult<T> | ReadableStreamReadDoneResult<T>;
type ReadableStreamType = "bytes";
interface GenericTransformStream {
readonly readable: ReadableStream;
readonly writable: WritableStream;
}
interface QueuingStrategy<T = any> {
highWaterMark?: number;
size?: QueuingStrategySize<T>;
}
interface QueuingStrategyInit {
highWaterMark: number;
}
interface QueuingStrategySize<T = any> {
(chunk: T): number;
}
interface ReadableStreamBYOBReaderReadOptions {
min?: number;
}
interface ReadableStreamGenericReader {
readonly closed: Promise<void>;
cancel(reason?: any): Promise<void>;
}
interface ReadableStreamGetReaderOptions {
mode?: ReadableStreamReaderMode;
}
interface ReadableStreamIteratorOptions {
preventCancel?: boolean;
}
interface ReadableStreamReadDoneResult<T> {
done: true;
value: T | undefined;
}
interface ReadableStreamReadValueResult<T> {
done: false;
value: T;
}
interface ReadableWritablePair<R = any, W = any> {
readable: ReadableStream<R>;
writable: WritableStream<W>;
}
interface StreamPipeOptions {
preventAbort?: boolean;
preventCancel?: boolean;
preventClose?: boolean;
signal?: AbortSignal;
}
interface Transformer<I = any, O = any> {
cancel?: TransformerCancelCallback;
flush?: TransformerFlushCallback<O>;
readableType?: undefined;
start?: TransformerStartCallback<O>;
transform?: TransformerTransformCallback<I, O>;
writableType?: undefined;
}
interface TransformerCancelCallback {
(reason: any): void | PromiseLike<void>;
}
interface TransformerFlushCallback<O> {
(controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface TransformerStartCallback<O> {
(controller: TransformStreamDefaultController<O>): any;
}
interface TransformerTransformCallback<I, O> {
(chunk: I, controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface UnderlyingByteSource {
autoAllocateChunkSize?: number;
cancel?: UnderlyingSourceCancelCallback;
pull?: (controller: ReadableByteStreamController) => void | PromiseLike<void>;
start?: (controller: ReadableByteStreamController) => any;
type: "bytes";
}
interface UnderlyingDefaultSource<R = any> {
cancel?: UnderlyingSourceCancelCallback;
pull?: (controller: ReadableStreamDefaultController<R>) => void | PromiseLike<void>;
start?: (controller: ReadableStreamDefaultController<R>) => any;
type?: undefined;
}
interface UnderlyingSink<W = any> {
abort?: UnderlyingSinkAbortCallback;
close?: UnderlyingSinkCloseCallback;
start?: UnderlyingSinkStartCallback;
type?: undefined;
write?: UnderlyingSinkWriteCallback<W>;
}
interface UnderlyingSinkAbortCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSinkCloseCallback {
(): void | PromiseLike<void>;
}
interface UnderlyingSinkStartCallback {
(controller: WritableStreamDefaultController): any;
}
interface UnderlyingSinkWriteCallback<W> {
(chunk: W, controller: WritableStreamDefaultController): void | PromiseLike<void>;
}
interface UnderlyingSource<R = any> {
autoAllocateChunkSize?: number;
cancel?: UnderlyingSourceCancelCallback;
pull?: UnderlyingSourcePullCallback<R>;
start?: UnderlyingSourceStartCallback<R>;
type?: ReadableStreamType;
}
interface UnderlyingSourceCancelCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSourcePullCallback<R> {
(controller: ReadableStreamController<R>): void | PromiseLike<void>;
}
interface UnderlyingSourceStartCallback<R> {
(controller: ReadableStreamController<R>): any;
}
interface ByteLengthQueuingStrategy extends QueuingStrategy<NodeJS.ArrayBufferView> {
readonly highWaterMark: number;
readonly size: QueuingStrategySize<NodeJS.ArrayBufferView>;
}
var ByteLengthQueuingStrategy: {
prototype: ByteLengthQueuingStrategy;
new(init: QueuingStrategyInit): ByteLengthQueuingStrategy;
};
interface CompressionStream extends GenericTransformStream {
readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>;
readonly writable: WritableStream<NodeJS.BufferSource>;
}
var CompressionStream: {
prototype: CompressionStream;
new(format: CompressionFormat): CompressionStream;
};
interface CountQueuingStrategy extends QueuingStrategy {
readonly highWaterMark: number;
readonly size: QueuingStrategySize;
}
var CountQueuingStrategy: {
prototype: CountQueuingStrategy;
new(init: QueuingStrategyInit): CountQueuingStrategy;
};
interface DecompressionStream extends GenericTransformStream {
readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>;
readonly writable: WritableStream<NodeJS.BufferSource>;
}
var DecompressionStream: {
prototype: DecompressionStream;
new(format: CompressionFormat): DecompressionStream;
};
interface ReadableByteStreamController {
readonly byobRequest: ReadableStreamBYOBRequest | null;
readonly desiredSize: number | null;
close(): void;
enqueue(chunk: NodeJS.NonSharedArrayBufferView): void;
error(e?: any): void;
}
var ReadableByteStreamController: {
prototype: ReadableByteStreamController;
new(): ReadableByteStreamController;
};
interface ReadableStream<R = any> {
readonly locked: boolean;
cancel(reason?: any): Promise<void>;
getReader(options: { mode: "byob" }): ReadableStreamBYOBReader;
getReader(): ReadableStreamDefaultReader<R>;
getReader(options?: ReadableStreamGetReaderOptions): ReadableStreamReader<R>;
pipeThrough<T>(transform: ReadableWritablePair<T, R>, options?: StreamPipeOptions): ReadableStream<T>;
pipeTo(destination: WritableStream<R>, options?: StreamPipeOptions): Promise<void>;
tee(): [ReadableStream<R>, ReadableStream<R>];
[Symbol.asyncIterator](options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
values(options?: ReadableStreamIteratorOptions): ReadableStreamAsyncIterator<R>;
}
var ReadableStream: {
prototype: ReadableStream;
new(
underlyingSource: UnderlyingByteSource,
strategy?: { highWaterMark?: number },
): ReadableStream<NodeJS.NonSharedUint8Array>;
new<R = any>(underlyingSource: UnderlyingDefaultSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
new<R = any>(underlyingSource?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
from<R = any>(iterable: Iterable<R> | AsyncIterable<R>): ReadableStream<R>;
};
interface ReadableStreamAsyncIterator<T> extends NodeJS.AsyncIterator<T, BuiltinIteratorReturn, unknown> {
[Symbol.asyncIterator](): ReadableStreamAsyncIterator<T>;
}
interface ReadableStreamBYOBReader extends ReadableStreamGenericReader {
read<T extends NodeJS.NonSharedArrayBufferView>(
view: T,
options?: ReadableStreamBYOBReaderReadOptions,
): Promise<ReadableStreamReadResult<T>>;
releaseLock(): void;
}
var ReadableStreamBYOBReader: {
prototype: ReadableStreamBYOBReader;
new(stream: ReadableStream<NodeJS.NonSharedUint8Array>): ReadableStreamBYOBReader;
};
interface ReadableStreamBYOBRequest {
readonly view: NodeJS.NonSharedArrayBufferView | null;
respond(bytesWritten: number): void;
respondWithNewView(view: NodeJS.NonSharedArrayBufferView): void;
}
var ReadableStreamBYOBRequest: {
prototype: ReadableStreamBYOBRequest;
new(): ReadableStreamBYOBRequest;
};
interface ReadableStreamDefaultController<R = any> {
readonly desiredSize: number | null;
close(): void;
enqueue(chunk: R): void;
error(e?: any): void;
}
var ReadableStreamDefaultController: {
prototype: ReadableStreamDefaultController;
new(): ReadableStreamDefaultController;
};
interface ReadableStreamDefaultReader<R = any> extends ReadableStreamGenericReader {
read(): Promise<ReadableStreamReadResult<R>>;
releaseLock(): void;
}
var ReadableStreamDefaultReader: {
prototype: ReadableStreamDefaultReader;
new<R = any>(stream: ReadableStream<R>): ReadableStreamDefaultReader<R>;
};
interface TextDecoderStream extends GenericTransformStream, TextDecoderCommon {
readonly readable: ReadableStream<string>;
readonly writable: WritableStream<NodeJS.BufferSource>;
}
var TextDecoderStream: {
prototype: TextDecoderStream;
new(label?: string, options?: TextDecoderOptions): TextDecoderStream;
};
interface TextEncoderStream extends GenericTransformStream, TextEncoderCommon {
readonly readable: ReadableStream<NodeJS.NonSharedUint8Array>;
readonly writable: WritableStream<string>;
}
var TextEncoderStream: {
prototype: TextEncoderStream;
new(): TextEncoderStream;
};
interface TransformStream<I = any, O = any> {
readonly readable: ReadableStream<O>;
readonly writable: WritableStream<I>;
}
var TransformStream: {
prototype: TransformStream;
new<I = any, O = any>(
transformer?: Transformer<I, O>,
writableStrategy?: QueuingStrategy<I>,
readableStrategy?: QueuingStrategy<O>,
): TransformStream<I, O>;
};
interface TransformStreamDefaultController<O = any> {
readonly desiredSize: number | null;
enqueue(chunk: O): void;
error(reason?: any): void;
terminate(): void;
}
var TransformStreamDefaultController: {
prototype: TransformStreamDefaultController;
new(): TransformStreamDefaultController;
};
interface WritableStream<W = any> {
readonly locked: boolean;
abort(reason?: any): Promise<void>;
close(): Promise<void>;
getWriter(): WritableStreamDefaultWriter<W>;
}
var WritableStream: {
prototype: WritableStream;
new<W = any>(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>): WritableStream<W>;
};
interface WritableStreamDefaultController {
readonly signal: AbortSignal;
error(e?: any): void;
}
var WritableStreamDefaultController: {
prototype: WritableStreamDefaultController;
new(): WritableStreamDefaultController;
};
interface WritableStreamDefaultWriter<W = any> {
readonly closed: Promise<void>;
readonly desiredSize: number | null;
readonly ready: Promise<void>;
abort(reason?: any): Promise<void>;
close(): Promise<void>;
releaseLock(): void;
write(chunk: W): Promise<void>;
}
var WritableStreamDefaultWriter: {
prototype: WritableStreamDefaultWriter;
new<W = any>(stream: WritableStream<W>): WritableStreamDefaultWriter<W>;
};
}
declare module "stream/web" {
export * from "node:stream/web";
}

View File

@@ -0,0 +1,416 @@
/**
* @fileoverview Options configuration for optionator.
* @author George Zahariev
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const optionator = require("optionator");
//------------------------------------------------------------------------------
// Typedefs
//------------------------------------------------------------------------------
/**
* The options object parsed by Optionator.
* @typedef {Object} ParsedCLIOptions
* @property {boolean} cache Only check changed files
* @property {string} cacheFile Path to the cache file. Deprecated: use --cache-location
* @property {string} [cacheLocation] Path to the cache file or directory
* @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache
* @property {boolean} [color] Force enabling/disabling of color
* @property {number | "auto" | "off"} [concurrency] Number of linting threads, "auto" to choose automatically, "off" for no multithreading
* @property {string} [config] Use this configuration, overriding eslint.config.* config options if present
* @property {boolean} debug Output debugging information
* @property {boolean} envInfo Output execution environment information
* @property {boolean} errorOnUnmatchedPattern Prevent errors when pattern is unmatched
* @property {string[]} [ext] Specify JavaScript file extensions
* @property {string[]} [flag] Feature flags
* @property {boolean} fix Automatically fix problems
* @property {boolean} fixDryRun Automatically fix problems without saving the changes to the file system
* @property {("directive" | "problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (directive, problem, suggestion, layout)
* @property {string} format Use a specific output format
* @property {string[]} [global] Define global variables
* @property {boolean} [help] Show help
* @property {boolean} ignore Disable use of ignore files and patterns
* @property {string[]} [ignorePattern] Patterns of files to ignore
* @property {boolean} init Run config initialization wizard
* @property {boolean} inlineConfig Prevent comments from changing config or rules
* @property {number} maxWarnings Number of warnings to trigger nonzero exit code
* @property {string} [outputFile] Specify file to write report to
* @property {string} [parser] Specify the parser to be used
* @property {Object} [parserOptions] Specify parser options
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
* the linting operation to short circuit and not report any failures.
* @property {boolean} [passOnUnprunedSuppressions] Ignore unused suppressions
* @property {string[]} [plugin] Specify plugins
* @property {string} [printConfig] Print the configuration for the given file
* @property {boolean} [pruneSuppressions] Prune unused suppressions
* @property {boolean} quiet Report errors only
* @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable and eslint-enable directives
* @property {string | undefined} reportUnusedDisableDirectivesSeverity A severity string indicating if and how unused disable and enable directives should be tracked and reported.
* @property {Object} [rule] Specify rules
* @property {boolean} [stats] Report additional statistics
* @property {boolean} stdin Lint code provided on <STDIN>
* @property {string} [stdinFilename] Specify filename to process STDIN as
* @property {boolean} [suppressAll] Suppress all error violations
* @property {string} [suppressionsLocation] Path to the suppressions file or directory
* @property {string[]} [suppressRule] Suppress specific rules
* @property {boolean} [version] Output the version number
* @property {boolean} warnIgnored Show warnings when the file list includes ignored files
* @property {string[]} _ Positional filenames or patterns
*/
//------------------------------------------------------------------------------
// Initialization and Public Interface
//------------------------------------------------------------------------------
// exports "parse(args)", "generateHelp()", and "generateHelpForOption(optionName)"
/**
* Creates the CLI options for ESLint.
* @returns {Object} The optionator instance.
*/
module.exports = function () {
return optionator({
prepend: "eslint [options] file.js [file.js] [dir]",
defaults: {
concatRepeatedArrays: true,
mergeRepeatedObjects: true,
},
options: [
{
heading: "Basic configuration",
},
{
option: "config-lookup",
type: "Boolean",
default: "true",
description: "Disable look up for eslint.config.js",
},
{
option: "config",
alias: "c",
type: "path::String",
description:
"Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs",
},
{
option: "inspect-config",
type: "Boolean",
description:
"Open the config inspector with the current configuration",
},
{
option: "ext",
type: "[String]",
description: "Specify additional file extensions to lint",
},
{
option: "global",
type: "[String]",
description: "Define global variables",
},
{
option: "parser",
type: "String",
description: "Specify the parser to be used",
},
{
option: "parser-options",
type: "Object",
description: "Specify parser options",
},
{
heading: "Specify Rules and Plugins",
},
{
option: "plugin",
type: "[String]",
description: "Specify plugins",
},
{
option: "rule",
type: "Object",
description: "Specify rules",
},
{
heading: "Fix Problems",
},
{
option: "fix",
type: "Boolean",
default: false,
description: "Automatically fix problems",
},
{
option: "fix-dry-run",
type: "Boolean",
default: false,
description:
"Automatically fix problems without saving the changes to the file system",
},
{
option: "fix-type",
type: "Array",
description:
"Specify the types of fixes to apply (directive, problem, suggestion, layout)",
},
{
heading: "Ignore Files",
},
{
option: "ignore",
type: "Boolean",
default: "true",
description: "Disable use of ignore files and patterns",
},
{
option: "ignore-pattern",
type: "[String]",
description: "Patterns of files to ignore",
concatRepeatedArrays: [
true,
{
oneValuePerFlag: true,
},
],
},
{
heading: "Use stdin",
},
{
option: "stdin",
type: "Boolean",
default: "false",
description: "Lint code provided on <STDIN>",
},
{
option: "stdin-filename",
type: "String",
description: "Specify filename to process STDIN as",
},
{
heading: "Handle Warnings",
},
{
option: "quiet",
type: "Boolean",
default: "false",
description: "Report errors only",
},
{
option: "max-warnings",
type: "Int",
default: "-1",
description: "Number of warnings to trigger nonzero exit code",
},
{
heading: "Output",
},
{
option: "output-file",
alias: "o",
type: "path::String",
description: "Specify file to write report to",
},
{
option: "format",
alias: "f",
type: "String",
default: "stylish",
description: "Use a specific output format",
},
{
option: "color",
type: "Boolean",
alias: "no-color",
description: "Force enabling/disabling of color",
},
{
heading: "Inline configuration comments",
},
{
option: "inline-config",
type: "Boolean",
default: "true",
description: "Prevent comments from changing config or rules",
},
{
option: "report-unused-disable-directives",
type: "Boolean",
default: void 0,
description:
"Adds reported errors for unused eslint-disable and eslint-enable directives",
},
{
option: "report-unused-disable-directives-severity",
type: "String",
default: void 0,
description:
"Chooses severity level for reporting unused eslint-disable and eslint-enable directives",
enum: ["off", "warn", "error", "0", "1", "2"],
},
{
option: "report-unused-inline-configs",
type: "String",
default: void 0,
description:
"Adds reported errors for unused eslint inline config comments",
enum: ["off", "warn", "error", "0", "1", "2"],
},
{
heading: "Caching",
},
{
option: "cache",
type: "Boolean",
default: "false",
description: "Only check changed files",
},
{
option: "cache-file",
type: "path::String",
default: ".eslintcache",
description:
"Path to the cache file. Deprecated: use --cache-location",
},
{
option: "cache-location",
type: "path::String",
description: "Path to the cache file or directory",
},
{
option: "cache-strategy",
dependsOn: ["cache"],
type: "String",
default: "metadata",
enum: ["metadata", "content"],
description:
"Strategy to use for detecting changed files in the cache",
},
{
heading: "Suppressing Violations",
},
{
option: "suppress-all",
type: "Boolean",
default: "false",
description: "Suppress all violations",
},
{
option: "suppress-rule",
type: "[String]",
description: "Suppress specific rules",
},
{
option: "suppressions-location",
type: "path::String",
description: "Specify the location of the suppressions file",
},
{
option: "prune-suppressions",
type: "Boolean",
default: "false",
description: "Prune unused suppressions",
},
{
option: "pass-on-unpruned-suppressions",
type: "Boolean",
default: "false",
description: "Ignore unused suppressions",
},
{
heading: "Miscellaneous",
},
{
option: "init",
type: "Boolean",
default: "false",
description: "Run config initialization wizard",
},
{
option: "env-info",
type: "Boolean",
default: "false",
description: "Output execution environment information",
},
{
option: "error-on-unmatched-pattern",
type: "Boolean",
default: "true",
description: "Prevent errors when pattern is unmatched",
},
{
option: "exit-on-fatal-error",
type: "Boolean",
default: "false",
description: "Exit with exit code 2 in case of fatal error",
},
{
option: "warn-ignored",
type: "Boolean",
default: "true",
description:
"Suppress warnings when the file list includes ignored files",
},
{
option: "pass-on-no-patterns",
type: "Boolean",
default: false,
description:
"Exit with exit code 0 in case no file patterns are passed",
},
{
option: "debug",
type: "Boolean",
default: false,
description: "Output debugging information",
},
{
option: "help",
alias: "h",
type: "Boolean",
description: "Show help",
},
{
option: "version",
alias: "v",
type: "Boolean",
description: "Output the version number",
},
{
option: "print-config",
type: "path::String",
description: "Print the configuration for the given file",
},
{
option: "stats",
type: "Boolean",
default: "false",
description: "Add statistics to the lint report",
},
{
option: "flag",
type: "[String]",
description: "Enable a feature flag",
},
{
option: "mcp",
type: "Boolean",
description: "Start the ESLint MCP server",
},
{
option: "concurrency",
type: "Int|String",
default: "off",
description:
"Number of linting threads, auto to choose automatically, off for no multithreading",
},
],
});
};

View File

@@ -0,0 +1,9 @@
export declare const balanced: (a: string | RegExp, b: string | RegExp, str: string) => false | {
start: number;
end: number;
pre: string;
body: string;
post: string;
} | undefined;
export declare const range: (a: string, b: string, str: string) => undefined | [number, number];
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1,102 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const tsutils = __importStar(require("ts-api-utils"));
const ts = __importStar(require("typescript"));
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-meaningless-void-operator',
meta: {
type: 'suggestion',
docs: {
description: 'Disallow the `void` operator except when used to discard a value',
recommended: 'strict',
requiresTypeChecking: true,
},
fixable: 'code',
hasSuggestions: true,
messages: {
meaninglessVoidOperator: "void operator shouldn't be used on {{type}}; it should convey that a return value is being ignored",
removeVoid: "Remove 'void'",
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
checkNever: {
type: 'boolean',
description: 'Whether to suggest removing `void` when the argument has type `never`.',
},
},
},
],
},
defaultOptions: [{ checkNever: false }],
create(context, [{ checkNever }]) {
const services = utils_1.ESLintUtils.getParserServices(context);
const checker = services.program.getTypeChecker();
return {
'UnaryExpression[operator="void"]'(node) {
const fix = (fixer) => {
return fixer.removeRange([
context.sourceCode.getTokens(node)[0].range[0],
context.sourceCode.getTokens(node)[1].range[0],
]);
};
const argType = services.getTypeAtLocation(node.argument);
const unionParts = tsutils.unionConstituents(argType);
if (unionParts.every(part => tsutils.isTypeFlagSet(part, ts.TypeFlags.Void | ts.TypeFlags.Undefined))) {
context.report({
node,
messageId: 'meaninglessVoidOperator',
data: { type: checker.typeToString(argType) },
fix,
});
}
else if (checkNever &&
unionParts.every(part => tsutils.isTypeFlagSet(part, ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Never))) {
context.report({
node,
messageId: 'meaninglessVoidOperator',
data: { type: checker.typeToString(argType) },
suggest: [{ messageId: 'removeVoid', fix }],
});
}
},
};
},
});

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Tony Quetano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,16 @@
import type { CacheDurationSeconds } from '@typescript-eslint/types';
export declare const DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS = 30;
export interface CacheLike<Key, Value> {
get(key: Key): Value | undefined;
set(key: Key, value: Value): this;
}
/**
* A map with key-level expiration.
*/
export declare class ExpiringCache<Key, Value> implements CacheLike<Key, Value> {
#private;
constructor(cacheDurationSeconds: CacheDurationSeconds);
clear(): void;
get(key: Key): Value | undefined;
set(key: Key, value: Value): this;
}

View File

@@ -0,0 +1,425 @@
'use strict';
var buffer = require('buffer');
var eventemitter3 = require('eventemitter3');
// node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js
var WebSocketBrowserImpl = class extends eventemitter3.EventEmitter {
socket;
/** Instantiate a WebSocket class
* @constructor
* @param {String} address - url to a websocket server
* @param {WebSocketBrowserOptions} options - websocket options
* @return {WebSocketBrowserImpl} - returns a WebSocket instance
*/
constructor(address, options) {
super();
this.socket = new window.WebSocket(address, options.protocols);
this.socket.onopen = () => this.emit("open");
this.socket.onmessage = (event) => this.emit("message", event.data);
this.socket.onerror = (error) => this.emit("error", error);
this.socket.onclose = (event) => {
this.emit("close", event.code, event.reason);
};
}
/**
* Sends data through a websocket connection
* @method
* @param {(String|Object)} data - data to be sent via websocket
* @param {Object} optionsOrCallback - ws options
* @param {Function} callback - a callback called once the data is sent
* @return {Undefined}
*/
send(data, optionsOrCallback, callback) {
const cb = callback || optionsOrCallback;
try {
this.socket.send(data);
cb();
} catch (error) {
cb(error);
}
}
/**
* Closes an underlying socket
* @method
* @param {Number} code - status code explaining why the connection is being closed
* @param {String} reason - a description why the connection is closing
* @return {Undefined}
* @throws {Error}
*/
close(code, reason) {
this.socket.close(code, reason);
}
addEventListener(type, listener, options) {
this.socket.addEventListener(type, listener, options);
}
};
function WebSocket(address, options) {
return new WebSocketBrowserImpl(address, options);
}
// src/lib/utils.ts
var DefaultDataPack = class {
encode(value) {
return JSON.stringify(value);
}
decode(value) {
return JSON.parse(value);
}
};
// src/lib/client.ts
var CommonClient = class extends eventemitter3.EventEmitter {
address;
rpc_id;
queue;
options;
autoconnect;
ready;
reconnect;
reconnect_timer_id;
reconnect_interval;
max_reconnects;
rest_options;
current_reconnects;
generate_request_id;
socket;
webSocketFactory;
dataPack;
/**
* Instantiate a Client class.
* @constructor
* @param {webSocketFactory} webSocketFactory - factory method for WebSocket
* @param {String} address - url to a websocket server
* @param {Object} options - ws options object with reconnect parameters
* @param {Function} generate_request_id - custom generation request Id
* @param {DataPack} dataPack - data pack contains encoder and decoder
* @return {CommonClient}
*/
constructor(webSocketFactory, address = "ws://localhost:8080", {
autoconnect = true,
reconnect = true,
reconnect_interval = 1e3,
max_reconnects = 5,
...rest_options
} = {}, generate_request_id, dataPack) {
super();
this.webSocketFactory = webSocketFactory;
this.queue = {};
this.rpc_id = 0;
this.address = address;
this.autoconnect = autoconnect;
this.ready = false;
this.reconnect = reconnect;
this.reconnect_timer_id = void 0;
this.reconnect_interval = reconnect_interval;
this.max_reconnects = max_reconnects;
this.rest_options = rest_options;
this.current_reconnects = 0;
this.generate_request_id = generate_request_id || (() => typeof this.rpc_id === "number" ? ++this.rpc_id : Number(this.rpc_id) + 1);
if (!dataPack) this.dataPack = new DefaultDataPack();
else this.dataPack = dataPack;
if (this.autoconnect)
this._connect(this.address, {
autoconnect: this.autoconnect,
reconnect: this.reconnect,
reconnect_interval: this.reconnect_interval,
max_reconnects: this.max_reconnects,
...this.rest_options
});
}
/**
* Connects to a defined server if not connected already.
* @method
* @return {Undefined}
*/
connect() {
if (this.socket) return;
this._connect(this.address, {
autoconnect: this.autoconnect,
reconnect: this.reconnect,
reconnect_interval: this.reconnect_interval,
max_reconnects: this.max_reconnects,
...this.rest_options
});
}
/**
* Calls a registered RPC method on server.
* @method
* @param {String} method - RPC method name
* @param {Object|Array} params - optional method parameters
* @param {Number} timeout - RPC reply timeout value
* @param {Object} ws_opts - options passed to ws
* @return {Promise}
*/
call(method, params, timeout, ws_opts) {
if (!ws_opts && "object" === typeof timeout) {
ws_opts = timeout;
timeout = null;
}
return new Promise((resolve, reject) => {
if (!this.ready) return reject(new Error("socket not ready"));
const rpc_id = this.generate_request_id(method, params);
const message = {
jsonrpc: "2.0",
method,
params: params || void 0,
id: rpc_id
};
this.socket.send(this.dataPack.encode(message), ws_opts, (error) => {
if (error) return reject(error);
this.queue[rpc_id] = { promise: [resolve, reject] };
if (timeout) {
this.queue[rpc_id].timeout = setTimeout(() => {
delete this.queue[rpc_id];
reject(new Error("reply timeout"));
}, timeout);
}
});
});
}
/**
* Logins with the other side of the connection.
* @method
* @param {Object} params - Login credentials object
* @return {Promise}
*/
async login(params) {
const resp = await this.call("rpc.login", params);
if (!resp) throw new Error("authentication failed");
return resp;
}
/**
* Fetches a list of client's methods registered on server.
* @method
* @return {Array}
*/
async listMethods() {
return await this.call("__listMethods");
}
/**
* Sends a JSON-RPC 2.0 notification to server.
* @method
* @param {String} method - RPC method name
* @param {Object} params - optional method parameters
* @return {Promise}
*/
notify(method, params) {
return new Promise((resolve, reject) => {
if (!this.ready) return reject(new Error("socket not ready"));
const message = {
jsonrpc: "2.0",
method,
params
};
this.socket.send(this.dataPack.encode(message), (error) => {
if (error) return reject(error);
resolve();
});
});
}
/**
* Subscribes for a defined event.
* @method
* @param {String|Array} event - event name
* @return {Undefined}
* @throws {Error}
*/
async subscribe(event) {
if (typeof event === "string") event = [event];
const result = await this.call("rpc.on", event);
if (typeof event === "string" && result[event] !== "ok")
throw new Error(
"Failed subscribing to an event '" + event + "' with: " + result[event]
);
return result;
}
/**
* Unsubscribes from a defined event.
* @method
* @param {String|Array} event - event name
* @return {Undefined}
* @throws {Error}
*/
async unsubscribe(event) {
if (typeof event === "string") event = [event];
const result = await this.call("rpc.off", event);
if (typeof event === "string" && result[event] !== "ok")
throw new Error("Failed unsubscribing from an event with: " + result);
return result;
}
/**
* Closes a WebSocket connection gracefully.
* @method
* @param {Number} code - socket close code
* @param {String} data - optional data to be sent before closing
* @return {Undefined}
*/
close(code, data) {
if (this.socket) this.socket.close(code || 1e3, data);
}
/**
* Enable / disable automatic reconnection.
* @method
* @param {Boolean} reconnect - enable / disable reconnection
* @return {Undefined}
*/
setAutoReconnect(reconnect) {
this.reconnect = reconnect;
}
/**
* Set the interval between reconnection attempts.
* @method
* @param {Number} interval - reconnection interval in milliseconds
* @return {Undefined}
*/
setReconnectInterval(interval) {
this.reconnect_interval = interval;
}
/**
* Set the maximum number of reconnection attempts.
* @method
* @param {Number} max_reconnects - maximum reconnection attempts
* @return {Undefined}
*/
setMaxReconnects(max_reconnects) {
this.max_reconnects = max_reconnects;
}
/**
* Get the current number of reconnection attempts made.
* @method
* @return {Number} current reconnection attempts
*/
getCurrentReconnects() {
return this.current_reconnects;
}
/**
* Get the maximum number of reconnection attempts.
* @method
* @return {Number} maximum reconnection attempts
*/
getMaxReconnects() {
return this.max_reconnects;
}
/**
* Check if the client is currently attempting to reconnect.
* @method
* @return {Boolean} true if reconnection is in progress
*/
isReconnecting() {
return this.reconnect_timer_id !== void 0;
}
/**
* Check if the client will attempt to reconnect on the next close event.
* @method
* @return {Boolean} true if reconnection will be attempted
*/
willReconnect() {
return this.reconnect && (this.max_reconnects === 0 || this.current_reconnects < this.max_reconnects);
}
/**
* Connection/Message handler.
* @method
* @private
* @param {String} address - WebSocket API address
* @param {Object} options - ws options object
* @return {Undefined}
*/
_connect(address, options) {
clearTimeout(this.reconnect_timer_id);
this.socket = this.webSocketFactory(address, options);
this.socket.addEventListener("open", () => {
this.ready = true;
this.emit("open");
this.current_reconnects = 0;
});
this.socket.addEventListener("message", ({ data: message }) => {
if (message instanceof ArrayBuffer)
message = buffer.Buffer.from(message).toString();
try {
message = this.dataPack.decode(message);
} catch (_error) {
return;
}
if (message.notification && this.listeners(message.notification).length) {
if (!Object.keys(message.params).length)
return this.emit(message.notification);
const args = [message.notification];
if (message.params.constructor === Object) args.push(message.params);
else
for (let i = 0; i < message.params.length; i++)
args.push(message.params[i]);
return Promise.resolve().then(() => {
this.emit.apply(this, args);
});
}
if (!this.queue[message.id]) {
if (message.method) {
return Promise.resolve().then(() => {
this.emit(message.method, message?.params);
});
}
return;
}
if ("error" in message === "result" in message)
this.queue[message.id].promise[1](
new Error(
'Server response malformed. Response must include either "result" or "error", but not both.'
)
);
if (this.queue[message.id].timeout)
clearTimeout(this.queue[message.id].timeout);
if (message.error) this.queue[message.id].promise[1](message.error);
else this.queue[message.id].promise[0](message.result);
delete this.queue[message.id];
});
this.socket.addEventListener("error", (error) => this.emit("error", error));
this.socket.addEventListener("close", ({ code, reason }) => {
if (this.ready)
setTimeout(() => this.emit("close", code, reason), 0);
this.ready = false;
this.socket = void 0;
if (code === 1e3) return;
this.current_reconnects++;
if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0))
this.reconnect_timer_id = setTimeout(
() => this._connect(address, options),
this.reconnect_interval
);
else if (this.reconnect && this.max_reconnects > 0 && this.current_reconnects >= this.max_reconnects) {
setTimeout(() => this.emit("max_reconnects_reached", code, reason), 1);
}
});
}
};
// src/index.browser.ts
var Client = class extends CommonClient {
constructor(address = "ws://localhost:8080", {
autoconnect = true,
reconnect = true,
reconnect_interval = 1e3,
max_reconnects = 5,
...rest_options
} = {}, generate_request_id) {
super(
WebSocket,
address,
{
autoconnect,
reconnect,
reconnect_interval,
max_reconnects,
...rest_options
},
generate_request_id
);
}
};
exports.Client = Client;
exports.CommonClient = CommonClient;
exports.DefaultDataPack = DefaultDataPack;
exports.WebSocket = WebSocket;
//# sourceMappingURL=index.browser.cjs.map
//# sourceMappingURL=index.browser.cjs.map

View File

@@ -0,0 +1,58 @@
/**
* @fileoverview Common utils for regular expressions.
* @author Josh Goldberg
* @author Toru Nagashima
*/
"use strict";
const { RegExpValidator } = require("@eslint-community/regexpp");
const REGEXPP_LATEST_ECMA_VERSION = 2025;
/**
* Checks if the given regular expression pattern would be valid with the `u` flag.
* @param {number} ecmaVersion ECMAScript version to parse in.
* @param {string} pattern The regular expression pattern to verify.
* @param {"u"|"v"} flag The type of Unicode flag
* @returns {boolean} `true` if the pattern would be valid with the `u` flag.
* `false` if the pattern would be invalid with the `u` flag or the configured
* ecmaVersion doesn't support the `u` flag.
*/
function isValidWithUnicodeFlag(ecmaVersion, pattern, flag = "u") {
if (flag === "u" && ecmaVersion <= 5) {
// ecmaVersion <= 5 doesn't support the 'u' flag
return false;
}
if (flag === "v" && ecmaVersion <= 2023) {
return false;
}
const validator = new RegExpValidator({
ecmaVersion: Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION),
});
try {
validator.validatePattern(
pattern,
void 0,
void 0,
flag === "u"
? {
unicode: /* uFlag = */ true,
}
: {
unicodeSets: true,
},
);
} catch {
return false;
}
return true;
}
module.exports = {
isValidWithUnicodeFlag,
REGEXPP_LATEST_ECMA_VERSION,
};

View File

@@ -0,0 +1,114 @@
'use strict'
const Redact = require('@pinojs/redact')
const { redactFmtSym, wildcardFirstSym } = require('./symbols')
// Custom rx regex equivalent to fast-redact's rx
const rx = /[^.[\]]+|\[([^[\]]*?)\]/g
const CENSOR = '[Redacted]'
const strict = false // TODO should this be configurable?
function redaction (opts, serialize) {
const { paths, censor, remove } = handle(opts)
const shape = paths.reduce((o, str) => {
rx.lastIndex = 0
const first = rx.exec(str)
const next = rx.exec(str)
// ns is the top-level path segment, brackets + quoting removed.
let ns = first[1] !== undefined
? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, '$1')
: first[0]
if (ns === '*') {
ns = wildcardFirstSym
}
// top level key:
if (next === null) {
o[ns] = null
return o
}
// path with at least two segments:
// if ns is already redacted at the top level, ignore lower level redactions
if (o[ns] === null) {
return o
}
const { index } = next
const nextPath = `${str.substr(index, str.length - 1)}`
o[ns] = o[ns] || []
// shape is a mix of paths beginning with literal values and wildcard
// paths [ "a.b.c", "*.b.z" ] should reduce to a shape of
// { "a": [ "b.c", "b.z" ], *: [ "b.z" ] }
// note: "b.z" is in both "a" and * arrays because "a" matches the wildcard.
// (* entry has wildcardFirstSym as key)
if (ns !== wildcardFirstSym && o[ns].length === 0) {
// first time ns's get all '*' redactions so far
o[ns].push(...(o[wildcardFirstSym] || []))
}
if (ns === wildcardFirstSym) {
// new * path gets added to all previously registered literal ns's.
Object.keys(o).forEach(function (k) {
if (o[k]) {
o[k].push(nextPath)
}
})
}
o[ns].push(nextPath)
return o
}, {})
// the redactor assigned to the format symbol key
// provides top level redaction for instances where
// an object is interpolated into the msg string
const result = {
[redactFmtSym]: Redact({ paths, censor, serialize, strict, remove })
}
const topCensor = (...args) => {
return typeof censor === 'function' ? serialize(censor(...args)) : serialize(censor)
}
return [...Object.keys(shape), ...Object.getOwnPropertySymbols(shape)].reduce((o, k) => {
// top level key:
if (shape[k] === null) {
o[k] = (value) => topCensor(value, [k])
} else {
const wrappedCensor = typeof censor === 'function'
? (value, path) => {
return censor(value, [k, ...path])
}
: censor
o[k] = Redact({
paths: shape[k],
censor: wrappedCensor,
serialize,
strict,
remove
})
}
return o
}, result)
}
function handle (opts) {
if (Array.isArray(opts)) {
opts = { paths: opts, censor: CENSOR }
return opts
}
let { paths, censor = CENSOR, remove } = opts
if (Array.isArray(paths) === false) { throw Error('pino redact must contain an array of strings') }
if (remove === true) censor = undefined
return { paths, censor, remove }
}
module.exports = redaction

View File

@@ -0,0 +1,8 @@
export declare namespace enumUtil {
type UnionToIntersectionFn<T> = (T extends unknown ? (k: () => T) => void : never) extends (k: infer Intersection) => void ? Intersection : never;
type GetUnionLast<T> = UnionToIntersectionFn<T> extends () => infer Last ? Last : never;
type UnionToTuple<T, Tuple extends unknown[] = []> = [T] extends [never] ? Tuple : UnionToTuple<Exclude<T, GetUnionLast<T>>, [GetUnionLast<T>, ...Tuple]>;
type CastToStringTuple<T> = T extends [string, ...string[]] ? T : never;
export type UnionToTupleString<T> = CastToStringTuple<UnionToTuple<T>>;
export {};
}

View File

@@ -0,0 +1,71 @@
import { H as HoistMocksOptions } from './hoistMocks.d-w2ILr1dG.js';
export { c as createManualModuleSource } from './hoistMocks.d-w2ILr1dG.js';
import { AutomockOptions } from './automock.js';
export { automockModule } from './automock.js';
import { Plugin, Rollup, ViteDevServer } from 'vite';
import { SourceMap } from 'magic-string';
import { M as MockerRegistry, S as ServerMockResolution, f as ServerIdResolution } from './types.d-BjI5eAwu.js';
export { findMockRedirect } from './redirect.js';
declare function automockPlugin(options?: AutomockOptions): Plugin;
interface DynamicImportPluginOptions {
/**
* @default `"__vitest_mocker__"`
*/
globalThisAccessor?: string;
filter?: (id: string) => boolean;
}
declare function dynamicImportPlugin(options?: DynamicImportPluginOptions): Plugin;
interface HoistMocksPluginOptions extends Omit<HoistMocksOptions, "regexpHoistable"> {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
/**
* overrides include/exclude options
*/
filter?: (id: string) => boolean;
}
declare function hoistMocksPlugin(options?: HoistMocksPluginOptions): Plugin;
declare function hoistMockAndResolve(code: string, id: string, parse: Rollup.PluginContext["parse"], options?: HoistMocksOptions): HoistMocksResult | undefined;
interface HoistMocksResult {
code: string;
map: SourceMap;
}
interface InterceptorPluginOptions {
/**
* @default "__vitest_mocker__"
*/
globalThisAccessor?: string;
registry?: MockerRegistry;
}
declare function interceptorPlugin(options?: InterceptorPluginOptions): Plugin;
interface MockerPluginOptions extends AutomockOptions {
hoistMocks?: HoistMocksPluginOptions;
}
declare function mockerPlugin(options?: MockerPluginOptions): Plugin[];
interface ServerResolverOptions {
/**
* @default ['/node_modules/']
*/
moduleDirectories?: string[];
}
declare class ServerMockResolver {
private server;
private options;
constructor(server: ViteDevServer, options?: ServerResolverOptions);
resolveMock(rawId: string, importer: string, options: {
mock: "spy" | "factory" | "auto";
}): Promise<ServerMockResolution>;
invalidate(ids: string[]): void;
resolveId(id: string, importer?: string): Promise<ServerIdResolution | null>;
private normalizeResolveIdToUrl;
private resolveMockId;
private resolveModule;
}
export { AutomockOptions as AutomockPluginOptions, ServerMockResolver, automockPlugin, dynamicImportPlugin, hoistMockAndResolve as hoistMocks, hoistMocksPlugin, interceptorPlugin, mockerPlugin };
export type { HoistMocksPluginOptions, HoistMocksResult, InterceptorPluginOptions, ServerResolverOptions };

View File

@@ -0,0 +1,255 @@
import { EventEmitter } from 'eventemitter3';
import NodeWebSocket from 'ws';
type BrowserWebSocketType = InstanceType<typeof WebSocket>;
type NodeWebSocketType = InstanceType<typeof NodeWebSocket>;
type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions;
interface IWSClientAdditionalOptions {
autoconnect?: boolean;
reconnect?: boolean;
reconnect_interval?: number;
max_reconnects?: number;
}
interface ICommonWebSocketFactory {
(address: string, options: IWSClientAdditionalOptions): ICommonWebSocket;
}
interface ICommonWebSocket {
send: (data: Parameters<BrowserWebSocketType["send"]>[0], optionsOrCallback: ((error?: Error) => void) | Parameters<NodeWebSocketType["send"]>[1], callback?: (error?: Error) => void) => void;
close: (code?: number, reason?: string) => void;
addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
}
/**
* WebSocket implements a browser-side WebSocket specification.
* @module Client
*/
type WebSocketBrowserOptions = {
/**
* One or more protocols passed to the websocket constructor
* @link https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket
*/
protocols?: string | string[];
};
declare class WebSocketBrowserImpl extends EventEmitter {
socket: BrowserWebSocketType;
/** Instantiate a WebSocket class
* @constructor
* @param {String} address - url to a websocket server
* @param {WebSocketBrowserOptions} options - websocket options
* @return {WebSocketBrowserImpl} - returns a WebSocket instance
*/
constructor(address: string, options: WebSocketBrowserOptions);
/**
* Sends data through a websocket connection
* @method
* @param {(String|Object)} data - data to be sent via websocket
* @param {Object} optionsOrCallback - ws options
* @param {Function} callback - a callback called once the data is sent
* @return {Undefined}
*/
send(data: Parameters<BrowserWebSocketType["send"]>[0], optionsOrCallback: (error?: Error) => void | Parameters<NodeWebSocketType["send"]>[1], callback?: () => void): void;
/**
* Closes an underlying socket
* @method
* @param {Number} code - status code explaining why the connection is being closed
* @param {String} reason - a description why the connection is closing
* @return {Undefined}
* @throws {Error}
*/
close(code?: number, reason?: string): void;
addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
}
/**
* factory method for common WebSocket instance
* @method
* @param {String} address - url to a websocket server
* @param {(Object)} options - websocket options
* @return {Undefined}
*/
declare function WebSocket$1(address: string, options: IWSClientAdditionalOptions & WebSocketBrowserOptions): WebSocketBrowserImpl;
interface DataPack<T, R extends string | ArrayBufferLike | Blob | ArrayBufferView> {
encode(value: T): R;
decode(value: R): T;
}
declare class DefaultDataPack implements DataPack<Object, string> {
encode(value: Object): string;
decode(value: string): Object;
}
/**
* "Client" wraps "ws" or a browser-implemented "WebSocket" library
* according to the environment providing JSON RPC 2.0 support on top.
* @module Client
*/
interface IQueueElement {
promise: [
Parameters<ConstructorParameters<typeof Promise>[0]>[0],
Parameters<ConstructorParameters<typeof Promise>[0]>[1]
];
timeout?: ReturnType<typeof setTimeout>;
}
interface IQueue {
[x: number | string]: IQueueElement;
}
interface IWSRequestParams {
[x: string]: any;
[x: number]: any;
}
declare class CommonClient extends EventEmitter {
private address;
private rpc_id;
private queue;
private options;
private autoconnect;
private ready;
private reconnect;
private reconnect_timer_id;
private reconnect_interval;
private max_reconnects;
private rest_options;
private current_reconnects;
private generate_request_id;
private socket;
private webSocketFactory;
private dataPack;
/**
* Instantiate a Client class.
* @constructor
* @param {webSocketFactory} webSocketFactory - factory method for WebSocket
* @param {String} address - url to a websocket server
* @param {Object} options - ws options object with reconnect parameters
* @param {Function} generate_request_id - custom generation request Id
* @param {DataPack} dataPack - data pack contains encoder and decoder
* @return {CommonClient}
*/
constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: {
autoconnect?: boolean;
reconnect?: boolean;
reconnect_interval?: number;
max_reconnects?: number;
}, generate_request_id?: (method: string, params: object | Array<any>) => number | string, dataPack?: DataPack<object, string>);
/**
* Connects to a defined server if not connected already.
* @method
* @return {Undefined}
*/
connect(): void;
/**
* Calls a registered RPC method on server.
* @method
* @param {String} method - RPC method name
* @param {Object|Array} params - optional method parameters
* @param {Number} timeout - RPC reply timeout value
* @param {Object} ws_opts - options passed to ws
* @return {Promise}
*/
call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters<NodeWebSocketType["send"]>[1]): Promise<unknown>;
/**
* Logins with the other side of the connection.
* @method
* @param {Object} params - Login credentials object
* @return {Promise}
*/
login(params: IWSRequestParams): Promise<unknown>;
/**
* Fetches a list of client's methods registered on server.
* @method
* @return {Array}
*/
listMethods(): Promise<unknown>;
/**
* Sends a JSON-RPC 2.0 notification to server.
* @method
* @param {String} method - RPC method name
* @param {Object} params - optional method parameters
* @return {Promise}
*/
notify(method: string, params?: IWSRequestParams): Promise<void>;
/**
* Subscribes for a defined event.
* @method
* @param {String|Array} event - event name
* @return {Undefined}
* @throws {Error}
*/
subscribe(event: string | Array<string>): Promise<unknown>;
/**
* Unsubscribes from a defined event.
* @method
* @param {String|Array} event - event name
* @return {Undefined}
* @throws {Error}
*/
unsubscribe(event: string | Array<string>): Promise<unknown>;
/**
* Closes a WebSocket connection gracefully.
* @method
* @param {Number} code - socket close code
* @param {String} data - optional data to be sent before closing
* @return {Undefined}
*/
close(code?: number, data?: string): void;
/**
* Enable / disable automatic reconnection.
* @method
* @param {Boolean} reconnect - enable / disable reconnection
* @return {Undefined}
*/
setAutoReconnect(reconnect: boolean): void;
/**
* Set the interval between reconnection attempts.
* @method
* @param {Number} interval - reconnection interval in milliseconds
* @return {Undefined}
*/
setReconnectInterval(interval: number): void;
/**
* Set the maximum number of reconnection attempts.
* @method
* @param {Number} max_reconnects - maximum reconnection attempts
* @return {Undefined}
*/
setMaxReconnects(max_reconnects: number): void;
/**
* Get the current number of reconnection attempts made.
* @method
* @return {Number} current reconnection attempts
*/
getCurrentReconnects(): number;
/**
* Get the maximum number of reconnection attempts.
* @method
* @return {Number} maximum reconnection attempts
*/
getMaxReconnects(): number;
/**
* Check if the client is currently attempting to reconnect.
* @method
* @return {Boolean} true if reconnection is in progress
*/
isReconnecting(): boolean;
/**
* Check if the client will attempt to reconnect on the next close event.
* @method
* @return {Boolean} true if reconnection will be attempted
*/
willReconnect(): boolean;
/**
* Connection/Message handler.
* @method
* @private
* @param {String} address - WebSocket API address
* @param {Object} options - ws options object
* @return {Undefined}
*/
private _connect;
}
declare class Client extends CommonClient {
constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: IWSClientAdditionalOptions & WebSocketBrowserOptions, generate_request_id?: (method: string, params: object | Array<any>) => number | string);
}
export { type BrowserWebSocketType, Client, CommonClient, type DataPack, DefaultDataPack, type ICommonWebSocket, type ICommonWebSocketFactory, type IQueue, type IWSClientAdditionalOptions, type IWSRequestParams, type NodeWebSocketType, type NodeWebSocketTypeOptions, WebSocket$1 as WebSocket, type WebSocketBrowserOptions };

View File

@@ -0,0 +1,108 @@
import * as util from "../core/util.js";
const error = () => {
const Sizable = {
string: { unit: "символів", verb: "матиме" },
file: { unit: "байтів", verb: "матиме" },
array: { unit: "елементів", verb: "матиме" },
set: { unit: "елементів", verb: "матиме" },
};
function getSizing(origin) {
return Sizable[origin] ?? null;
}
const FormatDictionary = {
regex: "вхідні дані",
email: "адреса електронної пошти",
url: "URL",
emoji: "емодзі",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "дата та час ISO",
date: "дата ISO",
time: "час ISO",
duration: "тривалість ISO",
ipv4: "адреса IPv4",
ipv6: "адреса IPv6",
cidrv4: "діапазон IPv4",
cidrv6: "діапазон IPv6",
base64: "рядок у кодуванні base64",
base64url: "рядок у кодуванні base64url",
json_string: "рядок JSON",
e164: "номер E.164",
jwt: "JWT",
template_literal: "вхідні дані",
};
const TypeDictionary = {
nan: "NaN",
number: "число",
array: "масив",
};
return (issue) => {
switch (issue.code) {
case "invalid_type": {
const expected = TypeDictionary[issue.expected] ?? issue.expected;
const receivedType = util.parsedType(issue.input);
const received = TypeDictionary[receivedType] ?? receivedType;
if (/^[A-Z]/.test(issue.expected)) {
return `Неправильні вхідні дані: очікується instanceof ${issue.expected}, отримано ${received}`;
}
return `Неправильні вхідні дані: очікується ${expected}, отримано ${received}`;
}
case "invalid_value":
if (issue.values.length === 1)
return `Неправильні вхідні дані: очікується ${util.stringifyPrimitive(issue.values[0])}`;
return `Неправильна опція: очікується одне з ${util.joinValues(issue.values, "|")}`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing)
return `Занадто велике: очікується, що ${issue.origin ?? "значення"} ${sizing.verb} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "елементів"}`;
return `Занадто велике: очікується, що ${issue.origin ?? "значення"} буде ${adj}${issue.maximum.toString()}`;
}
case "too_small": {
const adj = issue.inclusive ? ">=" : ">";
const sizing = getSizing(issue.origin);
if (sizing) {
return `Занадто мале: очікується, що ${issue.origin} ${sizing.verb} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
}
return `Занадто мале: очікується, що ${issue.origin} буде ${adj}${issue.minimum.toString()}`;
}
case "invalid_format": {
const _issue = issue;
if (_issue.format === "starts_with")
return `Неправильний рядок: повинен починатися з "${_issue.prefix}"`;
if (_issue.format === "ends_with")
return `Неправильний рядок: повинен закінчуватися на "${_issue.suffix}"`;
if (_issue.format === "includes")
return `Неправильний рядок: повинен містити "${_issue.includes}"`;
if (_issue.format === "regex")
return `Неправильний рядок: повинен відповідати шаблону ${_issue.pattern}`;
return `Неправильний ${FormatDictionary[_issue.format] ?? issue.format}`;
}
case "not_multiple_of":
return `Неправильне число: повинно бути кратним ${issue.divisor}`;
case "unrecognized_keys":
return `Нерозпізнаний ключ${issue.keys.length > 1 ? "і" : ""}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
return `Неправильний ключ у ${issue.origin}`;
case "invalid_union":
return "Неправильні вхідні дані";
case "invalid_element":
return `Неправильне значення у ${issue.origin}`;
default:
return `Неправильні вхідні дані`;
}
};
};
export default function () {
return {
localeError: error(),
};
}

View File

@@ -0,0 +1,39 @@
# Nano ID
<img src="https://ai.github.io/nanoid/logo.svg" align="right"
alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
**English** | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md)
A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
> “An amazing level of senseless perfectionism,
> which is simply impossible not to respect.”
* **Small.** 130 bytes (minified and gzipped). No dependencies.
[Size Limit] controls the size.
* **Fast.** It is 2 times faster than UUID.
* **Safe.** It uses hardware random generator. Can be used in clusters.
* **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`).
So ID size was reduced from 36 to 21 symbols.
* **Portable.** Nano ID was ported
to [20 programming languages](#other-programming-languages).
```js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
```
Supports modern browsers, IE [with Babel], Node.js and React Native.
[online tool]: https://gitpod.io/#https://github.com/ai/nanoid/
[with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/
[Size Limit]: https://github.com/ai/size-limit
<a href="https://evilmartians.com/?utm_source=nanoid">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
alt="Sponsored by Evil Martians" width="236" height="54">
</a>
## Docs
Read full docs **[here](https://github.com/ai/nanoid#readme)**.