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,278 @@
/**
* @fileoverview Rule to flag block statements that do not use the one true brace style
* @author Ian Christian Myers
* @deprecated in ESLint v8.53.0
*/
"use strict";
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "brace-style",
url: "https://eslint.style/rules/brace-style",
},
},
],
},
type: "layout",
docs: {
description: "Enforce consistent brace style for blocks",
recommended: false,
url: "https://eslint.org/docs/latest/rules/brace-style",
},
schema: [
{
enum: ["1tbs", "stroustrup", "allman"],
},
{
type: "object",
properties: {
allowSingleLine: {
type: "boolean",
default: false,
},
},
additionalProperties: false,
},
],
fixable: "whitespace",
messages: {
nextLineOpen:
"Opening curly brace does not appear on the same line as controlling statement.",
sameLineOpen:
"Opening curly brace appears on the same line as controlling statement.",
blockSameLine:
"Statement inside of curly braces should be on next line.",
nextLineClose:
"Closing curly brace does not appear on the same line as the subsequent block.",
singleLineClose:
"Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.",
sameLineClose:
"Closing curly brace appears on the same line as the subsequent block.",
},
},
create(context) {
const style = context.options[0] || "1tbs",
params = context.options[1] || {},
sourceCode = context.sourceCode;
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
* Fixes a place where a newline unexpectedly appears
* @param {Token} firstToken The token before the unexpected newline
* @param {Token} secondToken The token after the unexpected newline
* @returns {Function} A fixer function to remove the newlines between the tokens
*/
function removeNewlineBetween(firstToken, secondToken) {
const textRange = [firstToken.range[1], secondToken.range[0]];
const textBetween = sourceCode.text.slice(
textRange[0],
textRange[1],
);
// Don't do a fix if there is a comment between the tokens
if (textBetween.trim()) {
return null;
}
return fixer => fixer.replaceTextRange(textRange, " ");
}
/**
* Validates a pair of curly brackets based on the user's config
* @param {Token} openingCurly The opening curly bracket
* @param {Token} closingCurly The closing curly bracket
* @returns {void}
*/
function validateCurlyPair(openingCurly, closingCurly) {
const tokenBeforeOpeningCurly =
sourceCode.getTokenBefore(openingCurly);
const tokenAfterOpeningCurly =
sourceCode.getTokenAfter(openingCurly);
const tokenBeforeClosingCurly =
sourceCode.getTokenBefore(closingCurly);
const singleLineException =
params.allowSingleLine &&
astUtils.isTokenOnSameLine(openingCurly, closingCurly);
if (
style !== "allman" &&
!astUtils.isTokenOnSameLine(
tokenBeforeOpeningCurly,
openingCurly,
)
) {
context.report({
node: openingCurly,
messageId: "nextLineOpen",
fix: removeNewlineBetween(
tokenBeforeOpeningCurly,
openingCurly,
),
});
}
if (
style === "allman" &&
astUtils.isTokenOnSameLine(
tokenBeforeOpeningCurly,
openingCurly,
) &&
!singleLineException
) {
context.report({
node: openingCurly,
messageId: "sameLineOpen",
fix: fixer => fixer.insertTextBefore(openingCurly, "\n"),
});
}
if (
astUtils.isTokenOnSameLine(
openingCurly,
tokenAfterOpeningCurly,
) &&
tokenAfterOpeningCurly !== closingCurly &&
!singleLineException
) {
context.report({
node: openingCurly,
messageId: "blockSameLine",
fix: fixer => fixer.insertTextAfter(openingCurly, "\n"),
});
}
if (
tokenBeforeClosingCurly !== openingCurly &&
!singleLineException &&
astUtils.isTokenOnSameLine(
tokenBeforeClosingCurly,
closingCurly,
)
) {
context.report({
node: closingCurly,
messageId: "singleLineClose",
fix: fixer => fixer.insertTextBefore(closingCurly, "\n"),
});
}
}
/**
* Validates the location of a token that appears before a keyword (e.g. a newline before `else`)
* @param {Token} curlyToken The closing curly token. This is assumed to precede a keyword token (such as `else` or `finally`).
* @returns {void}
*/
function validateCurlyBeforeKeyword(curlyToken) {
const keywordToken = sourceCode.getTokenAfter(curlyToken);
if (
style === "1tbs" &&
!astUtils.isTokenOnSameLine(curlyToken, keywordToken)
) {
context.report({
node: curlyToken,
messageId: "nextLineClose",
fix: removeNewlineBetween(curlyToken, keywordToken),
});
}
if (
style !== "1tbs" &&
astUtils.isTokenOnSameLine(curlyToken, keywordToken)
) {
context.report({
node: curlyToken,
messageId: "sameLineClose",
fix: fixer => fixer.insertTextAfter(curlyToken, "\n"),
});
}
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
BlockStatement(node) {
if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
validateCurlyPair(
sourceCode.getFirstToken(node),
sourceCode.getLastToken(node),
);
}
},
StaticBlock(node) {
validateCurlyPair(
sourceCode.getFirstToken(node, { skip: 1 }), // skip the `static` token
sourceCode.getLastToken(node),
);
},
ClassBody(node) {
validateCurlyPair(
sourceCode.getFirstToken(node),
sourceCode.getLastToken(node),
);
},
SwitchStatement(node) {
const closingCurly = sourceCode.getLastToken(node);
const openingCurly = sourceCode.getTokenBefore(
node.cases.length ? node.cases[0] : closingCurly,
);
validateCurlyPair(openingCurly, closingCurly);
},
IfStatement(node) {
if (
node.consequent.type === "BlockStatement" &&
node.alternate
) {
// Handle the keyword after the `if` block (before `else`)
validateCurlyBeforeKeyword(
sourceCode.getLastToken(node.consequent),
);
}
},
TryStatement(node) {
// Handle the keyword after the `try` block (before `catch` or `finally`)
validateCurlyBeforeKeyword(sourceCode.getLastToken(node.block));
if (node.handler && node.finalizer) {
// Handle the keyword after the `catch` block (before `finally`)
validateCurlyBeforeKeyword(
sourceCode.getLastToken(node.handler.body),
);
}
},
};
},
};

View File

