WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
|
||||
test("z.object", () => {
|
||||
const a = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
points: z.optional(z.number()),
|
||||
"test?": z.boolean(),
|
||||
});
|
||||
|
||||
a._zod.def.shape["test?"];
|
||||
a._zod.def.shape.points._zod.optin;
|
||||
|
||||
type a = z.output<typeof a>;
|
||||
|
||||
expectTypeOf<a>().toEqualTypeOf<{
|
||||
name: string;
|
||||
age: number;
|
||||
points?: number | undefined;
|
||||
"test?": boolean;
|
||||
}>();
|
||||
expect(z.parse(a, { name: "john", age: 30, "test?": true })).toEqual({
|
||||
name: "john",
|
||||
age: 30,
|
||||
"test?": true,
|
||||
});
|
||||
// "test?" is required in ZodObject
|
||||
expect(() => z.parse(a, { name: "john", age: "30" })).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
// null prototype
|
||||
const schema = z.object({ a: z.string() });
|
||||
const obj = Object.create(null);
|
||||
obj.a = "foo";
|
||||
expect(schema.parse(obj)).toEqual({ a: "foo" });
|
||||
});
|
||||
|
||||
test("z.object().check()", () => {
|
||||
const a = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
points: z.optional(z.number()),
|
||||
"test?": z.boolean(),
|
||||
});
|
||||
|
||||
type a = z.output<typeof a>;
|
||||
|
||||
a.check(({ value }) => {
|
||||
expectTypeOf(value).toEqualTypeOf<a>();
|
||||
});
|
||||
});
|
||||
|
||||
test("z.strictObject", () => {
|
||||
const a = z.strictObject({
|
||||
name: z.string(),
|
||||
});
|
||||
expect(z.parse(a, { name: "john" })).toEqual({ name: "john" });
|
||||
expect(() => z.parse(a, { name: "john", age: 30 })).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.looseObject", () => {
|
||||
const a = z.looseObject({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
expect(z.parse(a, { name: "john", age: 30 })).toEqual({
|
||||
name: "john",
|
||||
age: 30,
|
||||
});
|
||||
expect(z.parse(a, { name: "john", age: 30, extra: true })).toEqual({
|
||||
name: "john",
|
||||
age: 30,
|
||||
extra: true,
|
||||
});
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
const userSchema = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
email: z.optional(z.string()),
|
||||
});
|
||||
|
||||
test("z.keyof", () => {
|
||||
// z.keyof returns an enum schema of the keys of an object schema
|
||||
const userKeysSchema = z.keyof(userSchema);
|
||||
type UserKeys = z.infer<typeof userKeysSchema>;
|
||||
expectTypeOf<UserKeys>().toEqualTypeOf<"name" | "age" | "email">();
|
||||
expect(userKeysSchema).toBeDefined();
|
||||
expect(userKeysSchema._zod.def.type).toBe("enum");
|
||||
expect(userKeysSchema._zod.def.entries).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
email: "email",
|
||||
});
|
||||
expect(z.safeParse(userKeysSchema, "name").success).toBe(true);
|
||||
expect(z.safeParse(userKeysSchema, "age").success).toBe(true);
|
||||
expect(z.safeParse(userKeysSchema, "email").success).toBe(true);
|
||||
expect(z.safeParse(userKeysSchema, "isAdmin").success).toBe(false);
|
||||
});
|
||||
|
||||
test("z.extend", () => {
|
||||
const extendedSchema = z.extend(userSchema, {
|
||||
isAdmin: z.boolean(),
|
||||
});
|
||||
type ExtendedUser = z.infer<typeof extendedSchema>;
|
||||
expectTypeOf<ExtendedUser>().toEqualTypeOf<{
|
||||
name: string;
|
||||
age: number;
|
||||
email?: string | undefined;
|
||||
isAdmin: boolean;
|
||||
}>();
|
||||
expect(extendedSchema).toBeDefined();
|
||||
expect(z.safeParse(extendedSchema, { name: "John", age: 30, isAdmin: true }).success).toBe(true);
|
||||
});
|
||||
|
||||
test("z.safeExtend", () => {
|
||||
const extended = z.safeExtend(userSchema, { name: z.string() });
|
||||
expect(z.safeParse(extended, { name: "John", age: 30 }).success).toBe(true);
|
||||
type Extended = z.infer<typeof extended>;
|
||||
expectTypeOf<Extended>().toEqualTypeOf<{ name: string; age: number; email?: string | undefined }>();
|
||||
// @ts-expect-error
|
||||
z.safeExtend(userSchema, { name: z.number() });
|
||||
});
|
||||
|
||||
test("z.pick", () => {
|
||||
const pickedSchema = z.pick(userSchema, { name: true, email: true });
|
||||
type PickedUser = z.infer<typeof pickedSchema>;
|
||||
expectTypeOf<PickedUser>().toEqualTypeOf<{ name: string; email?: string | undefined }>();
|
||||
expect(pickedSchema).toBeDefined();
|
||||
expect(z.safeParse(pickedSchema, { name: "John", email: "john@example.com" }).success).toBe(true);
|
||||
});
|
||||
|
||||
test("z.omit", () => {
|
||||
const omittedSchema = z.omit(userSchema, { age: true });
|
||||
type OmittedUser = z.infer<typeof omittedSchema>;
|
||||
expectTypeOf<OmittedUser>().toEqualTypeOf<{
|
||||
name: string;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
expect(omittedSchema).toBeDefined();
|
||||
expect(Reflect.ownKeys(omittedSchema._zod.def.shape)).toEqual(["name", "email"]);
|
||||
expect(z.safeParse(omittedSchema, { name: "John", email: "john@example.com" }).success).toBe(true);
|
||||
});
|
||||
|
||||
test("z.partial", () => {
|
||||
const partialSchema = z.partial(userSchema);
|
||||
type PartialUser = z.infer<typeof partialSchema>;
|
||||
expectTypeOf<PartialUser>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
expect(z.safeParse(partialSchema, { name: "John" }).success).toBe(true);
|
||||
});
|
||||
|
||||
test("z.partial with mask", () => {
|
||||
const partialSchemaWithMask = z.partial(userSchema, { name: true });
|
||||
type PartialUserWithMask = z.infer<typeof partialSchemaWithMask>;
|
||||
expectTypeOf<PartialUserWithMask>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age: number;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
expect(z.safeParse(partialSchemaWithMask, { age: 30 }).success).toBe(true);
|
||||
expect(z.safeParse(partialSchemaWithMask, { name: "John" }).success).toBe(false);
|
||||
});
|
||||
|
||||
test("z.pick/omit/partial/required - do not allow unknown keys", () => {
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
// Mixed valid + invalid keys - throws at parse time (lazy evaluation)
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.pick(schema, { name: true, asdf: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.omit(schema, { name: true, asdf: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.partial(schema, { name: true, asdf: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.required(schema, { name: true, asdf: true }), {})).toThrow();
|
||||
|
||||
// Only invalid keys
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.pick(schema, { $unknown: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.omit(schema, { $unknown: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.partial(schema, { $unknown: true }), {})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.parse(z.required(schema, { $unknown: true }), {})).toThrow();
|
||||
});
|
||||
|
||||
test("z.catchall", () => {
|
||||
// z.catchall()
|
||||
const schema = z.catchall(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
// age: z.number(),
|
||||
}),
|
||||
z.string()
|
||||
);
|
||||
|
||||
type schemaIn = z.input<typeof schema>;
|
||||
type schemaOut = z.output<typeof schema>;
|
||||
expectTypeOf<schemaIn>().toEqualTypeOf<{
|
||||
name: string;
|
||||
[key: string]: string;
|
||||
}>();
|
||||
|
||||
expectTypeOf<schemaOut>().toEqualTypeOf<{
|
||||
name: string;
|
||||
[key: string]: string;
|
||||
}>();
|
||||
|
||||
schema.parse({
|
||||
name: "john",
|
||||
age: "30",
|
||||
extra: "extra value",
|
||||
});
|
||||
|
||||
expect(() => schema.parse({ name: "john", age: 30 })).toThrow();
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
import {Connection, SignatureResult} from '../connection';
|
||||
import {Transaction} from '../transaction';
|
||||
import type {ConfirmOptions} from '../connection';
|
||||
import type {Signer} from '../keypair';
|
||||
import type {TransactionSignature} from '../transaction';
|
||||
import {SendTransactionError} from '../errors';
|
||||
|
||||
/**
|
||||
* Sign, send and confirm a transaction.
|
||||
*
|
||||
* If `commitment` option is not specified, defaults to 'max' commitment.
|
||||
*
|
||||
* @param {Connection} connection
|
||||
* @param {Transaction} transaction
|
||||
* @param {Array<Signer>} signers
|
||||
* @param {ConfirmOptions} [options]
|
||||
* @returns {Promise<TransactionSignature>}
|
||||
*/
|
||||
export async function sendAndConfirmTransaction(
|
||||
connection: Connection,
|
||||
transaction: Transaction,
|
||||
signers: Array<Signer>,
|
||||
options?: ConfirmOptions &
|
||||
Readonly<{
|
||||
// A signal that, when aborted, cancels any outstanding transaction confirmation operations
|
||||
abortSignal?: AbortSignal;
|
||||
}>,
|
||||
): Promise<TransactionSignature> {
|
||||
const sendOptions = options && {
|
||||
skipPreflight: options.skipPreflight,
|
||||
preflightCommitment: options.preflightCommitment || options.commitment,
|
||||
maxRetries: options.maxRetries,
|
||||
minContextSlot: options.minContextSlot,
|
||||
};
|
||||
|
||||
const signature = await connection.sendTransaction(
|
||||
transaction,
|
||||
signers,
|
||||
sendOptions,
|
||||
);
|
||||
|
||||
let status: SignatureResult;
|
||||
if (
|
||||
transaction.recentBlockhash != null &&
|
||||
transaction.lastValidBlockHeight != null
|
||||
) {
|
||||
status = (
|
||||
await connection.confirmTransaction(
|
||||
{
|
||||
abortSignal: options?.abortSignal,
|
||||
signature: signature,
|
||||
blockhash: transaction.recentBlockhash,
|
||||
lastValidBlockHeight: transaction.lastValidBlockHeight,
|
||||
},
|
||||
options && options.commitment,
|
||||
)
|
||||
).value;
|
||||
} else if (
|
||||
transaction.minNonceContextSlot != null &&
|
||||
transaction.nonceInfo != null
|
||||
) {
|
||||
const {nonceInstruction} = transaction.nonceInfo;
|
||||
const nonceAccountPubkey = nonceInstruction.keys[0].pubkey;
|
||||
status = (
|
||||
await connection.confirmTransaction(
|
||||
{
|
||||
abortSignal: options?.abortSignal,
|
||||
minContextSlot: transaction.minNonceContextSlot,
|
||||
nonceAccountPubkey,
|
||||
nonceValue: transaction.nonceInfo.nonce,
|
||||
signature,
|
||||
},
|
||||
options && options.commitment,
|
||||
)
|
||||
).value;
|
||||
} else {
|
||||
if (options?.abortSignal != null) {
|
||||
console.warn(
|
||||
'sendAndConfirmTransaction(): A transaction with a deprecated confirmation strategy was ' +
|
||||
'supplied along with an `abortSignal`. Only transactions having `lastValidBlockHeight` ' +
|
||||
'or a combination of `nonceInfo` and `minNonceContextSlot` are abortable.',
|
||||
);
|
||||
}
|
||||
status = (
|
||||
await connection.confirmTransaction(
|
||||
signature,
|
||||
options && options.commitment,
|
||||
)
|
||||
).value;
|
||||
}
|
||||
|
||||
if (status.err) {
|
||||
if (signature != null) {
|
||||
throw new SendTransactionError({
|
||||
action: 'send',
|
||||
signature: signature,
|
||||
transactionMessage: `Status: (${JSON.stringify(status)})`,
|
||||
});
|
||||
}
|
||||
throw new Error(
|
||||
`Transaction ${signature} failed (${JSON.stringify(status)})`,
|
||||
);
|
||||
}
|
||||
|
||||
return signature;
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
'use strict';
|
||||
|
||||
var errors = require('@solana/errors');
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
|
||||
// src/bytes.ts
|
||||
var mergeBytes = (byteArrays) => {
|
||||
const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length);
|
||||
if (nonEmptyByteArrays.length === 0) {
|
||||
return byteArrays.length ? byteArrays[0] : new Uint8Array();
|
||||
}
|
||||
if (nonEmptyByteArrays.length === 1) {
|
||||
return nonEmptyByteArrays[0];
|
||||
}
|
||||
const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);
|
||||
const result = new Uint8Array(totalLength);
|
||||
let offset = 0;
|
||||
nonEmptyByteArrays.forEach((arr) => {
|
||||
result.set(arr, offset);
|
||||
offset += arr.length;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
var padBytes = (bytes, length) => {
|
||||
if (bytes.length >= length) return bytes;
|
||||
const paddedBytes = new Uint8Array(length).fill(0);
|
||||
paddedBytes.set(bytes);
|
||||
return paddedBytes;
|
||||
};
|
||||
var fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);
|
||||
function containsBytes(data, bytes, offset) {
|
||||
const slice = offset === 0 && data.length === bytes.length ? data : data.slice(offset, offset + bytes.length);
|
||||
if (slice.length !== bytes.length) return false;
|
||||
return bytes.every((b, i) => b === slice[i]);
|
||||
}
|
||||
function getEncodedSize(value, encoder) {
|
||||
return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value);
|
||||
}
|
||||
function createEncoder(encoder) {
|
||||
return Object.freeze({
|
||||
...encoder,
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, encoder));
|
||||
encoder.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function createDecoder(decoder) {
|
||||
return Object.freeze({
|
||||
...decoder,
|
||||
decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0]
|
||||
});
|
||||
}
|
||||
function createCodec(codec) {
|
||||
return Object.freeze({
|
||||
...codec,
|
||||
decode: (bytes, offset = 0) => codec.read(bytes, offset)[0],
|
||||
encode: (value) => {
|
||||
const bytes = new Uint8Array(getEncodedSize(value, codec));
|
||||
codec.write(value, bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function isFixedSize(codec) {
|
||||
return "fixedSize" in codec && typeof codec.fixedSize === "number";
|
||||
}
|
||||
function assertIsFixedSize(codec) {
|
||||
if (!isFixedSize(codec)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_FIXED_LENGTH);
|
||||
}
|
||||
}
|
||||
function isVariableSize(codec) {
|
||||
return !isFixedSize(codec);
|
||||
}
|
||||
function assertIsVariableSize(codec) {
|
||||
if (!isVariableSize(codec)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_VARIABLE_LENGTH);
|
||||
}
|
||||
}
|
||||
function combineCodec(encoder, decoder) {
|
||||
if (isFixedSize(encoder) !== isFixedSize(decoder)) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_SIZE_COMPATIBILITY_MISMATCH);
|
||||
}
|
||||
if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_FIXED_SIZE_MISMATCH, {
|
||||
decoderFixedSize: decoder.fixedSize,
|
||||
encoderFixedSize: encoder.fixedSize
|
||||
});
|
||||
}
|
||||
if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODER_DECODER_MAX_SIZE_MISMATCH, {
|
||||
decoderMaxSize: decoder.maxSize,
|
||||
encoderMaxSize: encoder.maxSize
|
||||
});
|
||||
}
|
||||
return {
|
||||
...decoder,
|
||||
...encoder,
|
||||
decode: decoder.decode,
|
||||
encode: encoder.encode,
|
||||
read: decoder.read,
|
||||
write: encoder.write
|
||||
};
|
||||
}
|
||||
|
||||
// src/add-codec-sentinel.ts
|
||||
function addEncoderSentinel(encoder, sentinel) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
if (findSentinelIndex(encoderBytes, sentinel) >= 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__ENCODED_BYTES_MUST_NOT_INCLUDE_SENTINEL, {
|
||||
encodedBytes: encoderBytes,
|
||||
hexEncodedBytes: hexBytes(encoderBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
bytes.set(encoderBytes, offset);
|
||||
offset += encoderBytes.length;
|
||||
bytes.set(sentinel, offset);
|
||||
offset += sentinel.length;
|
||||
return offset;
|
||||
};
|
||||
if (isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: encoder.fixedSize + sentinel.length, write });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...encoder.maxSize != null ? { maxSize: encoder.maxSize + sentinel.length } : {},
|
||||
getSizeFromValue: (value) => encoder.getSizeFromValue(value) + sentinel.length,
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSentinel(decoder, sentinel) {
|
||||
const read = (bytes, offset) => {
|
||||
const candidateBytes = offset === 0 ? bytes : bytes.slice(offset);
|
||||
const sentinelIndex = findSentinelIndex(candidateBytes, sentinel);
|
||||
if (sentinelIndex === -1) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__SENTINEL_MISSING_IN_DECODED_BYTES, {
|
||||
decodedBytes: candidateBytes,
|
||||
hexDecodedBytes: hexBytes(candidateBytes),
|
||||
hexSentinel: hexBytes(sentinel),
|
||||
sentinel
|
||||
});
|
||||
}
|
||||
const preSentinelBytes = candidateBytes.slice(0, sentinelIndex);
|
||||
return [decoder.decode(preSentinelBytes), offset + preSentinelBytes.length + sentinel.length];
|
||||
};
|
||||
if (isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: decoder.fixedSize + sentinel.length, read });
|
||||
}
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
...decoder.maxSize != null ? { maxSize: decoder.maxSize + sentinel.length } : {},
|
||||
read
|
||||
});
|
||||
}
|
||||
function addCodecSentinel(codec, sentinel) {
|
||||
return combineCodec(addEncoderSentinel(codec, sentinel), addDecoderSentinel(codec, sentinel));
|
||||
}
|
||||
function findSentinelIndex(bytes, sentinel) {
|
||||
return bytes.findIndex((byte, index, arr) => {
|
||||
if (sentinel.length === 1) return byte === sentinel[0];
|
||||
return containsBytes(arr, sentinel, index);
|
||||
});
|
||||
}
|
||||
function hexBytes(bytes) {
|
||||
return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
||||
}
|
||||
function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) {
|
||||
if (bytes.length - offset <= 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__CANNOT_DECODE_EMPTY_BYTE_ARRAY, {
|
||||
codecDescription
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) {
|
||||
const bytesLength = bytes.length - offset;
|
||||
if (bytesLength < expected) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__INVALID_BYTE_LENGTH, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
expected
|
||||
});
|
||||
}
|
||||
}
|
||||
function assertByteArrayOffsetIsNotOutOfRange(codecDescription, offset, bytesLength) {
|
||||
if (offset < 0 || offset > bytesLength) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__OFFSET_OUT_OF_RANGE, {
|
||||
bytesLength,
|
||||
codecDescription,
|
||||
offset
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// src/add-codec-size-prefix.ts
|
||||
function addEncoderSizePrefix(encoder, prefix) {
|
||||
const write = (value, bytes, offset) => {
|
||||
const encoderBytes = encoder.encode(value);
|
||||
offset = prefix.write(encoderBytes.length, bytes, offset);
|
||||
bytes.set(encoderBytes, offset);
|
||||
return offset + encoderBytes.length;
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(encoder)) {
|
||||
return createEncoder({ ...encoder, fixedSize: prefix.fixedSize + encoder.fixedSize, write });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const encoderMaxSize = isFixedSize(encoder) ? encoder.fixedSize : encoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && encoderMaxSize !== null ? prefixMaxSize + encoderMaxSize : null;
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
...maxSize !== null ? { maxSize } : {},
|
||||
getSizeFromValue: (value) => {
|
||||
const encoderSize = getEncodedSize(value, encoder);
|
||||
return getEncodedSize(encoderSize, prefix) + encoderSize;
|
||||
},
|
||||
write
|
||||
});
|
||||
}
|
||||
function addDecoderSizePrefix(decoder, prefix) {
|
||||
const read = (bytes, offset) => {
|
||||
const [bigintSize, decoderOffset] = prefix.read(bytes, offset);
|
||||
const size = Number(bigintSize);
|
||||
offset = decoderOffset;
|
||||
if (offset > 0 || bytes.length > size) {
|
||||
bytes = bytes.slice(offset, offset + size);
|
||||
}
|
||||
assertByteArrayHasEnoughBytesForCodec("addDecoderSizePrefix", size, bytes);
|
||||
return [decoder.decode(bytes), offset + size];
|
||||
};
|
||||
if (isFixedSize(prefix) && isFixedSize(decoder)) {
|
||||
return createDecoder({ ...decoder, fixedSize: prefix.fixedSize + decoder.fixedSize, read });
|
||||
}
|
||||
const prefixMaxSize = isFixedSize(prefix) ? prefix.fixedSize : prefix.maxSize ?? null;
|
||||
const decoderMaxSize = isFixedSize(decoder) ? decoder.fixedSize : decoder.maxSize ?? null;
|
||||
const maxSize = prefixMaxSize !== null && decoderMaxSize !== null ? prefixMaxSize + decoderMaxSize : null;
|
||||
return createDecoder({ ...decoder, ...maxSize !== null ? { maxSize } : {}, read });
|
||||
}
|
||||
function addCodecSizePrefix(codec, prefix) {
|
||||
return combineCodec(addEncoderSizePrefix(codec, prefix), addDecoderSizePrefix(codec, prefix));
|
||||
}
|
||||
|
||||
// src/fix-codec-size.ts
|
||||
function fixEncoderSize(encoder, fixedBytes) {
|
||||
return createEncoder({
|
||||
fixedSize: fixedBytes,
|
||||
write: (value, bytes, offset) => {
|
||||
const variableByteArray = encoder.encode(value);
|
||||
const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray;
|
||||
bytes.set(fixedByteArray, offset);
|
||||
return offset + fixedBytes;
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixDecoderSize(decoder, fixedBytes) {
|
||||
return createDecoder({
|
||||
fixedSize: fixedBytes,
|
||||
read: (bytes, offset) => {
|
||||
assertByteArrayHasEnoughBytesForCodec("fixCodecSize", fixedBytes, bytes, offset);
|
||||
if (offset > 0 || bytes.length > fixedBytes) {
|
||||
bytes = bytes.slice(offset, offset + fixedBytes);
|
||||
}
|
||||
if (isFixedSize(decoder)) {
|
||||
bytes = fixBytes(bytes, decoder.fixedSize);
|
||||
}
|
||||
const [value] = decoder.read(bytes, 0);
|
||||
return [value, offset + fixedBytes];
|
||||
}
|
||||
});
|
||||
}
|
||||
function fixCodecSize(codec, fixedBytes) {
|
||||
return combineCodec(fixEncoderSize(codec, fixedBytes), fixDecoderSize(codec, fixedBytes));
|
||||
}
|
||||
|
||||
// src/offset-codec.ts
|
||||
function offsetEncoder(encoder, config) {
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPreOffset, bytes.length);
|
||||
const postOffset = encoder.write(value, bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetEncoder", newPostOffset, bytes.length);
|
||||
return newPostOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetDecoder(decoder, config) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, preOffset) => {
|
||||
const wrapBytes = (offset) => modulo(offset, bytes.length);
|
||||
const newPreOffset = config.preOffset ? config.preOffset({ bytes, preOffset, wrapBytes }) : preOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPreOffset, bytes.length);
|
||||
const [value, postOffset] = decoder.read(bytes, newPreOffset);
|
||||
const newPostOffset = config.postOffset ? config.postOffset({ bytes, newPreOffset, postOffset, preOffset, wrapBytes }) : postOffset;
|
||||
assertByteArrayOffsetIsNotOutOfRange("offsetDecoder", newPostOffset, bytes.length);
|
||||
return [value, newPostOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function offsetCodec(codec, config) {
|
||||
return combineCodec(offsetEncoder(codec, config), offsetDecoder(codec, config));
|
||||
}
|
||||
function modulo(dividend, divisor) {
|
||||
if (divisor === 0) return 0;
|
||||
return (dividend % divisor + divisor) % divisor;
|
||||
}
|
||||
function resizeEncoder(encoder, resize) {
|
||||
if (isFixedSize(encoder)) {
|
||||
const fixedSize = resize(encoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return createEncoder({ ...encoder, fixedSize });
|
||||
}
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
getSizeFromValue: (value) => {
|
||||
const newSize = resize(encoder.getSizeFromValue(value));
|
||||
if (newSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: newSize,
|
||||
codecDescription: "resizeEncoder"
|
||||
});
|
||||
}
|
||||
return newSize;
|
||||
}
|
||||
});
|
||||
}
|
||||
function resizeDecoder(decoder, resize) {
|
||||
if (isFixedSize(decoder)) {
|
||||
const fixedSize = resize(decoder.fixedSize);
|
||||
if (fixedSize < 0) {
|
||||
throw new errors.SolanaError(errors.SOLANA_ERROR__CODECS__EXPECTED_POSITIVE_BYTE_LENGTH, {
|
||||
bytesLength: fixedSize,
|
||||
codecDescription: "resizeDecoder"
|
||||
});
|
||||
}
|
||||
return createDecoder({ ...decoder, fixedSize });
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
function resizeCodec(codec, resize) {
|
||||
return combineCodec(resizeEncoder(codec, resize), resizeDecoder(codec, resize));
|
||||
}
|
||||
|
||||
// src/pad-codec.ts
|
||||
function padLeftEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightEncoder(encoder, offset) {
|
||||
return offsetEncoder(
|
||||
resizeEncoder(encoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ preOffset: ({ preOffset }) => preOffset + offset }
|
||||
);
|
||||
}
|
||||
function padRightDecoder(decoder, offset) {
|
||||
return offsetDecoder(
|
||||
resizeDecoder(decoder, (size) => size + offset),
|
||||
{ postOffset: ({ postOffset }) => postOffset + offset }
|
||||
);
|
||||
}
|
||||
function padLeftCodec(codec, offset) {
|
||||
return combineCodec(padLeftEncoder(codec, offset), padLeftDecoder(codec, offset));
|
||||
}
|
||||
function padRightCodec(codec, offset) {
|
||||
return combineCodec(padRightEncoder(codec, offset), padRightDecoder(codec, offset));
|
||||
}
|
||||
|
||||
// src/reverse-codec.ts
|
||||
function copySourceToTargetInReverse(source, target_WILL_MUTATE, sourceOffset, sourceLength, targetOffset = 0) {
|
||||
while (sourceOffset < --sourceLength) {
|
||||
const leftValue = source[sourceOffset];
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceLength];
|
||||
target_WILL_MUTATE[sourceLength + targetOffset] = leftValue;
|
||||
sourceOffset++;
|
||||
}
|
||||
if (sourceOffset === sourceLength) {
|
||||
target_WILL_MUTATE[sourceOffset + targetOffset] = source[sourceOffset];
|
||||
}
|
||||
}
|
||||
function reverseEncoder(encoder) {
|
||||
assertIsFixedSize(encoder);
|
||||
return createEncoder({
|
||||
...encoder,
|
||||
write: (value, bytes, offset) => {
|
||||
const newOffset = encoder.write(value, bytes, offset);
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
bytes,
|
||||
offset,
|
||||
offset + encoder.fixedSize
|
||||
);
|
||||
return newOffset;
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseDecoder(decoder) {
|
||||
assertIsFixedSize(decoder);
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const reversedBytes = bytes.slice();
|
||||
copySourceToTargetInReverse(
|
||||
bytes,
|
||||
reversedBytes,
|
||||
offset,
|
||||
offset + decoder.fixedSize
|
||||
);
|
||||
return decoder.read(reversedBytes, offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
function reverseCodec(codec) {
|
||||
return combineCodec(reverseEncoder(codec), reverseDecoder(codec));
|
||||
}
|
||||
|
||||
// src/transform-codec.ts
|
||||
function transformEncoder(encoder, unmap) {
|
||||
return createEncoder({
|
||||
...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder,
|
||||
write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset)
|
||||
});
|
||||
}
|
||||
function transformDecoder(decoder, map) {
|
||||
return createDecoder({
|
||||
...decoder,
|
||||
read: (bytes, offset) => {
|
||||
const [value, newOffset] = decoder.read(bytes, offset);
|
||||
return [map(value, bytes, offset), newOffset];
|
||||
}
|
||||
});
|
||||
}
|
||||
function transformCodec(codec, unmap, map) {
|
||||
return createCodec({
|
||||
...transformEncoder(codec, unmap),
|
||||
read: map ? transformDecoder(codec, map).read : codec.read
|
||||
});
|
||||
}
|
||||
|
||||
exports.addCodecSentinel = addCodecSentinel;
|
||||
exports.addCodecSizePrefix = addCodecSizePrefix;
|
||||
exports.addDecoderSentinel = addDecoderSentinel;
|
||||
exports.addDecoderSizePrefix = addDecoderSizePrefix;
|
||||
exports.addEncoderSentinel = addEncoderSentinel;
|
||||
exports.addEncoderSizePrefix = addEncoderSizePrefix;
|
||||
exports.assertByteArrayHasEnoughBytesForCodec = assertByteArrayHasEnoughBytesForCodec;
|
||||
exports.assertByteArrayIsNotEmptyForCodec = assertByteArrayIsNotEmptyForCodec;
|
||||
exports.assertByteArrayOffsetIsNotOutOfRange = assertByteArrayOffsetIsNotOutOfRange;
|
||||
exports.assertIsFixedSize = assertIsFixedSize;
|
||||
exports.assertIsVariableSize = assertIsVariableSize;
|
||||
exports.combineCodec = combineCodec;
|
||||
exports.containsBytes = containsBytes;
|
||||
exports.createCodec = createCodec;
|
||||
exports.createDecoder = createDecoder;
|
||||
exports.createEncoder = createEncoder;
|
||||
exports.fixBytes = fixBytes;
|
||||
exports.fixCodecSize = fixCodecSize;
|
||||
exports.fixDecoderSize = fixDecoderSize;
|
||||
exports.fixEncoderSize = fixEncoderSize;
|
||||
exports.getEncodedSize = getEncodedSize;
|
||||
exports.isFixedSize = isFixedSize;
|
||||
exports.isVariableSize = isVariableSize;
|
||||
exports.mergeBytes = mergeBytes;
|
||||
exports.offsetCodec = offsetCodec;
|
||||
exports.offsetDecoder = offsetDecoder;
|
||||
exports.offsetEncoder = offsetEncoder;
|
||||
exports.padBytes = padBytes;
|
||||
exports.padLeftCodec = padLeftCodec;
|
||||
exports.padLeftDecoder = padLeftDecoder;
|
||||
exports.padLeftEncoder = padLeftEncoder;
|
||||
exports.padRightCodec = padRightCodec;
|
||||
exports.padRightDecoder = padRightDecoder;
|
||||
exports.padRightEncoder = padRightEncoder;
|
||||
exports.resizeCodec = resizeCodec;
|
||||
exports.resizeDecoder = resizeDecoder;
|
||||
exports.resizeEncoder = resizeEncoder;
|
||||
exports.reverseCodec = reverseCodec;
|
||||
exports.reverseDecoder = reverseDecoder;
|
||||
exports.reverseEncoder = reverseEncoder;
|
||||
exports.transformCodec = transformCodec;
|
||||
exports.transformDecoder = transformDecoder;
|
||||
exports.transformEncoder = transformEncoder;
|
||||
//# sourceMappingURL=index.browser.cjs.map
|
||||
//# sourceMappingURL=index.browser.cjs.map
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,326 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeComparisonResult = void 0;
|
||||
exports.compareNodes = compareNodes;
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const visitor_keys_1 = require("@typescript-eslint/visitor-keys");
|
||||
var NodeComparisonResult;
|
||||
(function (NodeComparisonResult) {
|
||||
/** the two nodes are comparably the same */
|
||||
NodeComparisonResult["Equal"] = "Equal";
|
||||
/** the left node is a subset of the right node */
|
||||
NodeComparisonResult["Subset"] = "Subset";
|
||||
/** the left node is not the same or is a superset of the right node */
|
||||
NodeComparisonResult["Invalid"] = "Invalid";
|
||||
})(NodeComparisonResult || (exports.NodeComparisonResult = NodeComparisonResult = {}));
|
||||
function compareArrays(arrayA, arrayB) {
|
||||
if (arrayA.length !== arrayB.length) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
const result = arrayA.every((elA, idx) => {
|
||||
const elB = arrayB[idx];
|
||||
if (elA == null || elB == null) {
|
||||
return elA === elB;
|
||||
}
|
||||
return compareUnknownValues(elA, elB) === NodeComparisonResult.Equal;
|
||||
});
|
||||
if (result) {
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
function isValidNode(x) {
|
||||
return (typeof x === 'object' &&
|
||||
x != null &&
|
||||
'type' in x &&
|
||||
typeof x.type === 'string');
|
||||
}
|
||||
function isValidChainExpressionToLookThrough(node) {
|
||||
return (!(node.parent?.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
||||
node.parent.object === node) &&
|
||||
!(node.parent?.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
||||
node.parent.callee === node) &&
|
||||
node.type === utils_1.AST_NODE_TYPES.ChainExpression);
|
||||
}
|
||||
function compareUnknownValues(valueA, valueB) {
|
||||
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
||||
if (valueA == null || valueB == null) {
|
||||
if (valueA !== valueB) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
||||
if (!isValidNode(valueA) || !isValidNode(valueB)) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
return compareNodes(valueA, valueB);
|
||||
}
|
||||
function compareByVisiting(nodeA, nodeB) {
|
||||
const currentVisitorKeys = visitor_keys_1.visitorKeys[nodeA.type];
|
||||
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
||||
if (currentVisitorKeys == null) {
|
||||
// we don't know how to visit this node, so assume it's invalid to avoid false-positives / broken fixers
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
if (currentVisitorKeys.length === 0) {
|
||||
// assume nodes with no keys are constant things like keywords
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
for (const key of currentVisitorKeys) {
|
||||
// @ts-expect-error - dynamic access but it's safe
|
||||
const nodeAChildOrChildren = nodeA[key];
|
||||
// @ts-expect-error - dynamic access but it's safe
|
||||
const nodeBChildOrChildren = nodeB[key];
|
||||
if (Array.isArray(nodeAChildOrChildren)) {
|
||||
const arrayA = nodeAChildOrChildren;
|
||||
const arrayB = nodeBChildOrChildren;
|
||||
const result = compareArrays(arrayA, arrayB);
|
||||
if (result !== NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// fallthrough to the next key as the key was "equal"
|
||||
}
|
||||
else {
|
||||
const result = compareUnknownValues(nodeAChildOrChildren, nodeBChildOrChildren);
|
||||
if (result !== NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// fallthrough to the next key as the key was "equal"
|
||||
}
|
||||
}
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
function compareNodesUncached(nodeA, nodeB) {
|
||||
if (nodeA.type !== nodeB.type) {
|
||||
// special cases where nodes are allowed to be non-equal
|
||||
// look through a chain expression node at the top-level because it only
|
||||
// exists to delimit the end of an optional chain
|
||||
//
|
||||
// a?.b && a.b.c
|
||||
// ^^^^ ChainExpression, MemberExpression
|
||||
// ^^^^^ MemberExpression
|
||||
//
|
||||
// except for in this class of cases
|
||||
// (a?.b).c && a.b.c
|
||||
// because the parentheses have runtime meaning (sad face)
|
||||
if (isValidChainExpressionToLookThrough(nodeA)) {
|
||||
return compareNodes(nodeA.expression, nodeB);
|
||||
}
|
||||
if (isValidChainExpressionToLookThrough(nodeB)) {
|
||||
return compareNodes(nodeA, nodeB.expression);
|
||||
}
|
||||
// look through the type-only non-null assertion because its existence could
|
||||
// possibly be replaced by an optional chain instead
|
||||
//
|
||||
// a.b! && a.b.c
|
||||
// ^^^^ TSNonNullExpression
|
||||
if (nodeA.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) {
|
||||
return compareNodes(nodeA.expression, nodeB);
|
||||
}
|
||||
if (nodeB.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) {
|
||||
return compareNodes(nodeA, nodeB.expression);
|
||||
}
|
||||
// special case for subset optional chains where the node types don't match,
|
||||
// but we want to try comparing by discarding the "extra" code
|
||||
//
|
||||
// a && a.b
|
||||
// ^ compare this
|
||||
// a && a()
|
||||
// ^ compare this
|
||||
// a.b && a.b()
|
||||
// ^^^ compare this
|
||||
// a() && a().b
|
||||
// ^^^ compare this
|
||||
// import.meta && import.meta.b
|
||||
// ^^^^^^^^^^^ compare this
|
||||
if (nodeA.type === utils_1.AST_NODE_TYPES.CallExpression ||
|
||||
nodeA.type === utils_1.AST_NODE_TYPES.Identifier ||
|
||||
nodeA.type === utils_1.AST_NODE_TYPES.MemberExpression ||
|
||||
nodeA.type === utils_1.AST_NODE_TYPES.MetaProperty) {
|
||||
switch (nodeB.type) {
|
||||
case utils_1.AST_NODE_TYPES.MemberExpression:
|
||||
if (nodeB.property.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
||||
// Private identifiers in optional chaining is not currently allowed
|
||||
// TODO - handle this once TS supports it (https://github.com/microsoft/TypeScript/issues/42734)
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
if (compareNodes(nodeA, nodeB.object) !== NodeComparisonResult.Invalid) {
|
||||
return NodeComparisonResult.Subset;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
case utils_1.AST_NODE_TYPES.CallExpression:
|
||||
if (compareNodes(nodeA, nodeB.callee) !== NodeComparisonResult.Invalid) {
|
||||
return NodeComparisonResult.Subset;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
default:
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
switch (nodeA.type) {
|
||||
// these expressions create a new instance each time - so it makes no sense to compare the chain
|
||||
case utils_1.AST_NODE_TYPES.ArrayExpression:
|
||||
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
||||
case utils_1.AST_NODE_TYPES.ClassExpression:
|
||||
case utils_1.AST_NODE_TYPES.FunctionExpression:
|
||||
case utils_1.AST_NODE_TYPES.JSXElement:
|
||||
case utils_1.AST_NODE_TYPES.JSXFragment:
|
||||
case utils_1.AST_NODE_TYPES.NewExpression:
|
||||
case utils_1.AST_NODE_TYPES.ObjectExpression:
|
||||
return NodeComparisonResult.Invalid;
|
||||
// chaining from assignments could change the value irrevocably - so it makes no sense to compare the chain
|
||||
case utils_1.AST_NODE_TYPES.AssignmentExpression:
|
||||
return NodeComparisonResult.Invalid;
|
||||
case utils_1.AST_NODE_TYPES.CallExpression: {
|
||||
const nodeBCall = nodeB;
|
||||
// check for cases like
|
||||
// foo() && foo()(bar)
|
||||
// ^^^^^ nodeA
|
||||
// ^^^^^^^^^^ nodeB
|
||||
// we don't want to check the arguments in this case
|
||||
const aSubsetOfB = compareNodes(nodeA, nodeBCall.callee);
|
||||
if (aSubsetOfB !== NodeComparisonResult.Invalid) {
|
||||
return NodeComparisonResult.Subset;
|
||||
}
|
||||
const calleeCompare = compareNodes(nodeA.callee, nodeBCall.callee);
|
||||
if (calleeCompare !== NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// NOTE - we purposely ignore optional flag because for our purposes
|
||||
// foo?.bar() && foo.bar?.()?.baz
|
||||
// or
|
||||
// foo.bar() && foo?.bar?.()?.baz
|
||||
// are going to be exactly the same
|
||||
const argumentCompare = compareArrays(nodeA.arguments, nodeBCall.arguments);
|
||||
if (argumentCompare !== NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
const typeParamCompare = compareNodes(nodeA.typeArguments, nodeBCall.typeArguments);
|
||||
if (typeParamCompare === NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.ChainExpression:
|
||||
// special case handling for ChainExpression because it's allowed to be a subset
|
||||
return compareNodes(nodeA, nodeB.expression);
|
||||
case utils_1.AST_NODE_TYPES.Identifier:
|
||||
case utils_1.AST_NODE_TYPES.PrivateIdentifier:
|
||||
if (nodeA.name === nodeB.name) {
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
case utils_1.AST_NODE_TYPES.Literal: {
|
||||
const nodeBLiteral = nodeB;
|
||||
if (nodeA.raw === nodeBLiteral.raw &&
|
||||
nodeA.value === nodeBLiteral.value) {
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.MemberExpression: {
|
||||
const nodeBMember = nodeB;
|
||||
if (nodeBMember.property.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
||||
// Private identifiers in optional chaining is not currently allowed
|
||||
// TODO - handle this once TS supports it (https://github.com/microsoft/TypeScript/issues/42734)
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// check for cases like
|
||||
// foo.bar && foo.bar.baz
|
||||
// ^^^^^^^ nodeA
|
||||
// ^^^^^^^^^^^ nodeB
|
||||
// result === Equal
|
||||
//
|
||||
// foo.bar && foo.bar.baz.bam
|
||||
// ^^^^^^^ nodeA
|
||||
// ^^^^^^^^^^^^^^^ nodeB
|
||||
// result === Subset
|
||||
//
|
||||
// we don't want to check the property in this case
|
||||
const aSubsetOfB = compareNodes(nodeA, nodeBMember.object);
|
||||
if (aSubsetOfB !== NodeComparisonResult.Invalid) {
|
||||
return NodeComparisonResult.Subset;
|
||||
}
|
||||
if (nodeA.computed !== nodeBMember.computed) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// NOTE - we purposely ignore optional flag because for our purposes
|
||||
// foo?.bar && foo.bar?.baz
|
||||
// or
|
||||
// foo.bar && foo?.bar?.baz
|
||||
// are going to be exactly the same
|
||||
const objectCompare = compareNodes(nodeA.object, nodeBMember.object);
|
||||
if (objectCompare !== NodeComparisonResult.Equal) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
return compareNodes(nodeA.property, nodeBMember.property);
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSTemplateLiteralType:
|
||||
case utils_1.AST_NODE_TYPES.TemplateLiteral: {
|
||||
const nodeBTemplate = nodeB;
|
||||
const areQuasisEqual = nodeA.quasis.length === nodeBTemplate.quasis.length &&
|
||||
nodeA.quasis.every((elA, idx) => {
|
||||
const elB = nodeBTemplate.quasis[idx];
|
||||
return elA.value.cooked === elB.value.cooked;
|
||||
});
|
||||
if (!areQuasisEqual) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TemplateElement: {
|
||||
const nodeBElement = nodeB;
|
||||
if (nodeA.value.cooked === nodeBElement.value.cooked) {
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
// these aren't actually valid expressions.
|
||||
// https://github.com/typescript-eslint/typescript-eslint/blob/20d7caee35ab84ae6381fdf04338c9e2b9e2bc48/packages/ast-spec/src/unions/Expression.ts#L37-L43
|
||||
case utils_1.AST_NODE_TYPES.ArrayPattern:
|
||||
case utils_1.AST_NODE_TYPES.ObjectPattern:
|
||||
/* istanbul ignore next */
|
||||
return NodeComparisonResult.Invalid;
|
||||
// update expression returns a number and also changes the value each time - so it makes no sense to compare the chain
|
||||
case utils_1.AST_NODE_TYPES.UpdateExpression:
|
||||
return NodeComparisonResult.Invalid;
|
||||
// yield returns the value passed to the `next` function, so it may not be the same each time - so it makes no sense to compare the chain
|
||||
case utils_1.AST_NODE_TYPES.YieldExpression:
|
||||
return NodeComparisonResult.Invalid;
|
||||
// general-case automatic handling of nodes to save us implementing every
|
||||
// single case by hand. This just iterates the visitor keys to recursively
|
||||
// check the children.
|
||||
//
|
||||
// Any specific logic cases or short-circuits should be listed as separate
|
||||
// cases so that they don't fall into this generic handling
|
||||
default:
|
||||
return compareByVisiting(nodeA, nodeB);
|
||||
}
|
||||
}
|
||||
const COMPARE_NODES_CACHE = new WeakMap();
|
||||
/**
|
||||
* Compares two nodes' ASTs to determine if the A is equal to or a subset of B
|
||||
*/
|
||||
function compareNodes(nodeA, nodeB) {
|
||||
if (nodeA == null || nodeB == null) {
|
||||
if (nodeA !== nodeB) {
|
||||
return NodeComparisonResult.Invalid;
|
||||
}
|
||||
return NodeComparisonResult.Equal;
|
||||
}
|
||||
const cached = COMPARE_NODES_CACHE.get(nodeA)?.get(nodeB);
|
||||
if (cached) {
|
||||
return cached;
|
||||
}
|
||||
const result = compareNodesUncached(nodeA, nodeB);
|
||||
let mapA = COMPARE_NODES_CACHE.get(nodeA);
|
||||
if (mapA == null) {
|
||||
mapA = new WeakMap();
|
||||
COMPARE_NODES_CACHE.set(nodeA, mapA);
|
||||
}
|
||||
mapA.set(nodeB, result);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
declare function serializeValue(val: any, seen?: WeakMap<WeakKey, any>): any;
|
||||
|
||||
export { serializeValue };
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag use of with statement
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Disallow `with` statements",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-with",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
unexpectedWith: "Unexpected use of 'with' statement.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
WithStatement(node) {
|
||||
context.report({
|
||||
node,
|
||||
loc: sourceCode.getFirstToken(node).loc,
|
||||
messageId: "unexpectedWith",
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @fileoverview Rule to flag variable leak in CatchClauses in IE 8 and earlier
|
||||
* @author Ian Christian Myers
|
||||
* @deprecated in ESLint v5.1.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow `catch` clause parameters from shadowing variables in the outer scope",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-catch-shadow",
|
||||
},
|
||||
|
||||
deprecated: {
|
||||
message: "This rule was renamed.",
|
||||
url: "https://eslint.org/blog/2018/07/eslint-v5.1.0-released/",
|
||||
deprecatedSince: "5.1.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
rule: {
|
||||
name: "no-shadow",
|
||||
url: "https://eslint.org/docs/rules/no-shadow",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
mutable:
|
||||
"Value of '{{name}}' may be overwritten in IE 8 and earlier.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Check if the parameters are been shadowed
|
||||
* @param {Object} scope current scope
|
||||
* @param {string} name parameter name
|
||||
* @returns {boolean} True is its been shadowed
|
||||
*/
|
||||
function paramIsShadowing(scope, name) {
|
||||
return astUtils.getVariableByName(scope, name) !== null;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public API
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
"CatchClause[param!=null]"(node) {
|
||||
let scope = sourceCode.getScope(node);
|
||||
|
||||
/*
|
||||
* When ecmaVersion >= 6, CatchClause creates its own scope
|
||||
* so start from one upper scope to exclude the current node
|
||||
*/
|
||||
if (scope.block === node) {
|
||||
scope = scope.upper;
|
||||
}
|
||||
|
||||
if (paramIsShadowing(scope, node.param.name)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: "mutable",
|
||||
data: { name: node.param.name },
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,223 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
|
||||
/*
|
||||
* Browser-compatible JavaScript MD5
|
||||
*
|
||||
* Modification of JavaScript MD5
|
||||
* https://github.com/blueimp/JavaScript-MD5
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
* Based on
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* Digest Algorithm, as defined in RFC 1321.
|
||||
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info.
|
||||
*/
|
||||
function md5(bytes) {
|
||||
if (typeof bytes === 'string') {
|
||||
const msg = unescape(encodeURIComponent(bytes)); // UTF8 escape
|
||||
|
||||
bytes = new Uint8Array(msg.length);
|
||||
|
||||
for (let i = 0; i < msg.length; ++i) {
|
||||
bytes[i] = msg.charCodeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return md5ToHexEncodedArray(wordsToMd5(bytesToWords(bytes), bytes.length * 8));
|
||||
}
|
||||
/*
|
||||
* Convert an array of little-endian words to an array of bytes
|
||||
*/
|
||||
|
||||
|
||||
function md5ToHexEncodedArray(input) {
|
||||
const output = [];
|
||||
const length32 = input.length * 32;
|
||||
const hexTab = '0123456789abcdef';
|
||||
|
||||
for (let i = 0; i < length32; i += 8) {
|
||||
const x = input[i >> 5] >>> i % 32 & 0xff;
|
||||
const hex = parseInt(hexTab.charAt(x >>> 4 & 0x0f) + hexTab.charAt(x & 0x0f), 16);
|
||||
output.push(hex);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Calculate output length with padding and bit length
|
||||
*/
|
||||
|
||||
|
||||
function getOutputLength(inputLength8) {
|
||||
return (inputLength8 + 64 >>> 9 << 4) + 14 + 1;
|
||||
}
|
||||
/*
|
||||
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
||||
*/
|
||||
|
||||
|
||||
function wordsToMd5(x, len) {
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << len % 32;
|
||||
x[getOutputLength(len) - 1] = len;
|
||||
let a = 1732584193;
|
||||
let b = -271733879;
|
||||
let c = -1732584194;
|
||||
let d = 271733878;
|
||||
|
||||
for (let i = 0; i < x.length; i += 16) {
|
||||
const olda = a;
|
||||
const oldb = b;
|
||||
const oldc = c;
|
||||
const oldd = d;
|
||||
a = md5ff(a, b, c, d, x[i], 7, -680876936);
|
||||
d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);
|
||||
c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);
|
||||
b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);
|
||||
a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);
|
||||
d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);
|
||||
c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);
|
||||
b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);
|
||||
a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);
|
||||
d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);
|
||||
c = md5ff(c, d, a, b, x[i + 10], 17, -42063);
|
||||
b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);
|
||||
a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);
|
||||
d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);
|
||||
c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);
|
||||
b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);
|
||||
a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);
|
||||
d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);
|
||||
c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);
|
||||
b = md5gg(b, c, d, a, x[i], 20, -373897302);
|
||||
a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);
|
||||
d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);
|
||||
c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);
|
||||
b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);
|
||||
a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);
|
||||
d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);
|
||||
c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);
|
||||
b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);
|
||||
a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);
|
||||
d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);
|
||||
c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);
|
||||
b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);
|
||||
a = md5hh(a, b, c, d, x[i + 5], 4, -378558);
|
||||
d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);
|
||||
c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);
|
||||
b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);
|
||||
a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);
|
||||
d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);
|
||||
c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);
|
||||
b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);
|
||||
a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);
|
||||
d = md5hh(d, a, b, c, x[i], 11, -358537222);
|
||||
c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);
|
||||
b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);
|
||||
a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);
|
||||
d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);
|
||||
c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);
|
||||
b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);
|
||||
a = md5ii(a, b, c, d, x[i], 6, -198630844);
|
||||
d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);
|
||||
c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);
|
||||
b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);
|
||||
a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);
|
||||
d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);
|
||||
c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);
|
||||
b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);
|
||||
a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);
|
||||
d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);
|
||||
c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);
|
||||
b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);
|
||||
a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);
|
||||
d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);
|
||||
c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);
|
||||
b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);
|
||||
a = safeAdd(a, olda);
|
||||
b = safeAdd(b, oldb);
|
||||
c = safeAdd(c, oldc);
|
||||
d = safeAdd(d, oldd);
|
||||
}
|
||||
|
||||
return [a, b, c, d];
|
||||
}
|
||||
/*
|
||||
* Convert an array bytes to an array of little-endian words
|
||||
* Characters >255 have their high-byte silently ignored.
|
||||
*/
|
||||
|
||||
|
||||
function bytesToWords(input) {
|
||||
if (input.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const length8 = input.length * 8;
|
||||
const output = new Uint32Array(getOutputLength(length8));
|
||||
|
||||
for (let i = 0; i < length8; i += 8) {
|
||||
output[i >> 5] |= (input[i / 8] & 0xff) << i % 32;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
|
||||
|
||||
function safeAdd(x, y) {
|
||||
const lsw = (x & 0xffff) + (y & 0xffff);
|
||||
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return msw << 16 | lsw & 0xffff;
|
||||
}
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
|
||||
|
||||
function bitRotateLeft(num, cnt) {
|
||||
return num << cnt | num >>> 32 - cnt;
|
||||
}
|
||||
/*
|
||||
* These functions implement the four basic operations the algorithm uses.
|
||||
*/
|
||||
|
||||
|
||||
function md5cmn(q, a, b, x, s, t) {
|
||||
return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);
|
||||
}
|
||||
|
||||
function md5ff(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b & c | ~b & d, a, b, x, s, t);
|
||||
}
|
||||
|
||||
function md5gg(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b & d | c & ~d, a, b, x, s, t);
|
||||
}
|
||||
|
||||
function md5hh(a, b, c, d, x, s, t) {
|
||||
return md5cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
|
||||
function md5ii(a, b, c, d, x, s, t) {
|
||||
return md5cmn(c ^ (b | ~d), a, b, x, s, t);
|
||||
}
|
||||
|
||||
var _default = md5;
|
||||
exports.default = _default;
|
||||
@@ -0,0 +1,12 @@
|
||||
function _defineEnumerableProperties(e, r) {
|
||||
for (var t in r) {
|
||||
var n = r[t];
|
||||
n.configurable = n.enumerable = !0, "value" in n && (n.writable = !0), Object.defineProperty(e, t, n);
|
||||
}
|
||||
if (Object.getOwnPropertySymbols) for (var a = Object.getOwnPropertySymbols(r), b = 0; b < a.length; b++) {
|
||||
var i = a[b];
|
||||
(n = r[i]).configurable = n.enumerable = !0, "value" in n && (n.writable = !0), Object.defineProperty(e, i, n);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
module.exports = _defineEnumerableProperties, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
|
||||
export { SnapshotEnvironment } from '@vitest/snapshot/environment';
|
||||
|
||||
declare class VitestNodeSnapshotEnvironment extends NodeSnapshotEnvironment {
|
||||
getHeader(): string;
|
||||
resolvePath(filepath: string): Promise<string>;
|
||||
}
|
||||
|
||||
export { VitestNodeSnapshotEnvironment as VitestSnapshotEnvironment };
|
||||
@@ -0,0 +1,10 @@
|
||||
function _objectWithoutPropertiesLoose(r, e) {
|
||||
if (null == r) return {};
|
||||
var t = {};
|
||||
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
||||
if (-1 !== e.indexOf(n)) continue;
|
||||
t[n] = r[n];
|
||||
}
|
||||
return t;
|
||||
}
|
||||
module.exports = _objectWithoutPropertiesLoose, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,109 @@
|
||||
import * as util from "../core/util.js";
|
||||
const error = () => {
|
||||
const Sizable = {
|
||||
string: { unit: "χαρακτήρες", verb: "να έχει" },
|
||||
file: { unit: "bytes", verb: "να έχει" },
|
||||
array: { unit: "στοιχεία", verb: "να έχει" },
|
||||
set: { unit: "στοιχεία", verb: "να έχει" },
|
||||
map: { unit: "καταχωρήσεις", verb: "να έχει" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "είσοδος",
|
||||
email: "διεύθυνση email",
|
||||
url: "URL",
|
||||
emoji: "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",
|
||||
mac: "διεύθυνση MAC",
|
||||
cidrv4: "εύρος IPv4",
|
||||
cidrv6: "εύρος IPv6",
|
||||
base64: "συμβολοσειρά κωδικοποιημένη σε base64",
|
||||
base64url: "συμβολοσειρά κωδικοποιημένη σε base64url",
|
||||
json_string: "συμβολοσειρά JSON",
|
||||
e164: "αριθμός E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "είσοδος",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
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 (typeof issue.expected === "string" && /^[A-Z]/.test(issue.expected)) {
|
||||
return `Μη έγκυρη είσοδος: αναμενόταν instanceof ${issue.expected}, λήφθηκε ${received}`;
|
||||
}
|
||||
return `Μη έγκυρη είσοδος: αναμενόταν ${expected}, λήφθηκε ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Μη έγκυρη είσοδος: αναμενόταν ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Μη έγκυρη επιλογή: αναμενόταν ένα από ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Πολύ μεγάλο: αναμενόταν ${issue.origin ?? "τιμή"} να έχει ${adj}${issue.maximum.toString()} ${sizing.unit ?? "στοιχεία"}`;
|
||||
return `Πολύ μεγάλο: αναμενόταν ${issue.origin ?? "τιμή"} να είναι ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Πολύ μικρό: αναμενόταν ${issue.origin} να έχει ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `Πολύ μικρό: αναμενόταν ${issue.origin} να είναι ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with") {
|
||||
return `Μη έγκυρη συμβολοσειρά: πρέπει να ξεκινά με "${_issue.prefix}"`;
|
||||
}
|
||||
if (_issue.format === "ends_with")
|
||||
return `Μη έγκυρη συμβολοσειρά: πρέπει να τελειώνει με "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes")
|
||||
return `Μη έγκυρη συμβολοσειρά: πρέπει να περιέχει "${_issue.includes}"`;
|
||||
if (_issue.format === "regex")
|
||||
return `Μη έγκυρη συμβολοσειρά: πρέπει να ταιριάζει με το μοτίβο ${_issue.pattern}`;
|
||||
return `Μη έγκυρο: ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Μη έγκυρος αριθμός: πρέπει να είναι πολλαπλάσιο του ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Άγνωστ${issue.keys.length > 1 ? "α" : "ο"} κλειδ${issue.keys.length > 1 ? "ιά" : "ί"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Μη έγκυρο κλειδί στο ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Μη έγκυρη είσοδος";
|
||||
case "invalid_element":
|
||||
return `Μη έγκυρη τιμή στο ${issue.origin}`;
|
||||
default:
|
||||
return `Μη έγκυρη είσοδος`;
|
||||
}
|
||||
};
|
||||
};
|
||||
export default function () {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
var objToString = Object.prototype.toString;
|
||||
var objKeys = Object.keys || function(obj) {
|
||||
var keys = [];
|
||||
for (var name in obj) {
|
||||
keys.push(name);
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
|
||||
function stringify(val, isArrayProp) {
|
||||
var i, max, str, keys, key, propVal, toStr;
|
||||
if (val === true) {
|
||||
return "true";
|
||||
}
|
||||
if (val === false) {
|
||||
return "false";
|
||||
}
|
||||
switch (typeof val) {
|
||||
case "object":
|
||||
if (val === null) {
|
||||
return null;
|
||||
} else if (val.toJSON && typeof val.toJSON === "function") {
|
||||
return stringify(val.toJSON(), isArrayProp);
|
||||
} else {
|
||||
toStr = objToString.call(val);
|
||||
if (toStr === "[object Array]") {
|
||||
str = '[';
|
||||
max = val.length - 1;
|
||||
for(i = 0; i < max; i++) {
|
||||
str += stringify(val[i], true) + ',';
|
||||
}
|
||||
if (max > -1) {
|
||||
str += stringify(val[i], true);
|
||||
}
|
||||
return str + ']';
|
||||
} else if (toStr === "[object Object]") {
|
||||
// only object is left
|
||||
keys = objKeys(val).sort();
|
||||
max = keys.length;
|
||||
str = "";
|
||||
i = 0;
|
||||
while (i < max) {
|
||||
key = keys[i];
|
||||
propVal = stringify(val[key], false);
|
||||
if (propVal !== undefined) {
|
||||
if (str) {
|
||||
str += ',';
|
||||
}
|
||||
str += JSON.stringify(key) + ':' + propVal;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return '{' + str + '}';
|
||||
} else {
|
||||
return JSON.stringify(val);
|
||||
}
|
||||
}
|
||||
case "function":
|
||||
case "undefined":
|
||||
return isArrayProp ? null : undefined;
|
||||
case "string":
|
||||
return JSON.stringify(val);
|
||||
default:
|
||||
return isFinite(val) ? val : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(val) {
|
||||
var returnVal = stringify(val, false);
|
||||
if (returnVal !== undefined) {
|
||||
return ''+ returnVal;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,354 @@
|
||||
import type { ParserServices, TSESTree } from '../ts-estree';
|
||||
import type { Parser } from './Parser';
|
||||
import type { Scope } from './Scope';
|
||||
declare class TokenStore {
|
||||
/**
|
||||
* Checks whether any comments exist or not between the given 2 nodes.
|
||||
* @param left The node to check.
|
||||
* @param right The node to check.
|
||||
* @returns `true` if one or more comments exist.
|
||||
*/
|
||||
commentsExistBetween(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token): boolean;
|
||||
/**
|
||||
* Gets all comment tokens directly after the given node or token.
|
||||
* @param nodeOrToken The AST node or token to check for adjacent comment tokens.
|
||||
* @returns An array of comments in occurrence order.
|
||||
*/
|
||||
getCommentsAfter(nodeOrToken: TSESTree.Node | TSESTree.Token): TSESTree.Comment[];
|
||||
/**
|
||||
* Gets all comment tokens directly before the given node or token.
|
||||
* @param nodeOrToken The AST node or token to check for adjacent comment tokens.
|
||||
* @returns An array of comments in occurrence order.
|
||||
*/
|
||||
getCommentsBefore(nodeOrToken: TSESTree.Node | TSESTree.Token): TSESTree.Comment[];
|
||||
/**
|
||||
* Gets all comment tokens inside the given node.
|
||||
* @param node The AST node to get the comments for.
|
||||
* @returns An array of comments in occurrence order.
|
||||
*/
|
||||
getCommentsInside(node: TSESTree.Node): TSESTree.Comment[];
|
||||
/**
|
||||
* Gets the first token of the given node.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getFirstToken<T extends SourceCode.CursorWithSkipOptions>(node: TSESTree.Node, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the first token between two non-overlapping nodes.
|
||||
* @param left Node before the desired token range.
|
||||
* @param right Node after the desired token range.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getFirstTokenBetween<T extends SourceCode.CursorWithSkipOptions>(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the first `count` tokens of the given node.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
*/
|
||||
getFirstTokens<T extends SourceCode.CursorWithCountOptions>(node: TSESTree.Node, options?: T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the first `count` tokens between two non-overlapping nodes.
|
||||
* @param left Node before the desired token range.
|
||||
* @param right Node after the desired token range.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
* @returns Tokens between left and right.
|
||||
*/
|
||||
getFirstTokensBetween<T extends SourceCode.CursorWithCountOptions>(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the last token of the given node.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getLastToken<T extends SourceCode.CursorWithSkipOptions>(node: TSESTree.Node, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the last token between two non-overlapping nodes.
|
||||
* @param left Node before the desired token range.
|
||||
* @param right Node after the desired token range.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getLastTokenBetween<T extends SourceCode.CursorWithSkipOptions>(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the last `count` tokens of the given node.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
*/
|
||||
getLastTokens<T extends SourceCode.CursorWithCountOptions>(node: TSESTree.Node, options?: T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the last `count` tokens between two non-overlapping nodes.
|
||||
* @param left Node before the desired token range.
|
||||
* @param right Node after the desired token range.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
* @returns Tokens between left and right.
|
||||
*/
|
||||
getLastTokensBetween<T extends SourceCode.CursorWithCountOptions>(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the token that follows a given node or token.
|
||||
* @param node The AST node or token.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getTokenAfter<T extends SourceCode.CursorWithSkipOptions>(node: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the token that precedes a given node or token.
|
||||
* @param node The AST node or token.
|
||||
* @param options The option object
|
||||
* @returns An object representing the token.
|
||||
*/
|
||||
getTokenBefore<T extends SourceCode.CursorWithSkipOptions>(node: TSESTree.Node | TSESTree.Token, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets the token starting at the specified index.
|
||||
* @param offset Index of the start of the token's range.
|
||||
* @param options The option object. If this is a number then it's `options.skip`. If this is a function then it's `options.filter`.
|
||||
* @returns The token starting at index, or null if no such token.
|
||||
*/
|
||||
getTokenByRangeStart<T extends {
|
||||
includeComments?: boolean;
|
||||
}>(offset: number, options?: T): SourceCode.ReturnTypeFromOptions<T> | null;
|
||||
/**
|
||||
* Gets all tokens that are related to the given node.
|
||||
* @param node The AST node.
|
||||
* @param beforeCount The number of tokens before the node to retrieve.
|
||||
* @param afterCount The number of tokens after the node to retrieve.
|
||||
* @returns Array of objects representing tokens.
|
||||
*/
|
||||
getTokens(node: TSESTree.Node, beforeCount?: number, afterCount?: number): TSESTree.Token[];
|
||||
/**
|
||||
* Gets all tokens that are related to the given node.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a function then it's `options.filter`.
|
||||
* @returns Array of objects representing tokens.
|
||||
*/
|
||||
getTokens<T extends SourceCode.CursorWithCountOptions>(node: TSESTree.Node, options: T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the `count` tokens that follows a given node or token.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
*/
|
||||
getTokensAfter<T extends SourceCode.CursorWithCountOptions>(node: TSESTree.Node | TSESTree.Token, options?: number | T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets the `count` tokens that precedes a given node or token.
|
||||
* @param node The AST node.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
*/
|
||||
getTokensBefore<T extends SourceCode.CursorWithCountOptions>(node: TSESTree.Node | TSESTree.Token, options?: number | T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
/**
|
||||
* Gets all of the tokens between two non-overlapping nodes.
|
||||
* @param left Node before the desired token range.
|
||||
* @param right Node after the desired token range.
|
||||
* @param options The option object. If this is a number then it's `options.count`. If this is a function then it's `options.filter`.
|
||||
* @returns Tokens between left and right.
|
||||
*/
|
||||
getTokensBetween<T extends SourceCode.CursorWithCountOptions>(left: TSESTree.Node | TSESTree.Token, right: TSESTree.Node | TSESTree.Token, options?: number | T): SourceCode.ReturnTypeFromOptions<T>[];
|
||||
}
|
||||
declare class SourceCodeBase extends TokenStore {
|
||||
/**
|
||||
* Represents parsed source code.
|
||||
* @param ast The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
|
||||
*/
|
||||
constructor(text: string, ast: SourceCode.Program);
|
||||
/**
|
||||
* Represents parsed source code.
|
||||
* @param config The config object.
|
||||
*/
|
||||
constructor(config: SourceCode.SourceCodeConfig);
|
||||
/**
|
||||
* The parsed AST for the source code.
|
||||
*/
|
||||
ast: SourceCode.Program;
|
||||
applyInlineConfig(): void;
|
||||
applyLanguageOptions(): void;
|
||||
finalize(): void;
|
||||
/**
|
||||
* Retrieves an array containing all comments in the source code.
|
||||
* @returns An array of comment nodes.
|
||||
*/
|
||||
getAllComments(): TSESTree.Comment[];
|
||||
/**
|
||||
* Converts a (line, column) pair into a range index.
|
||||
* @param location A line/column location
|
||||
* @returns The range index of the location in the file.
|
||||
*/
|
||||
getIndexFromLoc(location: TSESTree.Position): number;
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns The source text as an array of lines.
|
||||
*/
|
||||
getLines(): string[];
|
||||
/**
|
||||
* Converts a source text index into a (line, column) pair.
|
||||
* @param index The index of a character in a file
|
||||
* @returns A {line, column} location object with a 0-indexed column
|
||||
*/
|
||||
getLocFromIndex(index: number): TSESTree.Position;
|
||||
/**
|
||||
* Gets the deepest node containing a range index.
|
||||
* @param index Range index of the desired node.
|
||||
* @returns The node if found or `null` if not found.
|
||||
*/
|
||||
getNodeByRangeIndex(index: number): TSESTree.Node | null;
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param node The AST node to get the text for.
|
||||
* @param beforeCount The number of characters before the node to retrieve.
|
||||
* @param afterCount The number of characters after the node to retrieve.
|
||||
* @returns The text representing the AST node.
|
||||
*/
|
||||
getText(node?: TSESTree.Node | TSESTree.Token, beforeCount?: number, afterCount?: number): string;
|
||||
/**
|
||||
* The flag to indicate that the source code has Unicode BOM.
|
||||
*/
|
||||
hasBOM: boolean;
|
||||
/**
|
||||
* Determines if two nodes or tokens have at least one whitespace character
|
||||
* between them. Order does not matter. Returns false if the given nodes or
|
||||
* tokens overlap.
|
||||
* @param first The first node or token to check between.
|
||||
* @param second The second node or token to check between.
|
||||
* @returns True if there is a whitespace character between any of the tokens found between the two given nodes or tokens.
|
||||
*/
|
||||
isSpaceBetween(first: TSESTree.Node | TSESTree.Token, second: TSESTree.Node | TSESTree.Token): boolean;
|
||||
/**
|
||||
* Determines if two nodes or tokens have at least one whitespace character
|
||||
* between them. Order does not matter. Returns false if the given nodes or
|
||||
* tokens overlap.
|
||||
* For backward compatibility, this method returns true if there are
|
||||
* `JSXText` tokens that contain whitespace between the two.
|
||||
* @param first The first node or token to check between.
|
||||
* @param second The second node or token to check between.
|
||||
* @returns {boolean} True if there is a whitespace character between
|
||||
* any of the tokens found between the two given nodes or tokens.
|
||||
* @deprecated in favor of isSpaceBetween
|
||||
*/
|
||||
isSpaceBetweenTokens(first: TSESTree.Token, second: TSESTree.Token): boolean;
|
||||
/**
|
||||
* Returns the scope of the given node.
|
||||
* This information can be used track references to variables.
|
||||
*/
|
||||
getScope(node: TSESTree.Node): Scope.Scope;
|
||||
/**
|
||||
* Returns an array of the ancestors of the given node, starting at
|
||||
* the root of the AST and continuing through the direct parent of the current node.
|
||||
* This array does not include the currently-traversed node itself.
|
||||
*/
|
||||
getAncestors(node: TSESTree.Node): TSESTree.Node[];
|
||||
/**
|
||||
* Returns a list of variables declared by the given node.
|
||||
* This information can be used to track references to variables.
|
||||
*/
|
||||
getDeclaredVariables(node: TSESTree.Node): readonly Scope.Variable[];
|
||||
/**
|
||||
* Marks a variable with the given name in the current scope as used.
|
||||
* This affects the no-unused-vars rule.
|
||||
*/
|
||||
markVariableAsUsed(name: string, node: TSESTree.Node): boolean;
|
||||
/**
|
||||
* The source code split into lines according to ECMA-262 specification.
|
||||
* This is done to avoid each rule needing to do so separately.
|
||||
*/
|
||||
lines: string[];
|
||||
/**
|
||||
* The indexes in `text` that each line starts
|
||||
*/
|
||||
lineStartIndices: number[];
|
||||
/**
|
||||
* The parser services of this source code.
|
||||
*/
|
||||
parserServices?: Partial<ParserServices>;
|
||||
/**
|
||||
* The scope of this source code.
|
||||
*/
|
||||
scopeManager: Scope.ScopeManager | null;
|
||||
/**
|
||||
* The original text source code. BOM was stripped from this text.
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* All of the tokens and comments in the AST.
|
||||
*
|
||||
* TODO: rename to 'tokens'
|
||||
*/
|
||||
tokensAndComments: TSESTree.Token[];
|
||||
/**
|
||||
* The visitor keys to traverse AST.
|
||||
*/
|
||||
visitorKeys: SourceCode.VisitorKeys;
|
||||
/**
|
||||
* Split the source code into multiple lines based on the line delimiters.
|
||||
* @param text Source code as a string.
|
||||
* @returns Array of source code lines.
|
||||
*/
|
||||
static splitLines(text: string): string[];
|
||||
}
|
||||
declare namespace SourceCode {
|
||||
interface Program extends TSESTree.Program {
|
||||
comments: TSESTree.Comment[];
|
||||
tokens: TSESTree.Token[];
|
||||
}
|
||||
interface SourceCodeConfig {
|
||||
/**
|
||||
* The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
|
||||
*/
|
||||
ast: Program;
|
||||
/**
|
||||
* The parser services.
|
||||
*/
|
||||
parserServices: ParserServices | null;
|
||||
/**
|
||||
* The scope of this source code.
|
||||
*/
|
||||
scopeManager: Scope.ScopeManager | null;
|
||||
/**
|
||||
* The source code text.
|
||||
*/
|
||||
text: string;
|
||||
/**
|
||||
* The visitor keys to traverse AST.
|
||||
*/
|
||||
visitorKeys: VisitorKeys | null;
|
||||
}
|
||||
type VisitorKeys = Parser.VisitorKeys;
|
||||
type FilterPredicate = (token: TSESTree.Token) => boolean;
|
||||
type GetFilterPredicate<Filter, Default> = Filter extends ((token: TSESTree.Token) => token is infer U extends TSESTree.Token) ? U : Default;
|
||||
type GetFilterPredicateFromOptions<Options, Default> = Options extends {
|
||||
filter?: FilterPredicate;
|
||||
} ? GetFilterPredicate<Options['filter'], Default> : GetFilterPredicate<Options, Default>;
|
||||
type ReturnTypeFromOptions<T> = T extends {
|
||||
includeComments: true;
|
||||
} ? GetFilterPredicateFromOptions<T, TSESTree.Token> : GetFilterPredicateFromOptions<T, Exclude<TSESTree.Token, TSESTree.Comment>>;
|
||||
type CursorWithSkipOptions = number | FilterPredicate | {
|
||||
/**
|
||||
* The predicate function to choose tokens.
|
||||
*/
|
||||
filter?: FilterPredicate;
|
||||
/**
|
||||
* The flag to iterate comments as well.
|
||||
*/
|
||||
includeComments?: boolean;
|
||||
/**
|
||||
* The count of tokens the cursor skips.
|
||||
*/
|
||||
skip?: number;
|
||||
};
|
||||
type CursorWithCountOptions = number | FilterPredicate | {
|
||||
/**
|
||||
* The maximum count of tokens the cursor iterates.
|
||||
*/
|
||||
count?: number;
|
||||
/**
|
||||
* The predicate function to choose tokens.
|
||||
*/
|
||||
filter?: FilterPredicate;
|
||||
/**
|
||||
* The flag to iterate comments as well.
|
||||
*/
|
||||
includeComments?: boolean;
|
||||
};
|
||||
}
|
||||
declare const SourceCode_base: typeof SourceCodeBase;
|
||||
declare class SourceCode extends SourceCode_base {
|
||||
}
|
||||
export { SourceCode };
|
||||
@@ -0,0 +1,12 @@
|
||||
# `@typescript-eslint/types`
|
||||
|
||||
> Types for the TypeScript-ESTree AST spec
|
||||
|
||||
This package exists to help us reduce cycles and provide lighter-weight packages at runtime.
|
||||
|
||||
## ✋ Internal Package
|
||||
|
||||
This is an _internal package_ to the [typescript-eslint monorepo](https://github.com/typescript-eslint/typescript-eslint).
|
||||
You likely don't want to use it directly.
|
||||
|
||||
👉 See **https://typescript-eslint.io** for docs on typescript-eslint.
|
||||
@@ -0,0 +1,189 @@
|
||||
import * as ts from 'typescript';
|
||||
import type { TSESTree } from './ts-estree';
|
||||
import { AST_NODE_TYPES, AST_TOKEN_TYPES } from './ts-estree';
|
||||
declare const SyntaxKind: typeof ts.SyntaxKind;
|
||||
type LogicalOperatorKind = ts.SyntaxKind.AmpersandAmpersandToken | ts.SyntaxKind.BarBarToken | ts.SyntaxKind.QuestionQuestionToken;
|
||||
interface TokenToText extends TSESTree.PunctuatorTokenToText, TSESTree.BinaryOperatorToText {
|
||||
[SyntaxKind.ImportKeyword]: 'import';
|
||||
[SyntaxKind.KeyOfKeyword]: 'keyof';
|
||||
[SyntaxKind.NewKeyword]: 'new';
|
||||
[SyntaxKind.ReadonlyKeyword]: 'readonly';
|
||||
[SyntaxKind.UniqueKeyword]: 'unique';
|
||||
}
|
||||
type AssignmentOperatorKind = keyof TSESTree.AssignmentOperatorToText;
|
||||
type BinaryOperatorKind = keyof TSESTree.BinaryOperatorToText;
|
||||
type DeclarationKind = TSESTree.VariableDeclaration['kind'];
|
||||
/**
|
||||
* Returns true if the given ts.Token is a logical operator
|
||||
*/
|
||||
export declare function isLogicalOperator(operator: ts.BinaryOperatorToken): operator is ts.Token<LogicalOperatorKind>;
|
||||
export declare function isESTreeBinaryOperator(operator: ts.BinaryOperatorToken): operator is ts.Token<BinaryOperatorKind>;
|
||||
type TokenForTokenKind<T extends ts.SyntaxKind> = T extends keyof TokenToText ? TokenToText[T] : string | undefined;
|
||||
/**
|
||||
* Returns the string form of the given TSToken SyntaxKind
|
||||
*/
|
||||
export declare function getTextForTokenKind<T extends ts.SyntaxKind>(kind: T): TokenForTokenKind<T>;
|
||||
/**
|
||||
* Returns true if the given ts.Node is a valid ESTree class member
|
||||
*/
|
||||
export declare function isESTreeClassMember(node: ts.Node): boolean;
|
||||
/**
|
||||
* Checks if a ts.Node has a modifier
|
||||
*/
|
||||
export declare function hasModifier(modifierKind: ts.KeywordSyntaxKind, node: ts.Node): boolean;
|
||||
/**
|
||||
* Get last last modifier in ast
|
||||
* @returns returns last modifier if present or null
|
||||
*/
|
||||
export declare function getLastModifier(node: ts.Node): ts.Modifier | null;
|
||||
/**
|
||||
* Returns true if the given ts.Token is a comma
|
||||
*/
|
||||
export declare function isComma(token: ts.Node): token is ts.Token<ts.SyntaxKind.CommaToken>;
|
||||
/**
|
||||
* Returns true if the given ts.Node is a comment
|
||||
*/
|
||||
export declare function isComment(node: ts.Node): boolean;
|
||||
/**
|
||||
* Returns the binary expression type of the given ts.Token
|
||||
*/
|
||||
export declare function getBinaryExpressionType(operator: ts.BinaryOperatorToken): {
|
||||
operator: TokenForTokenKind<AssignmentOperatorKind>;
|
||||
type: AST_NODE_TYPES.AssignmentExpression;
|
||||
} | {
|
||||
operator: TokenForTokenKind<BinaryOperatorKind>;
|
||||
type: AST_NODE_TYPES.BinaryExpression;
|
||||
} | {
|
||||
operator: TokenForTokenKind<LogicalOperatorKind>;
|
||||
type: AST_NODE_TYPES.LogicalExpression;
|
||||
};
|
||||
/**
|
||||
* Returns line and column data for the given positions
|
||||
*/
|
||||
export declare function getLineAndCharacterFor(pos: number, ast: ts.SourceFile): TSESTree.Position;
|
||||
/**
|
||||
* Returns line and column data for the given start and end positions,
|
||||
* for the given AST
|
||||
*/
|
||||
export declare function getLocFor(range: TSESTree.Range, ast: ts.SourceFile): TSESTree.SourceLocation;
|
||||
/**
|
||||
* Check whatever node can contain directive
|
||||
*/
|
||||
export declare function canContainDirective(node: ts.Block | ts.ClassStaticBlockDeclaration | ts.ModuleBlock | ts.SourceFile): boolean;
|
||||
/**
|
||||
* Returns range for the given ts.Node
|
||||
*/
|
||||
export declare function getRange(node: Pick<ts.Node, 'getEnd' | 'getStart'>, ast: ts.SourceFile): [number, number];
|
||||
/**
|
||||
* Returns true if a given ts.Node is a JSX token
|
||||
*/
|
||||
export declare function isJSXToken(node: ts.Node): boolean;
|
||||
/**
|
||||
* Returns the declaration kind of the given ts.Node
|
||||
*/
|
||||
export declare function getDeclarationKind(node: ts.VariableDeclarationList): DeclarationKind;
|
||||
/**
|
||||
* Gets a ts.Node's accessibility level
|
||||
*/
|
||||
export declare function getTSNodeAccessibility(node: ts.Node): 'private' | 'protected' | 'public' | undefined;
|
||||
/**
|
||||
* Finds the next token based on the previous one and its parent
|
||||
* Had to copy this from TS instead of using TS's version because theirs doesn't pass the ast to getChildren
|
||||
*/
|
||||
export declare function findNextToken(previousToken: ts.TextRange, parent: ts.Node, ast: ts.SourceFile): ts.Node | undefined;
|
||||
/**
|
||||
* Find the first matching ancestor based on the given predicate function.
|
||||
* @param node The current ts.Node
|
||||
* @param predicate The predicate function to apply to each checked ancestor
|
||||
* @returns a matching parent ts.Node
|
||||
*/
|
||||
export declare function findFirstMatchingAncestor(node: ts.Node, predicate: (node: ts.Node) => boolean): ts.Node | undefined;
|
||||
/**
|
||||
* Returns true if a given ts.Node has a JSX token within its hierarchy
|
||||
*/
|
||||
export declare function hasJSXAncestor(node: ts.Node): boolean;
|
||||
/**
|
||||
* Unescape the text content of string literals, e.g. & -> &
|
||||
* @param text The escaped string literal text.
|
||||
* @returns The unescaped string literal text.
|
||||
*/
|
||||
export declare function unescapeStringLiteralText(text: string): string;
|
||||
/**
|
||||
* Returns true if a given ts.Node is a computed property
|
||||
*/
|
||||
export declare function isComputedProperty(node: ts.Node): node is ts.ComputedPropertyName;
|
||||
/**
|
||||
* Returns true if a given ts.Node is optional (has QuestionToken)
|
||||
* @param node ts.Node to be checked
|
||||
*/
|
||||
export declare function isOptional(node: {
|
||||
questionToken?: ts.QuestionToken;
|
||||
}): boolean;
|
||||
/**
|
||||
* Returns true if the node is an optional chain node
|
||||
*/
|
||||
export declare function isChainExpression(node: TSESTree.Node): node is TSESTree.ChainExpression;
|
||||
/**
|
||||
* Returns true of the child of property access expression is an optional chain
|
||||
*/
|
||||
export declare function isChildUnwrappableOptionalChain(node: ts.CallExpression | ts.ElementAccessExpression | ts.NonNullExpression | ts.PropertyAccessExpression, child: TSESTree.Node): boolean;
|
||||
/**
|
||||
* Returns the type of a given ts.Token
|
||||
*/
|
||||
export declare function getTokenType(token: ts.Identifier | ts.Token<ts.SyntaxKind>): Exclude<AST_TOKEN_TYPES, AST_TOKEN_TYPES.Block | AST_TOKEN_TYPES.Line>;
|
||||
/**
|
||||
* Extends and formats a given ts.Token, for a given AST
|
||||
*/
|
||||
export declare function convertToken(token: ts.Token<ts.TokenSyntaxKind>, ast: ts.SourceFile): TSESTree.Token;
|
||||
/**
|
||||
* Converts all tokens for the given AST
|
||||
* @param ast the AST object
|
||||
* @returns the converted Tokens
|
||||
*/
|
||||
export declare function convertTokens(ast: ts.SourceFile): TSESTree.Token[];
|
||||
export declare class TSError extends Error {
|
||||
readonly fileName: string;
|
||||
readonly location: {
|
||||
end: {
|
||||
column: number;
|
||||
line: number;
|
||||
offset: number;
|
||||
};
|
||||
start: {
|
||||
column: number;
|
||||
line: number;
|
||||
offset: number;
|
||||
};
|
||||
};
|
||||
name: string;
|
||||
constructor(message: string, fileName: string, location: {
|
||||
end: {
|
||||
column: number;
|
||||
line: number;
|
||||
offset: number;
|
||||
};
|
||||
start: {
|
||||
column: number;
|
||||
line: number;
|
||||
offset: number;
|
||||
};
|
||||
});
|
||||
get index(): number;
|
||||
get lineNumber(): number;
|
||||
get column(): number;
|
||||
}
|
||||
export declare function createError(node: ts.Node, message: string): TSError;
|
||||
export declare function createError(node: number | ts.Node | TSESTree.Range, message: string, sourceFile: ts.SourceFile): TSError;
|
||||
export declare function nodeHasTokens(n: ts.Node, ast: ts.SourceFile): boolean;
|
||||
/**
|
||||
* Like `forEach`, but suitable for use with numbers and strings (which may be falsy).
|
||||
*/
|
||||
export declare function firstDefined<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined;
|
||||
export declare function identifierIsThisKeyword(id: ts.Identifier): boolean;
|
||||
export declare function isThisIdentifier(node: ts.Node | undefined): node is ts.Identifier;
|
||||
export declare function isThisInTypeQuery(node: ts.Node): boolean;
|
||||
export declare function isValidAssignmentTarget(node: ts.Node): boolean;
|
||||
export declare function getNamespaceModifiers(node: ts.ModuleDeclaration): ts.Modifier[] | undefined;
|
||||
export declare function declarationNameToString(node: ts.Node): string;
|
||||
export declare function isEntityNameExpression(node: ts.Node): node is ts.EntityNameExpression;
|
||||
export {};
|
||||
@@ -0,0 +1,21 @@
|
||||
/*! *****************************************************************************
|
||||
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,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
/// <reference no-default-lib="true"/>
|
||||
|
||||
/// <reference lib="es2015" />
|
||||
/// <reference lib="es2016.array.include" />
|
||||
/// <reference lib="es2016.intl" />
|
||||
@@ -0,0 +1,86 @@
|
||||
# Pino Ecosystem
|
||||
|
||||
This is a list of ecosystem modules that integrate with `pino`.
|
||||
|
||||
Modules listed under [Core](#core) are maintained by the Pino team. Modules
|
||||
listed under [Community](#community) are maintained by independent community
|
||||
members.
|
||||
|
||||
Please send a PR to add new modules!
|
||||
|
||||
<a id="core"></a>
|
||||
## Core
|
||||
|
||||
### Frameworks
|
||||
+ [`express-pino-logger`](https://github.com/pinojs/express-pino-logger): use
|
||||
Pino to log requests within [express](https://expressjs.com/).
|
||||
+ [`koa-pino-logger`](https://github.com/pinojs/koa-pino-logger): use Pino to
|
||||
log requests within [Koa](https://koajs.com/).
|
||||
+ [`restify-pino-logger`](https://github.com/pinojs/restify-pino-logger): use
|
||||
Pino to log requests within [restify](http://restify.com/).
|
||||
+ [`rill-pino-logger`](https://github.com/pinojs/rill-pino-logger): use Pino as
|
||||
the logger for the [Rill framework](https://rill.site/).
|
||||
|
||||
### Utilities
|
||||
+ [`pino-arborsculpture`](https://github.com/pinojs/pino-arborsculpture): change
|
||||
log levels at runtime.
|
||||
+ [`pino-caller`](https://github.com/pinojs/pino-caller): add callsite to the log line.
|
||||
+ [`pino-clf`](https://github.com/pinojs/pino-clf): reformat Pino logs into
|
||||
Common Log Format.
|
||||
+ [`pino-console`](https://github.com/pinojs/pino-console): adapter for the [WHATWG Console](https://console.spec.whatwg.org/) spec.
|
||||
+ [`pino-debug`](https://github.com/pinojs/pino-debug): use Pino to interpret
|
||||
[`debug`](https://npm.im/debug) logs.
|
||||
+ [`pino-elasticsearch`](https://github.com/pinojs/pino-elasticsearch): send
|
||||
Pino logs to an Elasticsearch instance.
|
||||
+ [`pino-eventhub`](https://github.com/pinojs/pino-eventhub): send Pino logs
|
||||
to an [Event Hub](https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-what-is-event-hubs).
|
||||
+ [`pino-filter`](https://github.com/pinojs/pino-filter): filter Pino logs in
|
||||
the same fashion as the [`debug`](https://npm.im/debug) module.
|
||||
+ [`pino-gelf`](https://github.com/pinojs/pino-gelf): reformat Pino logs into
|
||||
GELF format for Graylog.
|
||||
+ [`pino-hapi`](https://github.com/pinojs/hapi-pino): use Pino as the logger
|
||||
for [Hapi](https://hapijs.com/).
|
||||
+ [`pino-http`](https://github.com/pinojs/pino-http): easily use Pino to log
|
||||
requests with the core `http` module.
|
||||
+ [`pino-http-print`](https://github.com/pinojs/pino-http-print): reformat Pino
|
||||
logs into traditional [HTTPD](https://httpd.apache.org/) style request logs.
|
||||
+ [`pino-mongodb`](https://github.com/pinojs/pino-mongodb): store Pino logs
|
||||
in a MongoDB database.
|
||||
+ [`pino-multi-stream`](https://github.com/pinojs/pino-multi-stream): send
|
||||
logs to multiple destination streams (slow!).
|
||||
+ [`pino-noir`](https://github.com/pinojs/pino-noir): redact sensitive information
|
||||
in logs.
|
||||
+ [`pino-pretty`](https://github.com/pinojs/pino-pretty): basic prettifier to
|
||||
make log lines human-readable.
|
||||
+ [`pino-socket`](https://github.com/pinojs/pino-socket): send logs to TCP or UDP
|
||||
destinations.
|
||||
+ [`pino-std-serializers`](https://github.com/pinojs/pino-std-serializers): the
|
||||
core object serializers used within Pino.
|
||||
+ [`pino-syslog`](https://github.com/pinojs/pino-syslog): reformat Pino logs
|
||||
to standard syslog format.
|
||||
+ [`pino-tee`](https://github.com/pinojs/pino-tee): pipe Pino logs into files
|
||||
based upon log levels.
|
||||
+ [`pino-test`](https://github.com/pinojs/pino-test): a set of utilities for
|
||||
verifying logs generated by the Pino logger.
|
||||
+ [`pino-toke`](https://github.com/pinojs/pino-toke): reformat Pino logs
|
||||
according to a given format string.
|
||||
|
||||
|
||||
<a id="community"></a>
|
||||
## Community
|
||||
|
||||
+ [`@google-cloud/pino-logging-gcp-config`](https://www.npmjs.com/package/@google-cloud/pino-logging-gcp-config): Config helper and formatter to output [Google Cloud Platform Structured Logging](https://cloud.google.com/logging/docs/structured-logging)
|
||||
+ [`@newrelic/pino-enricher`](https://github.com/newrelic/newrelic-node-log-extensions/blob/main/packages/pino-log-enricher): a log customization to add New Relic context to use [Logs In Context](https://docs.newrelic.com/docs/logs/logs-context/logs-in-context/)
|
||||
+ [`cloud-pine`](https://github.com/metcoder95/cloud-pine): transport that provides abstraction and compatibility with [`@google-cloud/logging`](https://www.npmjs.com/package/@google-cloud/logging).
|
||||
+ [`cls-proxify`](https://github.com/keenondrums/cls-proxify): integration of pino and [CLS](https://github.com/jeff-lewis/cls-hooked). Useful for creating dynamically configured child loggers (e.g. with added trace ID) for each request.
|
||||
+ [`crawlee-pino`](https://github.com/imyelo/crawlee-pino): use Pino to log within Crawlee
|
||||
+ [`eslint-plugin-pino`](https://github.com/orzarchi/eslint-plugin-pino): linting rules for pino usage, primarly for preventing missing context in logs due to incorrect argument order.
|
||||
+ [`pino-colada`](https://github.com/lrlna/pino-colada): cute ndjson formatter for pino.
|
||||
+ [`pino-dev`](https://github.com/dnjstrom/pino-dev): simple prettifier for pino with built-in support for common ecosystem packages.
|
||||
+ [`pino-fluentd`](https://github.com/davidedantonio/pino-fluentd): send Pino logs to Elasticsearch,
|
||||
MongoDB, and many [others](https://www.fluentd.org/dataoutputs) via Fluentd.
|
||||
+ [`pino-lambda`](https://github.com/FormidableLabs/pino-lambda): log transport for cloudwatch support inside aws-lambda
|
||||
+ [`pino-pretty-min`](https://github.com/unjello/pino-pretty-min): a minimal
|
||||
prettifier inspired by the [logrus](https://github.com/sirupsen/logrus) logger.
|
||||
+ [`pino-rotating-file`](https://github.com/homeaway/pino-rotating-file): a hapi-pino log transport for splitting logs into separate, automatically rotating files.
|
||||
+ [`pino-tiny`](https://github.com/holmok/pino-tiny): a tiny (and extensible?) little log formatter for pino.
|
||||
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isReferenceToGlobalFunction = isReferenceToGlobalFunction;
|
||||
function isReferenceToGlobalFunction(calleeName, node, sourceCode) {
|
||||
const ref = sourceCode
|
||||
.getScope(node)
|
||||
.references.find(ref => ref.identifier.name === calleeName);
|
||||
// ensure it's the "global" version
|
||||
return !ref?.resolved?.defs.length;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.skipChainExpression = skipChainExpression;
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
function skipChainExpression(node) {
|
||||
return node.type === utils_1.AST_NODE_TYPES.ChainExpression ? node.expression : node;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# vitest
|
||||
|
||||
[](https://npmx.dev/package/vitest)
|
||||
|
||||
Next generation testing framework powered by Vite.
|
||||
|
||||
[GitHub](https://github.com/vitest-dev/vitest) | [Documentation](https://vitest.dev/)
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_class_static_private_field_spec_set.js";
|
||||
@@ -0,0 +1,162 @@
|
||||
import Benchmark from "benchmark";
|
||||
|
||||
import { z } from "zod/v3";
|
||||
import { Mocker } from "../tests/Mocker.js";
|
||||
|
||||
const val = new Mocker();
|
||||
|
||||
const enumSuite = new Benchmark.Suite("z.enum");
|
||||
const enumSchema = z.enum(["a", "b", "c"]);
|
||||
|
||||
enumSuite
|
||||
.add("valid", () => {
|
||||
enumSchema.parse("a");
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
enumSchema.parse("x");
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.enum: ${e.target}`);
|
||||
});
|
||||
|
||||
const longEnumSuite = new Benchmark.Suite("long z.enum");
|
||||
const longEnumSchema = z.enum([
|
||||
"one",
|
||||
"two",
|
||||
"three",
|
||||
"four",
|
||||
"five",
|
||||
"six",
|
||||
"seven",
|
||||
"eight",
|
||||
"nine",
|
||||
"ten",
|
||||
"eleven",
|
||||
"twelve",
|
||||
"thirteen",
|
||||
"fourteen",
|
||||
"fifteen",
|
||||
"sixteen",
|
||||
"seventeen",
|
||||
]);
|
||||
|
||||
longEnumSuite
|
||||
.add("valid", () => {
|
||||
longEnumSchema.parse("five");
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
longEnumSchema.parse("invalid");
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`long z.enum: ${e.target}`);
|
||||
});
|
||||
|
||||
const undefinedSuite = new Benchmark.Suite("z.undefined");
|
||||
const undefinedSchema = z.undefined();
|
||||
|
||||
undefinedSuite
|
||||
.add("valid", () => {
|
||||
undefinedSchema.parse(undefined);
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
undefinedSchema.parse(1);
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.undefined: ${e.target}`);
|
||||
});
|
||||
|
||||
const literalSuite = new Benchmark.Suite("z.literal");
|
||||
const short = "short";
|
||||
const bad = "bad";
|
||||
const literalSchema = z.literal("short");
|
||||
|
||||
literalSuite
|
||||
.add("valid", () => {
|
||||
literalSchema.parse(short);
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
literalSchema.parse(bad);
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.literal: ${e.target}`);
|
||||
});
|
||||
|
||||
const numberSuite = new Benchmark.Suite("z.number");
|
||||
const numberSchema = z.number().int();
|
||||
|
||||
numberSuite
|
||||
.add("valid", () => {
|
||||
numberSchema.parse(1);
|
||||
})
|
||||
.add("invalid type", () => {
|
||||
try {
|
||||
numberSchema.parse("bad");
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.add("invalid number", () => {
|
||||
try {
|
||||
numberSchema.parse(0.5);
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.number: ${e.target}`);
|
||||
});
|
||||
|
||||
const dateSuite = new Benchmark.Suite("z.date");
|
||||
|
||||
const plainDate = z.date();
|
||||
const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01"));
|
||||
|
||||
dateSuite
|
||||
.add("valid", () => {
|
||||
plainDate.parse(new Date());
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
plainDate.parse(1);
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.add("valid min and max", () => {
|
||||
minMaxDate.parse(new Date("2023-01-01"));
|
||||
})
|
||||
.add("invalid min", () => {
|
||||
try {
|
||||
minMaxDate.parse(new Date("2019-01-01"));
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.add("invalid max", () => {
|
||||
try {
|
||||
minMaxDate.parse(new Date("2031-01-01"));
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.date: ${e.target}`);
|
||||
});
|
||||
|
||||
const symbolSuite = new Benchmark.Suite("z.symbol");
|
||||
const symbolSchema = z.symbol();
|
||||
|
||||
symbolSuite
|
||||
.add("valid", () => {
|
||||
symbolSchema.parse(val.symbol);
|
||||
})
|
||||
.add("invalid", () => {
|
||||
try {
|
||||
symbolSchema.parse(1);
|
||||
} catch (_e: any) {}
|
||||
})
|
||||
.on("cycle", (e: Benchmark.Event) => {
|
||||
console.log(`z.symbol: ${e.target}`);
|
||||
});
|
||||
|
||||
export default {
|
||||
suites: [enumSuite, longEnumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite],
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
function _nonIterableRest() {
|
||||
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
module.exports = _nonIterableRest, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "base-x",
|
||||
"version": "3.0.11",
|
||||
"description": "Fast base encoding / decoding of any given alphabet",
|
||||
"keywords": [
|
||||
"base-x",
|
||||
"base58",
|
||||
"base62",
|
||||
"base64",
|
||||
"crypto",
|
||||
"crytography",
|
||||
"decode",
|
||||
"decoding",
|
||||
"encode",
|
||||
"encoding"
|
||||
],
|
||||
"homepage": "https://github.com/cryptocoinjs/base-x",
|
||||
"bugs": {
|
||||
"url": "https://github.com/cryptocoinjs/base-x/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Daniel Cousens",
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"main": "src/index.js",
|
||||
"types": "src/index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cryptocoinjs/base-x.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p ./tsconfig.json ; standard --fix",
|
||||
"gitdiff": "npm run build && git diff --exit-code",
|
||||
"prepublish": "npm run gitdiff",
|
||||
"standard": "standard",
|
||||
"test": "npm run unit && npm run standard",
|
||||
"unit": "tape test/*.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "12.0.10",
|
||||
"standard": "^10.0.3",
|
||||
"tape": "^4.5.1",
|
||||
"typescript": "3.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
function _newArrowCheck(n, r) {
|
||||
if (n !== r) throw new TypeError("Cannot instantiate an arrow function");
|
||||
}
|
||||
module.exports = _newArrowCheck, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
@@ -0,0 +1,92 @@
|
||||
import { FixedSizeCodec, FixedSizeDecoder, FixedSizeEncoder } from './codec';
|
||||
/**
|
||||
* Reverses the bytes of a fixed-size encoder.
|
||||
*
|
||||
* Given a `FixedSizeEncoder`, this function returns a new `FixedSizeEncoder` that
|
||||
* reverses the bytes within the fixed-size byte array when encoding.
|
||||
*
|
||||
* This can be useful to modify endianness or for other byte-order transformations.
|
||||
*
|
||||
* For more details, see {@link reverseCodec}.
|
||||
*
|
||||
* @typeParam TFrom - The type of the value to encode.
|
||||
* @typeParam TSize - The fixed size of the encoded value in bytes.
|
||||
*
|
||||
* @param encoder - The fixed-size encoder to reverse.
|
||||
* @returns A new encoder that writes bytes in reverse order.
|
||||
*
|
||||
* @example
|
||||
* Encoding a `u16` value in reverse order.
|
||||
* ```ts
|
||||
* const encoder = reverseEncoder(getU16Encoder({ endian: Endian.Big }));
|
||||
* const bytes = encoder.encode(0x1234); // 0x3412 (bytes are flipped)
|
||||
* ```
|
||||
*
|
||||
* @see {@link reverseCodec}
|
||||
* @see {@link reverseDecoder}
|
||||
*/
|
||||
export declare function reverseEncoder<TFrom, TSize extends number>(encoder: FixedSizeEncoder<TFrom, TSize>): FixedSizeEncoder<TFrom, TSize>;
|
||||
/**
|
||||
* Reverses the bytes of a fixed-size decoder.
|
||||
*
|
||||
* Given a `FixedSizeDecoder`, this function returns a new `FixedSizeDecoder` that
|
||||
* reverses the bytes within the fixed-size byte array before decoding.
|
||||
*
|
||||
* This can be useful to modify endianness or for other byte-order transformations.
|
||||
*
|
||||
* For more details, see {@link reverseCodec}.
|
||||
*
|
||||
* @typeParam TTo - The type of the decoded value.
|
||||
* @typeParam TSize - The fixed size of the decoded value in bytes.
|
||||
*
|
||||
* @param decoder - The fixed-size decoder to reverse.
|
||||
* @returns A new decoder that reads bytes in reverse order.
|
||||
*
|
||||
* @example
|
||||
* Decoding a reversed `u16` value.
|
||||
* ```ts
|
||||
* const decoder = reverseDecoder(getU16Decoder({ endian: Endian.Big }));
|
||||
* const value = decoder.decode(new Uint8Array([0x34, 0x12])); // 0x1234 (bytes are flipped back)
|
||||
* ```
|
||||
*
|
||||
* @see {@link reverseCodec}
|
||||
* @see {@link reverseEncoder}
|
||||
*/
|
||||
export declare function reverseDecoder<TTo, TSize extends number>(decoder: FixedSizeDecoder<TTo, TSize>): FixedSizeDecoder<TTo, TSize>;
|
||||
/**
|
||||
* Reverses the bytes of a fixed-size codec.
|
||||
*
|
||||
* Given a `FixedSizeCodec`, this function returns a new `FixedSizeCodec` that
|
||||
* reverses the bytes within the fixed-size byte array during encoding and decoding.
|
||||
*
|
||||
* This can be useful to modify endianness or for other byte-order transformations.
|
||||
*
|
||||
* @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/decoded value in bytes.
|
||||
*
|
||||
* @param codec - The fixed-size codec to reverse.
|
||||
* @returns A new codec that encodes and decodes bytes in reverse order.
|
||||
*
|
||||
* @example
|
||||
* Reversing a `u16` codec.
|
||||
* ```ts
|
||||
* const codec = reverseCodec(getU16Codec({ endian: Endian.Big }));
|
||||
* const bytes = codec.encode(0x1234); // 0x3412 (bytes are flipped)
|
||||
* const value = codec.decode(bytes); // 0x1234 (bytes are flipped back)
|
||||
* ```
|
||||
*
|
||||
* @remarks
|
||||
* If you only need to reverse an encoder, use {@link reverseEncoder}.
|
||||
* If you only need to reverse a decoder, use {@link reverseDecoder}.
|
||||
*
|
||||
* ```ts
|
||||
* const bytes = reverseEncoder(getU16Encoder()).encode(0x1234);
|
||||
* const value = reverseDecoder(getU16Decoder()).decode(bytes);
|
||||
* ```
|
||||
*
|
||||
* @see {@link reverseEncoder}
|
||||
* @see {@link reverseDecoder}
|
||||
*/
|
||||
export declare function reverseCodec<TFrom, TTo extends TFrom, TSize extends number>(codec: FixedSizeCodec<TFrom, TTo, TSize>): FixedSizeCodec<TFrom, TTo, TSize>;
|
||||
//# sourceMappingURL=reverse-codec.d.ts.map
|
||||
@@ -0,0 +1,42 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const { createWarning } = require('..')
|
||||
const { withResolvers } = require('./promise')
|
||||
|
||||
test('emit should emit a given code unlimited times', t => {
|
||||
t.plan(60)
|
||||
|
||||
let runs = 0
|
||||
const expectedRun = []
|
||||
const times = 10
|
||||
|
||||
const { promise, resolve } = withResolvers()
|
||||
|
||||
process.on('warning', onWarning)
|
||||
function onWarning (warning) {
|
||||
t.assert.deepStrictEqual(warning.name, 'TestDeprecation')
|
||||
t.assert.deepStrictEqual(warning.code, 'CODE')
|
||||
t.assert.deepStrictEqual(warning.message, 'Hello world')
|
||||
t.assert.ok(warn.emitted)
|
||||
t.assert.deepStrictEqual(runs++, expectedRun.shift())
|
||||
}
|
||||
|
||||
const warn = createWarning({
|
||||
name: 'TestDeprecation',
|
||||
code: 'CODE',
|
||||
message: 'Hello world',
|
||||
unlimited: true
|
||||
})
|
||||
|
||||
for (let i = 0; i < times; i++) {
|
||||
expectedRun.push(i)
|
||||
t.assert.strictEqual(warn(), true)
|
||||
}
|
||||
setImmediate(() => {
|
||||
process.removeListener('warning', onWarning)
|
||||
resolve()
|
||||
})
|
||||
|
||||
return promise
|
||||
})
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow assignments to native objects or read-only global variables
|
||||
* @author Ilya Volodin
|
||||
* @deprecated in ESLint v3.3.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow assignments to native objects or read-only global variables",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-native-reassign",
|
||||
},
|
||||
|
||||
deprecated: {
|
||||
message: "Renamed rule.",
|
||||
url: "https://eslint.org/blog/2016/08/eslint-v3.3.0-released/#deprecated-rules",
|
||||
deprecatedSince: "3.3.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
rule: {
|
||||
name: "no-global-assign",
|
||||
url: "https://eslint.org/docs/rules/no-global-assign",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
exceptions: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
uniqueItems: true,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
nativeReassign:
|
||||
"Read-only global '{{name}}' should not be modified.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const config = context.options[0];
|
||||
const exceptions = (config && config.exceptions) || [];
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
/**
|
||||
* Reports write references.
|
||||
* @param {Reference} reference A reference to check.
|
||||
* @param {number} index The index of the reference in the references.
|
||||
* @param {Reference[]} references The array that the reference belongs to.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkReference(reference, index, references) {
|
||||
const identifier = reference.identifier;
|
||||
|
||||
if (
|
||||
reference.init === false &&
|
||||
reference.isWrite() &&
|
||||
/*
|
||||
* Destructuring assignments can have multiple default value,
|
||||
* so possibly there are multiple writeable references for the same identifier.
|
||||
*/
|
||||
(index === 0 || references[index - 1].identifier !== identifier)
|
||||
) {
|
||||
context.report({
|
||||
node: identifier,
|
||||
messageId: "nativeReassign",
|
||||
data: identifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports write references if a given variable is read-only builtin.
|
||||
* @param {Variable} variable A variable to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkVariable(variable) {
|
||||
if (
|
||||
variable.writeable === false &&
|
||||
!exceptions.includes(variable.name)
|
||||
) {
|
||||
variable.references.forEach(checkReference);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Program(node) {
|
||||
const globalScope = sourceCode.getScope(node);
|
||||
|
||||
globalScope.variables.forEach(checkVariable);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export declare const version: {
|
||||
readonly major: 4;
|
||||
readonly minor: 4;
|
||||
readonly patch: number;
|
||||
};
|
||||
Reference in New Issue
Block a user