WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -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),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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'
|
||||
);
|
||||
}
|
||||
@@ -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",
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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[];
|
||||
};
|
||||
}
|
||||
@@ -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',
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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 });
|
||||
});
|
||||
@@ -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',
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_object_destructuring_empty.cjs",
|
||||
"module": "../../esm/_object_destructuring_empty.js"
|
||||
}
|
||||
@@ -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"}
|
||||
@@ -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.
|
||||
@@ -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;
|
||||
@@ -0,0 +1,125 @@
|
||||
# locate-path [](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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export default function v6ToV1(uuid: string): string;
|
||||
export default function v6ToV1(uuid: Uint8Array): Uint8Array;
|
||||
@@ -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(),
|
||||
};
|
||||
}
|
||||
@@ -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 };
|
||||
@@ -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),
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user