@@ -0,0 +1,827 @@
import { ReadonlyUint8Array } from './readonly-uint8array';
/**
* Defines an offset in bytes.
*/
export type Offset = number;
/**
* An object that can encode a value of type {@link TFrom} into a {@link ReadonlyUint8Array}.
*
* This is a common interface for {@link FixedSizeEncoder} and {@link VariableSizeEncoder}.
*
* @interface
* @typeParam TFrom - The type of the value to encode.
*
* @see {@link FixedSizeEncoder}
* @see {@link VariableSizeEncoder}
*/
type BaseEncoder<TFrom> = {
/** Encode the provided value and return the encoded bytes directly. */
readonly encode: (value: TFrom) => ReadonlyUint8Array;
/**
* Writes the encoded value into the provided byte array at the given offset.
* Returns the offset of the next byte after the encoded value.
*/
readonly write: (value: TFrom, bytes: Uint8Array, offset: Offset) => Offset;
};
/**
* An object that can encode a value of type {@link TFrom} into a fixed-size {@link ReadonlyUint8Array}.
*
* See {@link Encoder} to learn more about creating and composing encoders.
*
* @interface
* @typeParam TFrom - The type of the value to encode.
* @typeParam TSize - The fixed size of the encoded value in bytes.
*
* @example
* ```ts
* const encoder: FixedSizeEncoder<number, 4>;
* const bytes = encoder.encode(42);
* const size = encoder.fixedSize; // 4
* ```
*
* @see {@link Encoder}
* @see {@link VariableSizeEncoder}
*/
export type FixedSizeEncoder<TFrom, TSize extends number = number> = BaseEncoder<TFrom> & {
/** The fixed size of the encoded value in bytes. */
readonly fixedSize: TSize;
};
/**
* An object that can encode a value of type {@link TFrom} into a variable-size {@link ReadonlyUint8Array}.
*
* See {@link Encoder} to learn more about creating and composing encoders.
*
* @interface
* @typeParam TFrom - The type of the value to encode.
*
* @example
* ```ts
* const encoder: VariableSizeEncoder<string>;
* const bytes = encoder.encode('hello');
* const size = encoder.getSizeFromValue('hello');
* ```
*
* @see {@link Encoder}
* @see {@link FixedSizeEncoder}
*/
export type VariableSizeEncoder<TFrom> = BaseEncoder<TFrom> & {
/** Returns the size of the encoded value in bytes for a given input. */
readonly getSizeFromValue: (value: TFrom) => number;
/** The maximum possible size of an encoded value in bytes, if applicable. */
readonly maxSize?: number;
};
/**
* An object that can encode a value of type {@link TFrom} into a {@link ReadonlyUint8Array}.
*
* An `Encoder` can be either:
* - A {@link FixedSizeEncoder}, where all encoded values have the same fixed size.
* - A {@link VariableSizeEncoder}, where encoded values can vary in size.
*
* @typeParam TFrom - The type of the value to encode.
*
* @example
* Encoding a value into a new byte array.
* ```ts
* const encoder: Encoder<string>;
* const bytes = encoder.encode('hello');
* ```
*
* @example
* Writing the encoded value into an existing byte array.
* ```ts
* const encoder: Encoder<string>;
* const bytes = new Uint8Array(100);
* const nextOffset = encoder.write('hello', bytes, 20);
* ```
*
* @remarks
* You may create `Encoders` manually using the {@link createEncoder} function but it is more common
* to compose multiple `Encoders` together using the various helpers of the `@solana/codecs` package.
*
* For instance, here's how you might create an `Encoder` for a `Person` object type that contains
* a `name` string and an `age` number:
*
* ```ts
* import { getStructEncoder, addEncoderSizePrefix, getUtf8Encoder, getU32Encoder } from '@solana/codecs';
*
* type Person = { name: string; age: number };
* const getPersonEncoder = (): Encoder<Person> =>
* getStructEncoder([
* ['name', addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())],
* ['age', getU32Encoder()],
* ]);
* ```
*
* Note that composed `Encoder` types are clever enough to understand whether
* they are fixed-size or variable-size. In the example above, `getU32Encoder()` is
* a fixed-size encoder, while `addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())`
* is a variable-size encoder. This makes the final `Person` encoder a variable-size encoder.
*
* @see {@link FixedSizeEncoder}
* @see {@link VariableSizeEncoder}
* @see {@link createEncoder}
*/
export type Encoder<TFrom> = FixedSizeEncoder<TFrom> | VariableSizeEncoder<TFrom>;
/**
* An object that can decode a byte array into a value of type {@link TTo}.
*
* This is a common interface for {@link FixedSizeDecoder} and {@link VariableSizeDecoder}.
*
* @interface
* @typeParam TTo - The type of the decoded value.
*
* @see {@link FixedSizeDecoder}
* @see {@link VariableSizeDecoder}
*/
type BaseDecoder<TTo> = {
/** Decodes the provided byte array at the given offset (or zero) and returns the value directly. */
readonly decode: (bytes: ReadonlyUint8Array | Uint8Array, offset?: Offset) => TTo;
/**
* Reads the encoded value from the provided byte array at the given offset.
* Returns the decoded value and the offset of the next byte after the encoded value.
*/
readonly read: (bytes: ReadonlyUint8Array | Uint8Array, offset: Offset) => [TTo, Offset];
};
/**
* An object that can decode a fixed-size byte array into a value of type {@link TTo}.
*
* See {@link Decoder} to learn more about creating and composing decoders.
*
* @interface
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
*
* @example
* ```ts
* const decoder: FixedSizeDecoder<number, 4>;
* const value = decoder.decode(bytes);
* const size = decoder.fixedSize; // 4
* ```
*
* @see {@link Decoder}
* @see {@link VariableSizeDecoder}
*/
export type FixedSizeDecoder<TTo, TSize extends number = number> = BaseDecoder<TTo> & {
/** The fixed size of the encoded value in bytes. */
readonly fixedSize: TSize;
};
/**
* An object that can decode a variable-size byte array into a value of type {@link TTo}.
*
* See {@link Decoder} to learn more about creating and composing decoders.
*
* @interface
* @typeParam TTo - The type of the decoded value.
*
* @example
* ```ts
* const decoder: VariableSizeDecoder<number>;
* const value = decoder.decode(bytes);
* ```
*
* @see {@link Decoder}
* @see {@link VariableSizeDecoder}
*/
export type VariableSizeDecoder<TTo> = BaseDecoder<TTo> & {
/** The maximum possible size of an encoded value in bytes, if applicable. */
readonly maxSize?: number;
};
/**
* An object that can decode a byte array into a value of type {@link TTo}.
*
* An `Decoder` can be either:
* - A {@link FixedSizeDecoder}, where all byte arrays have the same fixed size.
* - A {@link VariableSizeDecoder}, where byte arrays can vary in size.
*
* @typeParam TTo - The type of the decoded value.
*
* @example
* Getting the decoded value from a byte array.
* ```ts
* const decoder: Decoder<string>;
* const value = decoder.decode(bytes);
* ```
*
* @example
* Reading the decoded value from a byte array at a specific offset
* and getting the offset of the next byte to read.
* ```ts
* const decoder: Decoder<string>;
* const [value, nextOffset] = decoder.read('hello', bytes, 20);
* ```
*
* @remarks
* You may create `Decoders` manually using the {@link createDecoder} function but it is more common
* to compose multiple `Decoders` together using the various helpers of the `@solana/codecs` package.
*
* For instance, here's how you might create an `Decoder` for a `Person` object type that contains
* a `name` string and an `age` number:
*
* ```ts
* import { getStructDecoder, addDecoderSizePrefix, getUtf8Decoder, getU32Decoder } from '@solana/codecs';
*
* type Person = { name: string; age: number };
* const getPersonDecoder = (): Decoder<Person> =>
* getStructDecoder([
* ['name', addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())],
* ['age', getU32Decoder()],
* ]);
* ```
*
* Note that composed `Decoder` types are clever enough to understand whether
* they are fixed-size or variable-size. In the example above, `getU32Decoder()` is
* a fixed-size decoder, while `addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())`
* is a variable-size decoder. This makes the final `Person` decoder a variable-size decoder.
*
* @see {@link FixedSizeDecoder}
* @see {@link VariableSizeDecoder}
* @see {@link createDecoder}
*/
export type Decoder<TTo> = FixedSizeDecoder<TTo> | VariableSizeDecoder<TTo>;
/**
* An object that can encode and decode a value to and from a fixed-size byte array.
*
* See {@link Codec} to learn more about creating and composing codecs.
*
* @interface
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
*
* @example
* ```ts
* const codec: FixedSizeCodec<number | bigint, bigint, 8>;
* const bytes = codec.encode(42);
* const value = codec.decode(bytes); // 42n
* const size = codec.fixedSize; // 8
* ```
*
* @see {@link Codec}
* @see {@link VariableSizeCodec}
*/
export type FixedSizeCodec<TFrom, TTo extends TFrom = TFrom, TSize extends number = number> = FixedSizeDecoder<TTo, TSize> & FixedSizeEncoder<TFrom, TSize>;
/**
* An object that can encode and decode a value to and from a variable-size byte array.
*
* See {@link Codec} to learn more about creating and composing codecs.
*
* @interface
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
*
* @example
* ```ts
* const codec: VariableSizeCodec<number | bigint, bigint>;
* const bytes = codec.encode(42);
* const value = codec.decode(bytes); // 42n
* const size = codec.getSizeFromValue(42);
* ```
*
* @see {@link Codec}
* @see {@link FixedSizeCodec}
*/
export type VariableSizeCodec<TFrom, TTo extends TFrom = TFrom> = VariableSizeDecoder<TTo> & VariableSizeEncoder<TFrom>;
/**
* An object that can encode and decode a value to and from a byte array.
*
* A `Codec` can be either:
* - A {@link FixedSizeCodec}, where all encoded values have the same fixed size.
* - A {@link VariableSizeCodec}, where encoded values can vary in size.
*
* @example
* ```ts
* const codec: Codec<string>;
* const bytes = codec.encode('hello');
* const value = codec.decode(bytes); // 'hello'
* ```
*
* @remarks
* For convenience, codecs can encode looser types than they decode.
* That is, type {@link TFrom} can be a superset of type {@link TTo}.
* For instance, a `Codec<bigint | number, bigint>` can encode both
* `bigint` and `number` values, but will always decode to a `bigint`.
*
* ```ts
* const codec: Codec<bigint | number, bigint>;
* const bytes = codec.encode(42);
* const value = codec.decode(bytes); // 42n
* ```
*
* It is worth noting that codecs are the union of encoders and decoders.
* This means that a `Codec<TFrom, TTo>` can be combined from an `Encoder<TFrom>`
* and a `Decoder<TTo>` using the {@link combineCodec} function. This is particularly
* useful for library authors who want to expose all three types of objects to their users.
*
* ```ts
* const encoder: Encoder<bigint | number>;
* const decoder: Decoder<bigint>;
* const codec: Codec<bigint | number, bigint> = combineCodec(encoder, decoder);
* ```
*
* Aside from combining encoders and decoders, codecs can also be created from scratch using
* the {@link createCodec} function but it is more common to compose multiple codecs together
* using the various helpers of the `@solana/codecs` package.
*
* For instance, here's how you might create a `Codec` for a `Person` object type that contains
* a `name` string and an `age` number:
*
* ```ts
* import { getStructCodec, addCodecSizePrefix, getUtf8Codec, getU32Codec } from '@solana/codecs';
*
* type Person = { name: string; age: number };
* const getPersonCodec = (): Codec<Person> =>
* getStructCodec([
* ['name', addCodecSizePrefix(getUtf8Codec(), getU32Codec())],
* ['age', getU32Codec()],
* ]);
* ```
*
* Note that composed `Codec` types are clever enough to understand whether
* they are fixed-size or variable-size. In the example above, `getU32Codec()` is
* a fixed-size codec, while `addCodecSizePrefix(getUtf8Codec(), getU32Codec())`
* is a variable-size codec. This makes the final `Person` codec a variable-size codec.
*
* @see {@link FixedSizeCodec}
* @see {@link VariableSizeCodec}
* @see {@link combineCodec}
* @see {@link createCodec}
*/
export type Codec<TFrom, TTo extends TFrom = TFrom> = FixedSizeCodec<TFrom, TTo> | VariableSizeCodec<TFrom, TTo>;
/**
* Gets the encoded size of a given value in bytes using the provided encoder.
*
* @typeParam TFrom - The type of the value to encode.
* @param value - The value to be encoded.
* @param encoder - The encoder used to determine the encoded size.
* @returns The size of the encoded value in bytes.
*
* @example
* ```ts
* const fixedSizeEncoder = { fixedSize: 4 };
* getEncodedSize(123, fixedSizeEncoder); // Returns 4.
*
* const variableSizeEncoder = { getSizeFromValue: (value: string) => value.length };
* getEncodedSize("hello", variableSizeEncoder); // Returns 5.
* ```
*
* @see {@link Encoder}
*/
export declare function getEncodedSize<TFrom>(value: TFrom, encoder: {
fixedSize: number;
} | {
getSizeFromValue: (value: TFrom) => number;
}): number;
/**
* Creates an `Encoder` by filling in the missing `encode` function using the provided `write` function and
* either the `fixedSize` property (for {@link FixedSizeEncoder | FixedSizeEncoders}) or
* the `getSizeFromValue` function (for {@link VariableSizeEncoder | VariableSizeEncoders}).
*
* Instead of manually implementing `encode`, this utility leverages the existing `write` function
* and the size helpers to generate a complete encoder. The provided `encode` method will allocate
* a new `Uint8Array` of the correct size and use `write` to populate it.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TSize - The fixed size of the encoded value in bytes (for fixed-size encoders).
*
* @param encoder - An encoder object that implements `write`, but not `encode`.
* - If the encoder has a `fixedSize` property, it is treated as a {@link FixedSizeEncoder}.
* - Otherwise, it is treated as a {@link VariableSizeEncoder}.
*
* @returns A fully functional `Encoder` with both `write` and `encode` methods.
*
* @example
* Creating a custom fixed-size encoder.
* ```ts
* const encoder = createEncoder({
* fixedSize: 4,
* write: (value: number, bytes, offset) => {
* bytes.set(new Uint8Array([value]), offset);
* return offset + 4;
* },
* });
*
* const bytes = encoder.encode(42);
* // 0x2a000000
* ```
*
* @example
* Creating a custom variable-size encoder:
* ```ts
* const encoder = createEncoder({
* getSizeFromValue: (value: string) => value.length,
* write: (value: string, bytes, offset) => {
* const encodedValue = new TextEncoder().encode(value);
* bytes.set(encodedValue, offset);
* return offset + encodedValue.length;
* },
* });
*
* const bytes = encoder.encode("hello");
* // 0x68656c6c6f
* ```
*
* @remarks
* Note that, while `createEncoder` is useful for defining more complex encoders, it is more common to compose
* encoders together using the various helpers and primitives of the `@solana/codecs` package.
*
* Here are some alternative examples using codec primitives instead of `createEncoder`.
*
* ```ts
* // Fixed-size encoder for unsigned 32-bit integers.
* const encoder = getU32Encoder();
* const bytes = encoder.encode(42);
* // 0x2a000000
*
* // Variable-size encoder for 32-bytes prefixed UTF-8 strings.
* const encoder = addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
* const bytes = encoder.encode("hello");
* // 0x0500000068656c6c6f
*
* // Variable-size encoder for custom objects.
* type Person = { name: string; age: number };
* const encoder: Encoder<Person> = getStructEncoder([
* ['name', addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder())],
* ['age', getU32Encoder()],
* ]);
* const bytes = encoder.encode({ name: "Bob", age: 42 });
* // 0x03000000426f622a000000
* ```
*
* @see {@link Encoder}
* @see {@link FixedSizeEncoder}
* @see {@link VariableSizeEncoder}
* @see {@link getStructEncoder}
* @see {@link getU32Encoder}
* @see {@link getUtf8Encoder}
* @see {@link addEncoderSizePrefix}
*/
export declare function createEncoder<TFrom, TSize extends number>(encoder: Omit<FixedSizeEncoder<TFrom, TSize>, 'encode'>): FixedSizeEncoder<TFrom, TSize>;
export declare function createEncoder<TFrom>(encoder: Omit<VariableSizeEncoder<TFrom>, 'encode'>): VariableSizeEncoder<TFrom>;
export declare function createEncoder<TFrom>(encoder: Omit<FixedSizeEncoder<TFrom>, 'encode'> | Omit<VariableSizeEncoder<TFrom>, 'encode'>): Encoder<TFrom>;
/**
* Creates a `Decoder` by filling in the missing `decode` function using the provided `read` function.
*
* Instead of manually implementing `decode`, this utility leverages the existing `read` function
* and the size properties to generate a complete decoder. The provided `decode` method will read
* from a `Uint8Array` at the given offset and return the decoded value.
*
* If the `fixedSize` property is provided, a {@link FixedSizeDecoder} will be created, otherwise
* a {@link VariableSizeDecoder} will be created.
*
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes (for fixed-size decoders).
*
* @param decoder - A decoder object that implements `read`, but not `decode`.
* - If the decoder has a `fixedSize` property, it is treated as a {@link FixedSizeDecoder}.
* - Otherwise, it is treated as a {@link VariableSizeDecoder}.
*
* @returns A fully functional `Decoder` with both `read` and `decode` methods.
*
* @example
* Creating a custom fixed-size decoder.
* ```ts
* const decoder = createDecoder({
* fixedSize: 4,
* read: (bytes, offset) => {
* const value = bytes[offset];
* return [value, offset + 4];
* },
* });
*
* const value = decoder.decode(new Uint8Array([42, 0, 0, 0]));
* // 42
* ```
*
* @example
* Creating a custom variable-size decoder:
* ```ts
* const decoder = createDecoder({
* read: (bytes, offset) => {
* const decodedValue = new TextDecoder().decode(bytes.subarray(offset));
* return [decodedValue, bytes.length];
* },
* });
*
* const value = decoder.decode(new Uint8Array([104, 101, 108, 108, 111]));
* // "hello"
* ```
*
* @remarks
* Note that, while `createDecoder` is useful for defining more complex decoders, it is more common to compose
* decoders together using the various helpers and primitives of the `@solana/codecs` package.
*
* Here are some alternative examples using codec primitives instead of `createDecoder`.
*
* ```ts
* // Fixed-size decoder for unsigned 32-bit integers.
* const decoder = getU32Decoder();
* const value = decoder.decode(new Uint8Array([42, 0, 0, 0]));
* // 42
*
* // Variable-size decoder for 32-bytes prefixed UTF-8 strings.
* const decoder = addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder());
* const value = decoder.decode(new Uint8Array([5, 0, 0, 0, 104, 101, 108, 108, 111]));
* // "hello"
*
* // Variable-size decoder for custom objects.
* type Person = { name: string; age: number };
* const decoder: Decoder<Person> = getStructDecoder([
* ['name', addDecoderSizePrefix(getUtf8Decoder(), getU32Decoder())],
* ['age', getU32Decoder()],
* ]);
* const value = decoder.decode(new Uint8Array([3, 0, 0, 0, 66, 111, 98, 42, 0, 0, 0]));
* // { name: "Bob", age: 42 }
* ```
*
* @see {@link Decoder}
* @see {@link FixedSizeDecoder}
* @see {@link VariableSizeDecoder}
* @see {@link getStructDecoder}
* @see {@link getU32Decoder}
* @see {@link getUtf8Decoder}
* @see {@link addDecoderSizePrefix}
*/
export declare function createDecoder<TTo, TSize extends number>(decoder: Omit<FixedSizeDecoder<TTo, TSize>, 'decode'>): FixedSizeDecoder<TTo, TSize>;
export declare function createDecoder<TTo>(decoder: Omit<VariableSizeDecoder<TTo>, 'decode'>): VariableSizeDecoder<TTo>;
export declare function createDecoder<TTo>(decoder: Omit<FixedSizeDecoder<TTo>, 'decode'> | Omit<VariableSizeDecoder<TTo>, 'decode'>): Decoder<TTo>;
/**
* Creates a `Codec` by filling in the missing `encode` and `decode` functions using the provided `write` and `read` functions.
*
* This utility combines the behavior of {@link createEncoder} and {@link createDecoder} to produce a fully functional `Codec`.
* The `encode` method is derived from the `write` function, while the `decode` method is derived from the `read` function.
*
* If the `fixedSize` property is provided, a {@link FixedSizeCodec} will be created, otherwise
* a {@link VariableSizeCodec} will be created.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes (for fixed-size codecs).
*
* @param codec - A codec object that implements `write` and `read`, but not `encode` or `decode`.
* - If the codec has a `fixedSize` property, it is treated as a {@link FixedSizeCodec}.
* - Otherwise, it is treated as a {@link VariableSizeCodec}.
*
* @returns A fully functional `Codec` with `write`, `read`, `encode`, and `decode` methods.
*
* @example
* Creating a custom fixed-size codec.
* ```ts
* const codec = createCodec({
* fixedSize: 4,
* read: (bytes, offset) => {
* const value = bytes[offset];
* return [value, offset + 4];
* },
* write: (value: number, bytes, offset) => {
* bytes.set(new Uint8Array([value]), offset);
* return offset + 4;
* },
* });
*
* const bytes = codec.encode(42);
* // 0x2a000000
* const value = codec.decode(bytes);
* // 42
* ```
*
* @example
* Creating a custom variable-size codec:
* ```ts
* const codec = createCodec({
* getSizeFromValue: (value: string) => value.length,
* read: (bytes, offset) => {
* const decodedValue = new TextDecoder().decode(bytes.subarray(offset));
* return [decodedValue, bytes.length];
* },
* write: (value: string, bytes, offset) => {
* const encodedValue = new TextEncoder().encode(value);
* bytes.set(encodedValue, offset);
* return offset + encodedValue.length;
* },
* });
*
* const bytes = codec.encode("hello");
* // 0x68656c6c6f
* const value = codec.decode(bytes);
* // "hello"
* ```
*
* @remarks
* This function effectively combines the behavior of {@link createEncoder} and {@link createDecoder}.
* If you only need to encode or decode (but not both), consider using those functions instead.
*
* Here are some alternative examples using codec primitives instead of `createCodec`.
*
* ```ts
* // Fixed-size codec for unsigned 32-bit integers.
* const codec = getU32Codec();
* const bytes = codec.encode(42);
* // 0x2a000000
* const value = codec.decode(bytes);
* // 42
*
* // Variable-size codec for 32-bytes prefixed UTF-8 strings.
* const codec = addCodecSizePrefix(getUtf8Codec(), getU32Codec());
* const bytes = codec.encode("hello");
* // 0x0500000068656c6c6f
* const value = codec.decode(bytes);
* // "hello"
*
* // Variable-size codec for custom objects.
* type Person = { name: string; age: number };
* const codec: Codec<PersonInput, Person> = getStructCodec([
* ['name', addCodecSizePrefix(getUtf8Codec(), getU32Codec())],
* ['age', getU32Codec()],
* ]);
* const bytes = codec.encode({ name: "Bob", age: 42 });
* // 0x03000000426f622a000000
* const value = codec.decode(bytes);
* // { name: "Bob", age: 42 }
* ```
*
* @see {@link Codec}
* @see {@link FixedSizeCodec}
* @see {@link VariableSizeCodec}
* @see {@link createEncoder}
* @see {@link createDecoder}
* @see {@link getStructCodec}
* @see {@link getU32Codec}
* @see {@link getUtf8Codec}
* @see {@link addCodecSizePrefix}
*/
export declare function createCodec<TFrom, TTo extends TFrom = TFrom, TSize extends number = number>(codec: Omit<FixedSizeCodec<TFrom, TTo, TSize>, 'decode' | 'encode'>): FixedSizeCodec<TFrom, TTo, TSize>;
export declare function createCodec<TFrom, TTo extends TFrom = TFrom>(codec: Omit<VariableSizeCodec<TFrom, TTo>, 'decode' | 'encode'>): VariableSizeCodec<TFrom, TTo>;
export declare function createCodec<TFrom, TTo extends TFrom = TFrom>(codec: Omit<FixedSizeCodec<TFrom, TTo>, 'decode' | 'encode'> | Omit<VariableSizeCodec<TFrom, TTo>, 'decode' | 'encode'>): Codec<TFrom, TTo>;
/**
* Determines whether the given codec, encoder, or decoder is fixed-size.
*
* A fixed-size object is identified by the presence of a `fixedSize` property.
* If this property exists, the object is considered a {@link FixedSizeCodec},
* {@link FixedSizeEncoder}, or {@link FixedSizeDecoder}.
* Otherwise, it is assumed to be a {@link VariableSizeCodec},
* {@link VariableSizeEncoder}, or {@link VariableSizeDecoder}.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
* @returns `true` if the object is fixed-size, `false` otherwise.
*
* @example
* Checking a fixed-size encoder.
* ```ts
* const encoder = getU32Encoder();
* isFixedSize(encoder); // true
* ```
*
* @example
* Checking a variable-size encoder.
* ```ts
* const encoder = addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
* isFixedSize(encoder); // false
* ```
*
* @remarks
* This function is commonly used to distinguish between fixed-size and variable-size objects at runtime.
* If you need to enforce this distinction with type assertions, consider using {@link assertIsFixedSize}.
*
* @see {@link assertIsFixedSize}
*/
export declare function isFixedSize<TFrom, TSize extends number>(encoder: FixedSizeEncoder<TFrom, TSize> | VariableSizeEncoder<TFrom>): encoder is FixedSizeEncoder<TFrom, TSize>;
export declare function isFixedSize<TTo, TSize extends number>(decoder: FixedSizeDecoder<TTo, TSize> | VariableSizeDecoder<TTo>): decoder is FixedSizeDecoder<TTo, TSize>;
export declare function isFixedSize<TFrom, TTo extends TFrom, TSize extends number>(codec: FixedSizeCodec<TFrom, TTo, TSize> | VariableSizeCodec<TFrom, TTo>): codec is FixedSizeCodec<TFrom, TTo, TSize>;
export declare function isFixedSize<TSize extends number>(codec: {
fixedSize: TSize;
} | {
maxSize?: number;
}): codec is {
fixedSize: TSize;
};
/**
* Asserts that the given codec, encoder, or decoder is fixed-size.
*
* If the object is not fixed-size (i.e., it lacks a `fixedSize` property),
* this function throws a {@link SolanaError} with the code `SOLANA_ERROR__CODECS__EXPECTED_FIXED_LENGTH`.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
* @throws {SolanaError} If the object is not fixed-size.
*
* @example
* Asserting a fixed-size encoder.
* ```ts
* const encoder = getU32Encoder();
* assertIsFixedSize(encoder); // Passes
* ```
*
* @example
* Attempting to assert a variable-size encoder.
* ```ts
* const encoder = addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
* assertIsFixedSize(encoder); // Throws SolanaError
* ```
*
* @remarks
* This function is the assertion-based counterpart of {@link isFixedSize}.
* If you only need to check whether an object is fixed-size without throwing an error, use {@link isFixedSize} instead.
*
* @see {@link isFixedSize}
*/
export declare function assertIsFixedSize<TFrom, TSize extends number>(encoder: FixedSizeEncoder<TFrom, TSize> | VariableSizeEncoder<TFrom>): asserts encoder is FixedSizeEncoder<TFrom, TSize>;
export declare function assertIsFixedSize<TTo, TSize extends number>(decoder: FixedSizeDecoder<TTo, TSize> | VariableSizeDecoder<TTo>): asserts decoder is FixedSizeDecoder<TTo, TSize>;
export declare function assertIsFixedSize<TFrom, TTo extends TFrom, TSize extends number>(codec: FixedSizeCodec<TFrom, TTo, TSize> | VariableSizeCodec<TFrom, TTo>): asserts codec is FixedSizeCodec<TFrom, TTo, TSize>;
export declare function assertIsFixedSize<TSize extends number>(codec: {
fixedSize: TSize;
} | {
maxSize?: number;
}): asserts codec is {
fixedSize: TSize;
};
/**
* Determines whether the given codec, encoder, or decoder is variable-size.
*
* A variable-size object is identified by the absence of a `fixedSize` property.
* If this property is missing, the object is considered a {@link VariableSizeCodec},
* {@link VariableSizeEncoder}, or {@link VariableSizeDecoder}.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
* @returns `true` if the object is variable-size, `false` otherwise.
*
* @example
* Checking a variable-size encoder.
* ```ts
* const encoder = addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
* isVariableSize(encoder); // true
* ```
*
* @example
* Checking a fixed-size encoder.
* ```ts
* const encoder = getU32Encoder();
* isVariableSize(encoder); // false
* ```
*
* @remarks
* This function is the inverse of {@link isFixedSize}.
*
* @see {@link isFixedSize}
* @see {@link assertIsVariableSize}
*/
export declare function isVariableSize<TFrom>(encoder: Encoder<TFrom>): encoder is VariableSizeEncoder<TFrom>;
export declare function isVariableSize<TTo>(decoder: Decoder<TTo>): decoder is VariableSizeDecoder<TTo>;
export declare function isVariableSize<TFrom, TTo extends TFrom>(codec: Codec<TFrom, TTo>): codec is VariableSizeCodec<TFrom, TTo>;
export declare function isVariableSize(codec: {
fixedSize: number;
} | {
maxSize?: number;
}): codec is {
maxSize?: number;
};
/**
* Asserts that the given codec, encoder, or decoder is variable-size.
*
* If the object is not variable-size (i.e., it has a `fixedSize` property),
* this function throws a {@link SolanaError} with the code `SOLANA_ERROR__CODECS__EXPECTED_VARIABLE_LENGTH`.
*
* @typeParam TFrom - The type of the value to encode.
* @typeParam TTo - The type of the decoded value.
* @typeParam TSize - The fixed size of the encoded value in bytes.
* @throws {SolanaError} If the object is not variable-size.
*
* @example
* Asserting a variable-size encoder.
* ```ts
* const encoder = addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
* assertIsVariableSize(encoder); // Passes
* ```
*
* @example
* Attempting to assert a fixed-size encoder.
* ```ts
* const encoder = getU32Encoder();
* assertIsVariableSize(encoder); // Throws SolanaError
* ```
*
* @remarks
* This function is the assertion-based counterpart of {@link isVariableSize}.
* If you only need to check whether an object is variable-size without throwing an error, use {@link isVariableSize} instead.
*
* Also note that this function is the inverse of {@link assertIsFixedSize}.
*
* @see {@link isVariableSize}
* @see {@link assertIsFixedSize}
*/
export declare function assertIsVariableSize<TFrom>(encoder: Encoder<TFrom>): asserts encoder is VariableSizeEncoder<TFrom>;
export declare function assertIsVariableSize<TTo>(decoder: Decoder<TTo>): asserts decoder is VariableSizeDecoder<TTo>;
export declare function assertIsVariableSize<TFrom, TTo extends TFrom>(codec: Codec<TFrom, TTo>): asserts codec is VariableSizeCodec<TFrom, TTo>;
export declare function assertIsVariableSize(codec: {
fixedSize: number;
} | {
maxSize?: number;
}): asserts codec is {
maxSize?: number;
};
export {};
//# sourceMappingURL=codec.d.ts.map

View File

@@ -0,0 +1,17 @@
"use strict";
/**
* Audited & minimal JS implementation of elliptic curve cryptography.
* @module
* @example
```js
import { secp256k1, schnorr } from '@noble/curves/secp256k1.js';
import { ed25519, ed25519ph, ed25519ctx, x25519, RistrettoPoint } from '@noble/curves/ed25519.js';
import { ed448, ed448ph, ed448ctx, x448 } from '@noble/curves/ed448.js';
import { p256, p384, p521 } from '@noble/curves/nist.js';
import { bls12_381 } from '@noble/curves/bls12-381.js';
import { bn254 } from '@noble/curves/bn254.js';
import { bytesToHex, hexToBytes, concatBytes, utf8ToBytes } from '@noble/curves/abstract/utils.js';
```
*/
throw new Error('root module cannot be imported: import submodules instead. Check out README');
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,152 @@
import { WalkerBase } from './walker.js';
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => void} SyncHandler
*/
export class SyncWalker extends WalkerBase {
/**
*
* @param {SyncHandler} [enter]
* @param {SyncHandler} [leave]
*/
constructor(enter, leave) {
super();
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => (this.should_skip = true),
remove: () => (this.should_remove = true),
replace: (node) => (this.replacement = node)
};
/** @type {SyncHandler | undefined} */
this.enter = enter;
/** @type {SyncHandler | undefined} */
this.leave = leave;
}
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Node | null}
*/
visit(node, parent, prop, index) {
if (node) {
if (this.enter) {
const _should_skip = this.should_skip;
const _should_remove = this.should_remove;
const _replacement = this.replacement;
this.should_skip = false;
this.should_remove = false;
this.replacement = null;
this.enter.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const skipped = this.should_skip;
const removed = this.should_remove;
this.should_skip = _should_skip;
this.should_remove = _should_remove;
this.replacement = _replacement;
if (skipped) return node;
if (removed) return null;
}
/** @type {keyof Node} */
let key;
for (key in node) {
/** @type {unknown} */
const value = node[key];
if (value && typeof value === 'object') {
if (Array.isArray(value)) {
const nodes = /** @type {Array<unknown>} */ (value);
for (let i = 0; i < nodes.length; i += 1) {
const item = nodes[i];
if (isNode(item)) {
if (!this.visit(item, node, key, i)) {
// removed
i--;
}
}
}
} else if (isNode(value)) {
this.visit(value, node, key, null);
}
}
}
if (this.leave) {
const _replacement = this.replacement;
const _should_remove = this.should_remove;
this.replacement = null;
this.should_remove = false;
this.leave.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const removed = this.should_remove;
this.replacement = _replacement;
this.should_remove = _should_remove;
if (removed) return null;
}
}
return node;
}
}
/**
* Ducktype a node.
*
* @param {unknown} value
* @returns {value is Node}
*/
function isNode(value) {
return (
value !== null && typeof value === 'object' && 'type' in value && typeof value.type === 'string'
);
}

View File

@@ -0,0 +1,67 @@
/**
* @fileoverview Disallow the use of process.exit()
* @author Nicholas C. Zakas
* @deprecated in ESLint v7.0.0
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Node.js rules were moved out of ESLint core.",
url: "https://eslint.org/docs/latest/use/migrating-to-7.0.0#deprecate-node-rules",
deprecatedSince: "7.0.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"eslint-plugin-n now maintains deprecated Node.js-related rules.",
plugin: {
name: "eslint-plugin-n",
url: "https://github.com/eslint-community/eslint-plugin-n",
},
rule: {
name: "no-process-exit",
url: "https://github.com/eslint-community/eslint-plugin-n/tree/master/docs/rules/no-process-exit.md",
},
},
],
},
type: "suggestion",
docs: {
description: "Disallow the use of `process.exit()`",
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-process-exit",
},
schema: [],
messages: {
noProcessExit: "Don't use process.exit(); throw an error instead.",
},
},
create(context) {
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
"CallExpression > MemberExpression.callee[object.name = 'process'][property.name = 'exit']"(
node,
) {
context.report({
node: node.parent,
messageId: "noProcessExit",
});
},
};
},
};

View File

@@ -0,0 +1,28 @@
export function decodeLength(bytes: Array<number>): number {
let len = 0;
let size = 0;
for (;;) {
let elem = bytes.shift() as number;
len |= (elem & 0x7f) << (size * 7);
size += 1;
if ((elem & 0x80) === 0) {
break;
}
}
return len;
}
export function encodeLength(bytes: Array<number>, len: number) {
let rem_len = len;
for (;;) {
let elem = rem_len & 0x7f;
rem_len >>= 7;
if (rem_len == 0) {
bytes.push(elem);
break;
} else {
elem |= 0x80;
bytes.push(elem);
}
}
}

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getConstrainedTypeAtLocation = getConstrainedTypeAtLocation;
/**
* Resolves the given node's type. Will return the type's generic constraint, if it has one.
*
* Warning - if the type is generic and does _not_ have a constraint, the type will be
* returned as-is, rather than returning an `unknown` type. This can be checked
* for by checking for the type flag ts.TypeFlags.TypeParameter.
*
* @see https://github.com/typescript-eslint/typescript-eslint/issues/10438
*/
function getConstrainedTypeAtLocation(services, node) {
const nodeType = services.getTypeAtLocation(node);
const constrained = services.program
.getTypeChecker()
.getBaseConstraintOfType(nodeType);
return constrained ?? nodeType;
}

View File

@@ -0,0 +1,200 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABILITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference lib="es2018.intl" />
declare namespace Intl {
/**
* The locale matching algorithm to use.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_negotiation).
*/
type DurationFormatLocaleMatcher = "lookup" | "best fit";
/**
* The style of the formatted duration.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/DurationFormat#style).
*/
type DurationFormatStyle = "long" | "short" | "narrow" | "digital";
/**
* Whether to always display a unit, or only if it is non-zero.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/DurationFormat#display).
*/
type DurationFormatDisplayOption = "always" | "auto";
/**
* Value of the `unit` property in duration objects
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/format#duration).
*/
type DurationFormatUnit =
| "years"
| "months"
| "weeks"
| "days"
| "hours"
| "minutes"
| "seconds"
| "milliseconds"
| "microseconds"
| "nanoseconds";
type DurationFormatUnitSingular =
| "year"
| "month"
| "week"
| "day"
| "hour"
| "minute"
| "second"
| "millisecond"
| "microsecond"
| "nanosecond";
/**
* An object representing the relative time format in parts
* that can be used for custom locale-aware formatting.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/formatToParts).
*/
type DurationFormatPart =
| {
type: "literal";
value: string;
unit?: DurationFormatUnitSingular;
}
| {
type: Exclude<NumberFormatPartTypes, "literal">;
value: string;
unit: DurationFormatUnitSingular;
};
/**
* An object with some or all properties of the `Intl.DurationFormat` constructor `options` parameter.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/DurationFormat#parameters)
*/
interface DurationFormatOptions {
localeMatcher?: DurationFormatLocaleMatcher | undefined;
numberingSystem?: string | undefined;
style?: DurationFormatStyle | undefined;
years?: "long" | "short" | "narrow" | undefined;
yearsDisplay?: DurationFormatDisplayOption | undefined;
months?: "long" | "short" | "narrow" | undefined;
monthsDisplay?: DurationFormatDisplayOption | undefined;
weeks?: "long" | "short" | "narrow" | undefined;
weeksDisplay?: DurationFormatDisplayOption | undefined;
days?: "long" | "short" | "narrow" | undefined;
daysDisplay?: DurationFormatDisplayOption | undefined;
hours?: "long" | "short" | "narrow" | "numeric" | "2-digit" | undefined;
hoursDisplay?: DurationFormatDisplayOption | undefined;
minutes?: "long" | "short" | "narrow" | "numeric" | "2-digit" | undefined;
minutesDisplay?: DurationFormatDisplayOption | undefined;
seconds?: "long" | "short" | "narrow" | "numeric" | "2-digit" | undefined;
secondsDisplay?: DurationFormatDisplayOption | undefined;
milliseconds?: "long" | "short" | "narrow" | "numeric" | undefined;
millisecondsDisplay?: DurationFormatDisplayOption | undefined;
microseconds?: "long" | "short" | "narrow" | "numeric" | undefined;
microsecondsDisplay?: DurationFormatDisplayOption | undefined;
nanoseconds?: "long" | "short" | "narrow" | "numeric" | undefined;
nanosecondsDisplay?: DurationFormatDisplayOption | undefined;
fractionalDigits?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined;
}
/**
* The Intl.DurationFormat object enables language-sensitive duration formatting.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat)
*/
interface DurationFormat {
/**
* @param duration The duration object to be formatted. It should include some or all of the following properties: months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/format).
*/
format(duration: Partial<Record<DurationFormatUnit, number>>): string;
/**
* @param duration The duration object to be formatted. It should include some or all of the following properties: months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/formatToParts).
*/
formatToParts(duration: Partial<Record<DurationFormatUnit, number>>): DurationFormatPart[];
/**
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/resolvedOptions).
*/
resolvedOptions(): ResolvedDurationFormatOptions;
}
interface ResolvedDurationFormatOptions {
locale: UnicodeBCP47LocaleIdentifier;
numberingSystem: string;
style: DurationFormatStyle;
years: "long" | "short" | "narrow";
yearsDisplay: DurationFormatDisplayOption;
months: "long" | "short" | "narrow";
monthsDisplay: DurationFormatDisplayOption;
weeks: "long" | "short" | "narrow";
weeksDisplay: DurationFormatDisplayOption;
days: "long" | "short" | "narrow";
daysDisplay: DurationFormatDisplayOption;
hours: "long" | "short" | "narrow" | "numeric" | "2-digit";
hoursDisplay: DurationFormatDisplayOption;
minutes: "long" | "short" | "narrow" | "numeric" | "2-digit";
minutesDisplay: DurationFormatDisplayOption;
seconds: "long" | "short" | "narrow" | "numeric" | "2-digit";
secondsDisplay: DurationFormatDisplayOption;
milliseconds: "long" | "short" | "narrow" | "numeric";
millisecondsDisplay: DurationFormatDisplayOption;
microseconds: "long" | "short" | "narrow" | "numeric";
microsecondsDisplay: DurationFormatDisplayOption;
nanoseconds: "long" | "short" | "narrow" | "numeric";
nanosecondsDisplay: DurationFormatDisplayOption;
fractionalDigits?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
}
const DurationFormat: {
prototype: DurationFormat;
/**
* @param locales A string with a BCP 47 language tag, or an array of such strings.
* For the general form and interpretation of the `locales` argument, see the [Intl](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#locale_identification_and_negotiation)
* page.
*
* @param options An object for setting up a duration format.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/DurationFormat).
*/
new (locales?: LocalesArgument, options?: DurationFormatOptions): DurationFormat;
/**
* Returns an array containing those of the provided locales that are supported in display names without having to fall back to the runtime's default locale.
*
* @param locales A string with a BCP 47 language tag, or an array of such strings.
* For the general form and interpretation of the `locales` argument, see the [Intl](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#locale_identification_and_negotiation)
* page.
*
* @param options An object with a locale matcher.
*
* @returns An array of strings representing a subset of the given locale tags that are supported in display names without having to fall back to the runtime's default locale.
*
* [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat/supportedLocalesOf).
*/
supportedLocalesOf(locales?: LocalesArgument, options?: { localeMatcher?: DurationFormatLocaleMatcher; }): UnicodeBCP47LocaleIdentifier[];
};
}

View File

@@ -0,0 +1,121 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-extraneous-class',
meta: {
type: 'suggestion',
docs: {
description: 'Disallow classes used as namespaces',
recommended: 'strict',
},
messages: {
empty: 'Unexpected empty class.',
onlyConstructor: 'Unexpected class with only a constructor.',
onlyStatic: 'Unexpected class with only static properties.',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowConstructorOnly: {
type: 'boolean',
description: 'Whether to allow extraneous classes that contain only a constructor.',
},
allowEmpty: {
type: 'boolean',
description: 'Whether to allow extraneous classes that have no body (i.e. are empty).',
},
allowStaticOnly: {
type: 'boolean',
description: 'Whether to allow extraneous classes that only contain static members.',
},
allowWithDecorator: {
type: 'boolean',
description: 'Whether to allow extraneous classes that include a decorator.',
},
},
},
],
},
defaultOptions: [
{
allowConstructorOnly: false,
allowEmpty: false,
allowStaticOnly: false,
allowWithDecorator: false,
},
],
create(context, [{ allowConstructorOnly, allowEmpty, allowStaticOnly, allowWithDecorator }]) {
const isAllowWithDecorator = (node) => {
return !!(allowWithDecorator &&
node?.decorators &&
node.decorators.length !== 0);
};
return {
ClassBody(node) {
const parent = node.parent;
if (parent.superClass || isAllowWithDecorator(parent)) {
return;
}
const reportNode = parent.type === utils_1.AST_NODE_TYPES.ClassDeclaration && parent.id
? parent.id
: parent;
if (node.body.length === 0) {
if (allowEmpty) {
return;
}
context.report({
node: reportNode,
messageId: 'empty',
});
return;
}
let onlyStatic = true;
let onlyConstructor = true;
for (const prop of node.body) {
if (prop.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
prop.kind === 'constructor') {
if (prop.value.params.some(param => param.type === utils_1.AST_NODE_TYPES.TSParameterProperty)) {
onlyConstructor = false;
onlyStatic = false;
}
}
else {
onlyConstructor = false;
if (((prop.type === utils_1.AST_NODE_TYPES.PropertyDefinition ||
prop.type === utils_1.AST_NODE_TYPES.MethodDefinition ||
prop.type === utils_1.AST_NODE_TYPES.AccessorProperty) &&
!prop.static) ||
prop.type === utils_1.AST_NODE_TYPES.TSIndexSignature ||
prop.type === utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition ||
prop.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition || // `static abstract` methods and properties are currently not supported. See: https://github.com/microsoft/TypeScript/issues/34516
prop.type === utils_1.AST_NODE_TYPES.TSAbstractAccessorProperty) {
onlyStatic = false;
}
}
if (!(onlyStatic || onlyConstructor)) {
break;
}
}
if (onlyConstructor) {
if (!allowConstructorOnly) {
context.report({
node: reportNode,
messageId: 'onlyConstructor',
});
}
return;
}
if (onlyStatic && !allowStaticOnly) {
context.report({
node: reportNode,
messageId: 'onlyStatic',
});
}
},
};
},
});

View File

@@ -0,0 +1,171 @@
/**
* @fileoverview A rule to control the style of variable initializations.
* @author Colin Ihrig
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const CONSTANT_BINDINGS = new Set(["const", "using", "await using"]);
/**
* Checks whether or not a given node is a for loop.
* @param {ASTNode} block A node to check.
* @returns {boolean} `true` when the node is a for loop.
*/
function isForLoop(block) {
return (
block.type === "ForInStatement" ||
block.type === "ForOfStatement" ||
block.type === "ForStatement"
);
}
/**
* Checks whether or not a given declarator node has its initializer.
* @param {ASTNode} node A declarator node to check.
* @returns {boolean} `true` when the node has its initializer.
*/
function isInitialized(node) {
const declaration = node.parent;
const block = declaration.parent;
if (isForLoop(block)) {
if (block.type === "ForStatement") {
return block.init === declaration;
}
return block.left === declaration;
}
return Boolean(node.init);
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Require or disallow initialization in variable declarations",
dialects: ["JavaScript", "TypeScript"],
recommended: false,
frozen: true,
url: "https://eslint.org/docs/latest/rules/init-declarations",
},
schema: {
anyOf: [
{
type: "array",
items: [
{
enum: ["always"],
},
],
minItems: 0,
maxItems: 1,
},
{
type: "array",
items: [
{
enum: ["never"],
},
{
type: "object",
properties: {
ignoreForLoopInit: {
type: "boolean",
},
},
additionalProperties: false,
},
],
minItems: 0,
maxItems: 2,
},
],
},
defaultOptions: ["always"],
messages: {
initialized:
"Variable '{{idName}}' should be initialized on declaration.",
notInitialized:
"Variable '{{idName}}' should not be initialized on declaration.",
},
},
create(context) {
const mode = context.options[0];
const params = context.options[1] || {};
// Track whether we're inside a declared namespace
let insideDeclaredNamespace = false;
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
TSModuleDeclaration(node) {
if (node.declare) {
insideDeclaredNamespace = true;
}
},
"TSModuleDeclaration:exit"(node) {
if (node.declare) {
insideDeclaredNamespace = false;
}
},
"VariableDeclaration:exit"(node) {
const kind = node.kind,
declarations = node.declarations;
if (node.declare || insideDeclaredNamespace) {
return;
}
for (let i = 0; i < declarations.length; ++i) {
const declaration = declarations[i],
id = declaration.id,
initialized = isInitialized(declaration),
isIgnoredForLoop =
params.ignoreForLoopInit && isForLoop(node.parent);
let messageId = "";
if (mode === "always" && !initialized) {
messageId = "initialized";
} else if (
mode === "never" &&
!CONSTANT_BINDINGS.has(kind) &&
initialized &&
!isIgnoredForLoop
) {
messageId = "notInitialized";
}
if (id.type === "Identifier" && messageId) {
context.report({
node: declaration,
messageId,
data: {
idName: id.name,
},
});
}
}
},
};
},
};

View File

@@ -0,0 +1,52 @@
var assert = require('assert');
var arrTest = [];
var arrExpected;
for (var i = 0; i < 10; i++) { arrTest[i] = i; }
arrExpected = JSON.stringify(arrTest);
var arrReuse = [];
suite('itar-short', function() {
var minSamples = 160;
benchmark("for + if", function() {
var val = arrTest.slice();
var str = '[';
var max = val.length - 1;
var i;
for (i = 0; i < max; i++) {
str += JSON.stringify(val[i]) + ',';
}
if (max > -1) {
str += JSON.stringify(val[i]);
}
assert.equal(str + ']', arrExpected);
}, { minSamples: minSamples });
benchmark("while + if", function() {
var val = arrTest.slice();
var str = '[';
var max = val.length - 1;
var i = 0;
while (i < max) {
str += JSON.stringify(val[i++]) + ',';
}
if (max > -1) {
str += JSON.stringify(val[i]);
}
assert.equal(str + ']', arrExpected);
}, { minSamples: minSamples });
benchmark("array join", function() {
arrReuse.length = 0;
var val = arrTest.slice();
var max = val.length;
var i;
for (i = 0; i < max; i++) {
arrReuse[i] = JSON.stringify(val[i]);
}
assert.equal('[' + arrReuse.join(',') + ']', arrExpected);
}, { minSamples: minSamples });
});

View File

@@ -0,0 +1,16 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const eslint_recommended_raw_1 = __importDefault(require("../eslint-recommended-raw"));
/**
* This is a compatibility ruleset that:
* - disables rules from eslint:recommended which are already handled by TypeScript.
* - enables rules that make sense due to TS's typechecking / transpilation.
* @see {@link https://typescript-eslint.io/users/configs/#eslint-recommended}
*/
exports.default = (_plugin, _parser) => ({
...(0, eslint_recommended_raw_1.default)('minimatch'),
name: 'typescript-eslint/eslint-recommended',
});

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"file":"nist.js","sourceRoot":"","sources":["src/nist.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,sEAAsE;AACtE,mDAA+D;AAC/D,yDAAyE;AACzE,kEAA2E;AAC3E,sDAA8C;AAC9C,8DAImC;AAEnC,wDAAwD;AACxD,kCAAkC;AAClC,MAAM,UAAU,GAA4B;IAC1C,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,CAAC,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAC/E,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;IAChF,EAAE,EAAE,MAAM,CAAC,oEAAoE,CAAC;CACjF,CAAC;AAEF,mDAAmD;AACnD,MAAM,UAAU,GAA4B;IAC1C,CAAC,EAAE,MAAM,CACP,oGAAoG,CACrG;IACD,CAAC,EAAE,MAAM,CACP,oGAAoG,CACrG;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CACP,oGAAoG,CACrG;IACD,CAAC,EAAE,MAAM,CACP,oGAAoG,CACrG;IACD,EAAE,EAAE,MAAM,CACR,oGAAoG,CACrG;IACD,EAAE,EAAE,MAAM,CACR,oGAAoG,CACrG;CACF,CAAC;AAEF,oBAAoB;AACpB,MAAM,UAAU,GAA4B;IAC1C,CAAC,EAAE,MAAM,CACP,uIAAuI,CACxI;IACD,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACZ,CAAC,EAAE,MAAM,CACP,uIAAuI,CACxI;IACD,CAAC,EAAE,MAAM,CACP,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;IACD,EAAE,EAAE,MAAM,CACR,wIAAwI,CACzI;CACF,CAAC;AAEF,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAClC,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAClC,MAAM,KAAK,GAAG,IAAA,kBAAK,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAMlC,SAAS,SAAS,CAAC,KAAmC,EAAE,IAAa;IACnE,MAAM,GAAG,GAAG,IAAA,oCAAmB,EAAC,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,OAAiB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,2EAA2E;AAC9D,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAChD,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EACzC,gBAAM,CACP,CAAC;AACF,mEAAmE;AACtD,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE;IAClE,OAAO,IAAA,+BAAY,EACjB,YAAI,CAAC,KAAK,EACV,SAAS,CAAC,YAAI,CAAC,KAAK,EAAE;QACpB,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,YAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KACvC,CAAC,EACF;QACE,GAAG,EAAE,2BAA2B;QAChC,SAAS,EAAE,2BAA2B;QACtC,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,GAAG;QACN,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gBAAM;KACb,CACF,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC;AAEL,8CAA8C;AAC9C,yBAAyB;AACzB,uBAAuB;AACvB,kBAAkB;AAClB,0CAA0C;AAC1C,4CAA4C;AAC5C,MAAM;AAEN,+DAA+D;AAClD,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAChD,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EACzC,gBAAM,CACP,CAAC;AACF,mEAAmE;AACtD,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE;IAClE,OAAO,IAAA,+BAAY,EACjB,YAAI,CAAC,KAAK,EACV,SAAS,CAAC,YAAI,CAAC,KAAK,EAAE;QACpB,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,YAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KACvC,CAAC,EACF;QACE,GAAG,EAAE,2BAA2B;QAChC,SAAS,EAAE,2BAA2B;QACtC,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,GAAG;QACN,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gBAAM;KACb,CACF,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC;AAEL,8CAA8C;AAC9C,yBAAyB;AACzB,uBAAuB;AACvB,kBAAkB;AAClB,0CAA0C;AAC1C,4CAA4C;AAC5C,MAAM;AAEN,yEAAyE;AACzE,+DAA+D;AAClD,QAAA,IAAI,GAAsB,IAAA,8BAAW,EAChD,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EACpF,gBAAM,CACP,CAAC;AAEF,gEAAgE;AACnD,QAAA,SAAS,GAAgB,YAAI,CAAC;AAC3C,gEAAgE;AACnD,QAAA,SAAS,GAAgB,YAAI,CAAC;AAC3C,gEAAgE;AACnD,QAAA,SAAS,GAAgB,YAAI,CAAC;AAE3C,mEAAmE;AACtD,QAAA,WAAW,GAAsC,CAAC,GAAG,EAAE;IAClE,OAAO,IAAA,+BAAY,EACjB,YAAI,CAAC,KAAK,EACV,SAAS,CAAC,YAAI,CAAC,KAAK,EAAE;QACpB,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,YAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;KACtC,CAAC,EACF;QACE,GAAG,EAAE,2BAA2B;QAChC,SAAS,EAAE,2BAA2B;QACtC,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,GAAG;QACN,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,gBAAM;KACb,CACF,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC;AAEL,8CAA8C;AAC9C,yBAAyB;AACzB,uBAAuB;AACvB,kBAAkB;AAClB,0CAA0C;AAC1C,8EAA8E;AAC9E,MAAM"}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) egoist <0x142857@gmail.com> (https://github.com/egoist)
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 @@
export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;

View File

@@ -0,0 +1,125 @@
# locate-path [![Build Status](https://travis-ci.com/sindresorhus/locate-path.svg?branch=master)](https://travis-ci.com/github/sindresorhus/locate-path)
> Get the first path that exists on disk of multiple paths
## Install
```
$ npm install locate-path
```
## Usage
Here we find the first file that exists on disk, in array order.
```js
const locatePath = require('locate-path');
const files = [
'unicorn.png',
'rainbow.png', // Only this one actually exists on disk
'pony.png'
];
(async () => {
console(await locatePath(files));
//=> 'rainbow'
})();
```
## API
### locatePath(paths, options?)
Returns a `Promise<string>` for the first path that exists or `undefined` if none exists.
#### paths
Type: `Iterable<string>`
Paths to check.
#### options
Type: `object`
##### concurrency
Type: `number`\
Default: `Infinity`\
Minimum: `1`
Number of concurrently pending promises.
##### preserveOrder
Type: `boolean`\
Default: `true`
Preserve `paths` order when searching.
Disable this to improve performance if you don't care about the order.
##### cwd
Type: `string`\
Default: `process.cwd()`
Current working directory.
##### type
Type: `string`\
Default: `'file'`\
Values: `'file' | 'directory'`
The type of paths that can match.
##### allowSymlinks
Type: `boolean`\
Default: `true`
Allow symbolic links to match if they point to the chosen path type.
### locatePath.sync(paths, options?)
Returns the first path that exists or `undefined` if none exists.
#### paths
Type: `Iterable<string>`
Paths to check.
#### options
Type: `object`
##### cwd
Same as above.
##### type
Same as above.
##### allowSymlinks
Same as above.
## Related
- [path-exists](https://github.com/sindresorhus/path-exists) - Check if a path exists
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-locate-path?utm_source=npm-locate-path&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

View File

@@ -0,0 +1,95 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearGlobCache = clearGlobCache;
exports.resolveProjectList = resolveProjectList;
exports.clearGlobResolutionCache = clearGlobResolutionCache;
const debug_1 = __importDefault(require("debug"));
const tinyglobby_1 = require("tinyglobby");
const shared_1 = require("../create-program/shared");
const ExpiringCache_1 = require("./ExpiringCache");
const log = (0, debug_1.default)('typescript-eslint:typescript-estree:parseSettings:resolveProjectList');
let RESOLUTION_CACHE = null;
function clearGlobCache() {
RESOLUTION_CACHE?.clear();
}
/**
* Normalizes, sanitizes, resolves and filters the provided project paths
*/
function resolveProjectList(options) {
const sanitizedProjects = [];
// Normalize and sanitize the project paths
if (options.project != null) {
for (const project of options.project) {
if (typeof project === 'string') {
sanitizedProjects.push(project);
}
}
}
if (sanitizedProjects.length === 0) {
return new Map();
}
const projectFolderIgnoreList = (options.projectFolderIgnoreList ?? ['**/node_modules/**']).filter(folder => typeof folder === 'string');
const cacheKey = getHash({
project: sanitizedProjects,
projectFolderIgnoreList,
tsconfigRootDir: options.tsconfigRootDir,
});
if (RESOLUTION_CACHE == null) {
// note - we initialize the global cache based on the first config we encounter.
// this does mean that you can't have multiple lifetimes set per folder
// I doubt that anyone will really bother reconfiguring this, let alone
// try to do complicated setups, so we'll deal with this later if ever.
RESOLUTION_CACHE = new ExpiringCache_1.ExpiringCache(options.singleRun
? 'Infinity'
: (options.cacheLifetime?.glob ??
ExpiringCache_1.DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS));
}
else {
const cached = RESOLUTION_CACHE.get(cacheKey);
if (cached) {
return cached;
}
}
// Transform glob patterns into paths
const nonGlobProjects = sanitizedProjects.filter(project => !(0, tinyglobby_1.isDynamicPattern)(project));
const globProjects = sanitizedProjects.filter(project => (0, tinyglobby_1.isDynamicPattern)(project));
let globProjectPaths = [];
if (globProjects.length > 0) {
// To ensure the order is correct, we need to glob for each pattern
// separately and then concatenate the results in patterns' order.
globProjectPaths = globProjects.flatMap(pattern => (0, tinyglobby_1.globSync)(pattern, {
cwd: options.tsconfigRootDir,
expandDirectories: false,
ignore: projectFolderIgnoreList,
}));
}
const uniqueCanonicalProjectPaths = new Map([...nonGlobProjects, ...globProjectPaths].map(project => [
(0, shared_1.getCanonicalFileName)((0, shared_1.ensureAbsolutePath)(project, options.tsconfigRootDir)),
(0, shared_1.ensureAbsolutePath)(project, options.tsconfigRootDir),
]));
log('parserOptions.project (excluding ignored) matched projects: %s', uniqueCanonicalProjectPaths);
RESOLUTION_CACHE.set(cacheKey, uniqueCanonicalProjectPaths);
return uniqueCanonicalProjectPaths;
}
function getHash({ project, projectFolderIgnoreList, tsconfigRootDir, }) {
// create a stable representation of the config
const hashObject = {
tsconfigRootDir,
// the project order does matter and can impact the resolved globs
project,
// the ignore order won't doesn't ever matter
projectFolderIgnoreList: [...projectFolderIgnoreList].sort(),
};
return (0, shared_1.createHash)(JSON.stringify(hashObject));
}
/**
* Exported for testing purposes only
* @internal
*/
function clearGlobResolutionCache() {
RESOLUTION_CACHE?.clear();
RESOLUTION_CACHE = null;
}

View File

@@ -0,0 +1,2 @@
export default function v6ToV1(uuid: string): string;
export default function v6ToV1(uuid: Uint8Array): Uint8Array;

View File

@@ -0,0 +1,121 @@
import type { $ZodStringFormats } from "../core/checks.js";
import type * as errors from "../core/errors.js";
import * as util from "../core/util.js";
const error: () => errors.$ZodErrorMap = () => {
const Sizable: Record<string, { unit: string; verb: string }> = {
string: { unit: "문자", verb: "to have" },
file: { unit: "바이트", verb: "to have" },
array: { unit: "개", verb: "to have" },
set: { unit: "개", verb: "to have" },
};
function getSizing(origin: string): { unit: string; verb: string } | null {
return Sizable[origin] ?? null;
}
const FormatDictionary: {
[k in $ZodStringFormats | (string & {})]?: string;
} = {
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: {
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
} = {
nan: "NaN",
};
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 suffix = adj === "미만" ? "이어야 합니다" : "여야 합니다";
const sizing = getSizing(issue.origin);
const unit = sizing?.unit ?? "요소";
if (sizing) return `${issue.origin ?? "값"}이 너무 큽니다: ${issue.maximum.toString()}${unit} ${adj}${suffix}`;
return `${issue.origin ?? "값"}이 너무 큽니다: ${issue.maximum.toString()} ${adj}${suffix}`;
}
case "too_small": {
const adj = issue.inclusive ? "이상" : "초과";
const suffix = adj === "이상" ? "이어야 합니다" : "여야 합니다";
const sizing = getSizing(issue.origin);
const unit = sizing?.unit ?? "요소";
if (sizing) {
return `${issue.origin ?? "값"}이 너무 작습니다: ${issue.minimum.toString()}${unit} ${adj}${suffix}`;
}
return `${issue.origin ?? "값"}이 너무 작습니다: ${issue.minimum.toString()} ${adj}${suffix}`;
}
case "invalid_format": {
const _issue = issue as errors.$ZodStringFormatIssues;
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 `인식할 수 없는 키: ${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 (): { localeError: errors.$ZodErrorMap } {
return {
localeError: error(),
};
}

View File

@@ -0,0 +1,46 @@
import { InspectOptions } from "node:util";
//#region src/types.d.ts
interface InspectOptions$1 extends InspectOptions {
hideDate?: boolean;
}
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
interface Formatters {
[formatter: string]: (this: Debugger, v: any) => string;
}
interface Debugger extends Required<DebugOptions> {
(formatter: any, ...args: any[]): void;
namespace: string;
enabled: boolean;
extend: (namespace: string, delimiter?: string) => Debugger;
}
interface DebugOptions {
useColors?: boolean;
color?: string | number;
formatArgs?: (this: Debugger, diff: number, args: [string, ...any[]]) => void;
formatters?: Formatters;
/** Node.js only */
inspectOpts?: InspectOptions$1;
/** Humanize a duration in milliseconds */
humanize?: (value: number) => string;
log?: (this: Debugger, ...args: any[]) => void;
}
//#endregion
//#region src/core.d.ts
/**
* Returns a string of the currently enabled debug namespaces.
*/
declare function namespaces(): string;
/**
* Disable debug output.
*/
declare function disable(): string;
/**
* Returns true if the given mode name is enabled, false otherwise.
*/
declare function enabled(name: string): boolean;
//#endregion
export { Debugger as a, DebugOptions as i, enabled as n, Formatters as o, namespaces as r, InspectOptions$1 as s, disable as t };

View File

@@ -0,0 +1,128 @@
/**
* @fileoverview A rule to ensure consistent quotes used in jsx syntax.
* @author Mathias Schreck <https://github.com/lo1tuma>
* @deprecated in ESLint v8.53.0
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
const QUOTE_SETTINGS = {
"prefer-double": {
quote: '"',
description: "singlequote",
convert(str) {
return str.replace(/'/gu, '"');
},
},
"prefer-single": {
quote: "'",
description: "doublequote",
convert(str) {
return str.replace(/"/gu, "'");
},
},
};
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "jsx-quotes",
url: "https://eslint.style/rules/jsx-quotes",
},
},
],
},
type: "layout",
docs: {
description:
"Enforce the consistent use of either double or single quotes in JSX attributes",
recommended: false,
url: "https://eslint.org/docs/latest/rules/jsx-quotes",
},
fixable: "whitespace",
schema: [
{
enum: ["prefer-single", "prefer-double"],
},
],
messages: {
unexpected: "Unexpected usage of {{description}}.",
},
},
create(context) {
const quoteOption = context.options[0] || "prefer-double",
setting = QUOTE_SETTINGS[quoteOption];
/**
* Checks if the given string literal node uses the expected quotes
* @param {ASTNode} node A string literal node.
* @returns {boolean} Whether or not the string literal used the expected quotes.
* @public
*/
function usesExpectedQuotes(node) {
return (
node.value.includes(setting.quote) ||
astUtils.isSurroundedBy(node.raw, setting.quote)
);
}
return {
JSXAttribute(node) {
const attributeValue = node.value;
if (
attributeValue &&
astUtils.isStringLiteral(attributeValue) &&
!usesExpectedQuotes(attributeValue)
) {
context.report({
node: attributeValue,
messageId: "unexpected",
data: {
description: setting.description,
},
fix(fixer) {
return fixer.replaceText(
attributeValue,
setting.convert(attributeValue.raw),
);
},
});
}
},
};
},
};

View File

@@ -0,0 +1,95 @@
import rng from './rng.js';
import stringify from './stringify.js'; // **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
let _nodeId;
let _clockseq; // Previous uuid creation time
let _lastMSecs = 0;
let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details
function v1(options, buf, offset) {
let i = buf && offset || 0;
const b = buf || new Array(16);
options = options || {};
let node = options.node || _nodeId;
let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if (node == null || clockseq == null) {
const seedBytes = options.random || (options.rng || rng)();
if (node == null) {
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
}
if (clockseq == null) {
// Per 4.2.2, randomize (14 bit) clockseq
clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
}
} // UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs)
const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq === undefined) {
clockseq = clockseq + 1 & 0x3fff;
} // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
nsecs = 0;
} // Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000; // `time_low`
const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff; // `time_mid`
const tmh = msecs / 0x100000000 * 10000 & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff; // `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low`
b[i++] = clockseq & 0xff; // `node`
for (let n = 0; n < 6; ++n) {
b[i + n] = node[n];
}
return buf || stringify(b);
}
export default v1;

View File

@@ -0,0 +1,35 @@
'use strict'
const Benchmark = require('benchmark')
const sjson = require('..')
const internals = {
text: '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
}
const suite = new Benchmark.Suite()
suite
.add('JSON.parse', () => {
JSON.parse(internals.text)
})
.add('secure-json-parse parse', () => {
sjson.parse(internals.text, { protoAction: 'ignore' })
})
.add('secure-json-parse safeParse', () => {
sjson.safeParse(internals.text)
})
.add('reviver', () => {
JSON.parse(internals.text, internals.reviver)
})
.on('cycle', (event) => {
console.log(String(event.target))
})
.on('complete', function () {
console.log('Fastest is ' + this.filter('fastest').map('name'))
})
.run({ async: true })
internals.reviver = function (_key, value) {
return value
}