WIP: bootstrap and partial real Solana watcher implementation

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

View File

@@ -0,0 +1 @@
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/bytes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,UAAU,GAAI,YAAY,UAAU,EAAE,KAAG,UAkBrD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,kBAAkB,GAAG,UAAU,EAAE,QAAQ,MAAM,KAAG,kBAAkB,GAAG,UAKtG,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,kBAAkB,GAAG,UAAU,EAAE,QAAQ,MAAM,KAAG,kBAAkB,GAAG,UAC1B,CAAC;AAE9E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CACzB,IAAI,EAAE,kBAAkB,GAAG,UAAU,EACrC,KAAK,EAAE,kBAAkB,GAAG,UAAU,EACtC,MAAM,EAAE,MAAM,GACf,OAAO,CAIT"}

View File

@@ -0,0 +1,17 @@
module.exports = extend
var hasOwnProperty = Object.prototype.hasOwnProperty;
function extend(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i]
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
target[key] = source[key]
}
}
}
return target
}

View File

@@ -0,0 +1,39 @@
'use strict';
const {Transform} = require('stream');
class Take extends Transform {
constructor(options) {
super(Object.assign({}, options, {writableObjectMode: true, readableObjectMode: true}));
this._n = this._skip = 0;
if (options) {
'n' in options && (this._n = options.n);
'skip' in options && (this._skip = options.skip);
}
if (this._skip <= 0) {
this._transform = this._n > 0 ? this._countValues : this._doNothing;
}
}
_transform(chunk, encoding, callback) {
if (--this._skip <= 0) {
this._transform = this._n > 0 ? this._countValues : this._doNothing;
}
callback(null);
}
_countValues(chunk, encoding, callback) {
if (--this._n <= 0) {
this._transform = this._doNothing;
}
this.push(chunk);
callback(null);
}
_doNothing(chunk, encoding, callback) {
callback(null);
}
static make(n) {
return new Take(typeof n == 'object' ? n : {n});
}
}
Take.make.Constructor = Take;
module.exports = Take.make;

View File

@@ -0,0 +1,242 @@
/**
* @fileoverview A rule to set the maximum number of line of code in a function.
* @author Pete Ward <peteward44@gmail.com>
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
const { upperCaseFirst } = require("../shared/string-utils");
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
const OPTIONS_SCHEMA = {
type: "object",
properties: {
max: {
type: "integer",
minimum: 0,
},
skipComments: {
type: "boolean",
},
skipBlankLines: {
type: "boolean",
},
IIFEs: {
type: "boolean",
},
},
additionalProperties: false,
};
const OPTIONS_OR_INTEGER_SCHEMA = {
oneOf: [
OPTIONS_SCHEMA,
{
type: "integer",
minimum: 1,
},
],
};
/**
* Given a list of comment nodes, return a map with numeric keys (source code line numbers) and comment token values.
* @param {Array} comments An array of comment nodes.
* @returns {Map<string, Node>} A map with numeric keys (source code line numbers) and comment token values.
*/
function getCommentLineNumbers(comments) {
const map = new Map();
comments.forEach(comment => {
for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) {
map.set(i, comment);
}
});
return map;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description:
"Enforce a maximum number of lines of code in a function",
recommended: false,
url: "https://eslint.org/docs/latest/rules/max-lines-per-function",
},
schema: [OPTIONS_OR_INTEGER_SCHEMA],
defaultOptions: [50],
messages: {
exceed: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}.",
},
},
create(context) {
const sourceCode = context.sourceCode;
const lines = sourceCode.lines;
const option = context.options[0];
let maxLines = 50;
let skipComments = false;
let skipBlankLines = false;
let IIFEs = false;
if (typeof option === "object") {
maxLines = typeof option.max === "number" ? option.max : 50;
skipComments = !!option.skipComments;
skipBlankLines = !!option.skipBlankLines;
IIFEs = !!option.IIFEs;
} else if (typeof option === "number") {
maxLines = option;
}
const commentLineNumbers = getCommentLineNumbers(
sourceCode.getAllComments(),
);
//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------
/**
* Tells if a comment encompasses the entire line.
* @param {string} line The source line with a trailing comment
* @param {number} lineNumber The one-indexed line number this is on
* @param {ASTNode} comment The comment to remove
* @returns {boolean} If the comment covers the entire line
*/
function isFullLineComment(line, lineNumber, comment) {
const start = comment.loc.start,
end = comment.loc.end,
isFirstTokenOnLine =
start.line === lineNumber &&
!line.slice(0, start.column).trim(),
isLastTokenOnLine =
end.line === lineNumber && !line.slice(end.column).trim();
return (
comment &&
(start.line < lineNumber || isFirstTokenOnLine) &&
(end.line > lineNumber || isLastTokenOnLine)
);
}
/**
* Identifies is a node is a FunctionExpression which is part of an IIFE
* @param {ASTNode} node Node to test
* @returns {boolean} True if it's an IIFE
*/
function isIIFE(node) {
return (
(node.type === "FunctionExpression" ||
node.type === "ArrowFunctionExpression") &&
node.parent &&
node.parent.type === "CallExpression" &&
node.parent.callee === node
);
}
/**
* Identifies is a node is a FunctionExpression which is embedded within a MethodDefinition or Property
* @param {ASTNode} node Node to test
* @returns {boolean} True if it's a FunctionExpression embedded within a MethodDefinition or Property
*/
function isEmbedded(node) {
if (!node.parent) {
return false;
}
if (node !== node.parent.value) {
return false;
}
if (node.parent.type === "MethodDefinition") {
return true;
}
if (node.parent.type === "Property") {
return (
node.parent.method === true ||
node.parent.kind === "get" ||
node.parent.kind === "set"
);
}
return false;
}
/**
* Count the lines in the function
* @param {ASTNode} funcNode Function AST node
* @returns {void}
* @private
*/
function processFunction(funcNode) {
const node = isEmbedded(funcNode) ? funcNode.parent : funcNode;
if (!IIFEs && isIIFE(node)) {
return;
}
let lineCount = 0;
for (let i = node.loc.start.line - 1; i < node.loc.end.line; ++i) {
const line = lines[i];
if (skipComments) {
if (
commentLineNumbers.has(i + 1) &&
isFullLineComment(
line,
i + 1,
commentLineNumbers.get(i + 1),
)
) {
continue;
}
}
if (skipBlankLines) {
if (line.match(/^\s*$/u)) {
continue;
}
}
lineCount++;
}
if (lineCount > maxLines) {
const name = upperCaseFirst(
astUtils.getFunctionNameWithKind(funcNode),
);
context.report({
node,
loc: astUtils.getFunctionHeadLoc(funcNode, sourceCode),
messageId: "exceed",
data: { name, lineCount, maxLines },
});
}
}
//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
return {
FunctionDeclaration: processFunction,
FunctionExpression: processFunction,
ArrowFunctionExpression: processFunction,
};
},
};

View File

@@ -0,0 +1,85 @@
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.globalConfig = exports.$ZodEncodeError = exports.$ZodAsyncError = exports.$brand = exports.NEVER = void 0;
exports.$constructor = $constructor;
exports.config = config;
/** A special constant with type `never` */
exports.NEVER = Object.freeze({
status: "aborted",
});
function $constructor(name, initializer, params) {
function init(inst, def) {
if (!inst._zod) {
Object.defineProperty(inst, "_zod", {
value: {
def,
constr: _,
traits: new Set(),
},
enumerable: false,
});
}
if (inst._zod.traits.has(name)) {
return;
}
inst._zod.traits.add(name);
initializer(inst, def);
// support prototype modifications
const proto = _.prototype;
const keys = Object.keys(proto);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
if (!(k in inst)) {
inst[k] = proto[k].bind(inst);
}
}
}
// doesn't work if Parent has a constructor with arguments
const Parent = params?.Parent ?? Object;
class Definition extends Parent {
}
Object.defineProperty(Definition, "name", { value: name });
function _(def) {
var _a;
const inst = params?.Parent ? new Definition() : this;
init(inst, def);
(_a = inst._zod).deferred ?? (_a.deferred = []);
for (const fn of inst._zod.deferred) {
fn();
}
return inst;
}
Object.defineProperty(_, "init", { value: init });
Object.defineProperty(_, Symbol.hasInstance, {
value: (inst) => {
if (params?.Parent && inst instanceof params.Parent)
return true;
return inst?._zod?.traits?.has(name);
},
});
Object.defineProperty(_, "name", { value: name });
return _;
}
////////////////////////////// UTILITIES ///////////////////////////////////////
exports.$brand = Symbol("zod_brand");
class $ZodAsyncError extends Error {
constructor() {
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
}
}
exports.$ZodAsyncError = $ZodAsyncError;
class $ZodEncodeError extends Error {
constructor(name) {
super(`Encountered unidirectional transform during encode: ${name}`);
this.name = "ZodEncodeError";
}
}
exports.$ZodEncodeError = $ZodEncodeError;
(_a = globalThis).__zod_globalConfig ?? (_a.__zod_globalConfig = {});
exports.globalConfig = globalThis.__zod_globalConfig;
function config(newConfig) {
if (newConfig)
Object.assign(exports.globalConfig, newConfig);
return exports.globalConfig;
}

View File

@@ -0,0 +1,9 @@
'use strict';
var util = require('./util');
module.exports = SchemaObject;
function SchemaObject(obj) {
util.copy(obj, this);
}

View File

@@ -0,0 +1,224 @@
/**
* @fileoverview Rule to flag unnecessary bind calls
* @author Bence Dányi <bence@danyi.me>
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const SIDE_EFFECT_FREE_NODE_TYPES = new Set([
"Literal",
"Identifier",
"ThisExpression",
"FunctionExpression",
]);
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Disallow unnecessary calls to `.bind()`",
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-extra-bind",
},
schema: [],
fixable: "code",
messages: {
unexpected: "The function binding is unnecessary.",
},
},
create(context) {
const sourceCode = context.sourceCode;
let scopeInfo = null;
/**
* Checks if a node is free of side effects.
*
* This check is stricter than it needs to be, in order to keep the implementation simple.
* @param {ASTNode} node A node to check.
* @returns {boolean} True if the node is known to be side-effect free, false otherwise.
*/
function isSideEffectFree(node) {
return SIDE_EFFECT_FREE_NODE_TYPES.has(node.type);
}
/**
* Reports a given function node.
* @param {ASTNode} node A node to report. This is a FunctionExpression or
* an ArrowFunctionExpression.
* @returns {void}
*/
function report(node) {
const memberNode = node.parent;
const callNode =
memberNode.parent.type === "ChainExpression"
? memberNode.parent.parent
: memberNode.parent;
context.report({
node: callNode,
messageId: "unexpected",
loc: memberNode.property.loc,
fix(fixer) {
if (!isSideEffectFree(callNode.arguments[0])) {
return null;
}
/*
* The list of the first/last token pair of a removal range.
* This is two parts because closing parentheses may exist between the method name and arguments.
* E.g. `(function(){}.bind ) (obj)`
* ^^^^^ ^^^^^ < removal ranges
* E.g. `(function(){}?.['bind'] ) ?.(obj)`
* ^^^^^^^^^^ ^^^^^^^ < removal ranges
*/
const tokenPairs = [
[
// `.`, `?.`, or `[` token.
sourceCode.getTokenAfter(
memberNode.object,
astUtils.isNotClosingParenToken,
),
// property name or `]` token.
sourceCode.getLastToken(memberNode),
],
[
// `?.` or `(` token of arguments.
sourceCode.getTokenAfter(
memberNode,
astUtils.isNotClosingParenToken,
),
// `)` token of arguments.
sourceCode.getLastToken(callNode),
],
];
const firstTokenToRemove = tokenPairs[0][0];
const lastTokenToRemove = tokenPairs[1][1];
if (
sourceCode.commentsExistBetween(
firstTokenToRemove,
lastTokenToRemove,
)
) {
return null;
}
return tokenPairs.map(([start, end]) =>
fixer.removeRange([start.range[0], end.range[1]]),
);
},
});
}
/**
* Checks whether or not a given function node is the callee of `.bind()`
* method.
*
* e.g. `(function() {}.bind(foo))`
* @param {ASTNode} node A node to report. This is a FunctionExpression or
* an ArrowFunctionExpression.
* @returns {boolean} `true` if the node is the callee of `.bind()` method.
*/
function isCalleeOfBindMethod(node) {
if (!astUtils.isSpecificMemberAccess(node.parent, null, "bind")) {
return false;
}
// The node of `*.bind` member access.
const bindNode =
node.parent.parent.type === "ChainExpression"
? node.parent.parent
: node.parent;
return (
bindNode.parent.type === "CallExpression" &&
bindNode.parent.callee === bindNode &&
bindNode.parent.arguments.length === 1 &&
bindNode.parent.arguments[0].type !== "SpreadElement"
);
}
/**
* Adds a scope information object to the stack.
* @param {ASTNode} node A node to add. This node is a FunctionExpression
* or a FunctionDeclaration node.
* @returns {void}
*/
function enterFunction(node) {
scopeInfo = {
isBound: isCalleeOfBindMethod(node),
thisFound: false,
upper: scopeInfo,
};
}
/**
* Removes the scope information object from the top of the stack.
* At the same time, this reports the function node if the function has
* `.bind()` and the `this` keywords found.
* @param {ASTNode} node A node to remove. This node is a
* FunctionExpression or a FunctionDeclaration node.
* @returns {void}
*/
function exitFunction(node) {
if (scopeInfo.isBound && !scopeInfo.thisFound) {
report(node);
}
scopeInfo = scopeInfo.upper;
}
/**
* Reports a given arrow function if the function is callee of `.bind()`
* method.
* @param {ASTNode} node A node to report. This node is an
* ArrowFunctionExpression.
* @returns {void}
*/
function exitArrowFunction(node) {
if (isCalleeOfBindMethod(node)) {
report(node);
}
}
/**
* Set the mark as the `this` keyword was found in this scope.
* @returns {void}
*/
function markAsThisFound() {
if (scopeInfo) {
scopeInfo.thisFound = true;
}
}
return {
"ArrowFunctionExpression:exit": exitArrowFunction,
FunctionDeclaration: enterFunction,
"FunctionDeclaration:exit": exitFunction,
FunctionExpression: enterFunction,
"FunctionExpression:exit": exitFunction,
ThisExpression: markAsThisFound,
};
},
};

View File

@@ -0,0 +1,2 @@
import type { LibDefinition } from '../variable';
export declare const es2024_sharedmemory: LibDefinition;

View File

@@ -0,0 +1,210 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-invalid-void-type',
meta: {
type: 'problem',
docs: {
description: 'Disallow `void` type outside of generic or return types',
recommended: 'strict',
},
messages: {
invalidVoidForGeneric: '{{ generic }} may not have void as a type argument.',
invalidVoidNotReturn: 'void is only valid as a return type.',
invalidVoidNotReturnOrGeneric: 'void is only valid as a return type or generic type argument.',
invalidVoidNotReturnOrThisParam: 'void is only valid as return type or type of `this` parameter.',
invalidVoidNotReturnOrThisParamOrGeneric: 'void is only valid as a return type or generic type argument or the type of a `this` parameter.',
invalidVoidUnionConstituent: 'void is not valid as a constituent in a union type',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowAsThisParameter: {
type: 'boolean',
description: 'Whether a `this` parameter of a function may be `void`.',
},
allowInGenericTypeArguments: {
description: 'Whether `void` can be used as a valid value for generic type parameters.',
oneOf: [
{
type: 'boolean',
description: 'Whether `void` can be used as a valid value for all generic type parameters.',
},
{
type: 'array',
description: 'Allowlist of types that may accept `void` as a generic type parameter.',
items: { type: 'string' },
minItems: 1,
},
],
},
},
},
],
},
defaultOptions: [
{ allowAsThisParameter: false, allowInGenericTypeArguments: true },
],
create(context, [{ allowAsThisParameter, allowInGenericTypeArguments }]) {
const validParents = [
utils_1.AST_NODE_TYPES.TSTypeAnnotation, //
];
const invalidGrandParents = [
utils_1.AST_NODE_TYPES.TSPropertySignature,
utils_1.AST_NODE_TYPES.CallExpression,
utils_1.AST_NODE_TYPES.PropertyDefinition,
utils_1.AST_NODE_TYPES.AccessorProperty,
utils_1.AST_NODE_TYPES.Identifier,
];
const validUnionMembers = [
utils_1.AST_NODE_TYPES.TSVoidKeyword,
utils_1.AST_NODE_TYPES.TSNeverKeyword,
];
if (allowInGenericTypeArguments === true) {
validParents.push(utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation);
}
/**
* @brief check if the given void keyword is used as a valid generic type
*
* reports if the type parametrized by void is not in the allowlist, or
* allowInGenericTypeArguments is false.
* no-op if the given void keyword is not used as generic type
*/
function checkGenericTypeArgument(node) {
// only matches T<..., void, ...>
// extra check for precaution
/* istanbul ignore next */
if (node.parent.type !== utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation ||
node.parent.parent.type !== utils_1.AST_NODE_TYPES.TSTypeReference) {
return;
}
// check allowlist
if (Array.isArray(allowInGenericTypeArguments)) {
const fullyQualifiedName = context.sourceCode
.getText(node.parent.parent.typeName)
.replaceAll(' ', '');
if (!allowInGenericTypeArguments
.map(s => s.replaceAll(' ', ''))
.includes(fullyQualifiedName)) {
context.report({
node,
messageId: 'invalidVoidForGeneric',
data: { generic: fullyQualifiedName },
});
}
return;
}
if (!allowInGenericTypeArguments) {
context.report({
node,
messageId: allowAsThisParameter
? 'invalidVoidNotReturnOrThisParam'
: 'invalidVoidNotReturn',
});
}
}
/**
* @brief checks if the generic type parameter defaults to void
*/
function checkDefaultVoid(node, parentNode) {
if (parentNode.default !== node) {
context.report({
node,
messageId: getNotReturnOrGenericMessageId(node),
});
}
}
/**
* @brief checks that a union containing void is valid
* @return true if every member of the union is specified as a valid type in
* validUnionMembers, or is a valid generic type parametrized by void
*/
function isValidUnionType(node) {
return node.types.every(member => validUnionMembers.includes(member.type) ||
// allows any T<..., void, ...> here, checked by checkGenericTypeArgument
(member.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
member.typeArguments?.type ===
utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation &&
member.typeArguments.params
.map(param => param.type)
.includes(utils_1.AST_NODE_TYPES.TSVoidKeyword)));
}
return {
TSVoidKeyword(node) {
// checks T<..., void, ...> against specification of allowInGenericArguments option
if (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation &&
node.parent.parent.type === utils_1.AST_NODE_TYPES.TSTypeReference) {
checkGenericTypeArgument(node);
return;
}
// allow <T = void> if allowInGenericTypeArguments is specified, and report if the generic type parameter extends void
if (allowInGenericTypeArguments &&
node.parent.type === utils_1.AST_NODE_TYPES.TSTypeParameter &&
node.parent.default?.type === utils_1.AST_NODE_TYPES.TSVoidKeyword) {
checkDefaultVoid(node, node.parent);
return;
}
// union w/ void must contain types from validUnionMembers, or a valid generic void type
if (node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType &&
isValidUnionType(node.parent)) {
return;
}
// using `void` as part of the return type of function overloading implementation
if (node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType) {
const declaringFunction = getParentFunctionDeclarationNode(node.parent);
if (declaringFunction &&
(0, util_1.hasOverloadSignatures)(declaringFunction, context)) {
return;
}
}
// this parameter is ok to be void.
if (allowAsThisParameter &&
node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
node.parent.parent.type === utils_1.AST_NODE_TYPES.Identifier &&
node.parent.parent.name === 'this') {
return;
}
// default cases
if (validParents.includes(node.parent.type) &&
// https://github.com/typescript-eslint/typescript-eslint/issues/6225
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
!invalidGrandParents.includes(node.parent.parent.type)) {
return;
}
context.report({
node,
messageId: allowInGenericTypeArguments && allowAsThisParameter
? 'invalidVoidNotReturnOrThisParamOrGeneric'
: allowInGenericTypeArguments
? getNotReturnOrGenericMessageId(node)
: allowAsThisParameter
? 'invalidVoidNotReturnOrThisParam'
: 'invalidVoidNotReturn',
});
},
};
},
});
function getNotReturnOrGenericMessageId(node) {
return node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType
? 'invalidVoidUnionConstituent'
: 'invalidVoidNotReturnOrGeneric';
}
function getParentFunctionDeclarationNode(node) {
let current = node.parent;
while (current) {
if (current.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) {
return current;
}
if (current.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
current.value.body != null) {
return current;
}
current = current.parent;
}
return null;
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"ripemd160.js","sourceRoot":"","sources":["src/ripemd160.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,2CAA+E;AAC/E,+DAA+D;AAClD,QAAA,SAAS,GAAsB,qBAAU,CAAC;AACvD,+DAA+D;AAClD,QAAA,SAAS,GAAsB,qBAAU,CAAC"}

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Variable = void 0;
const VariableBase_1 = require("./VariableBase");
/**
* A Variable represents a locally scoped identifier. These include arguments to functions.
*/
class Variable extends VariableBase_1.VariableBase {
/**
* `true` if the variable is valid in a type context, false otherwise
* @public
*/
get isTypeVariable() {
if (this.defs.length === 0) {
// we don't statically know whether this is a type or a value
return true;
}
return this.defs.some(def => def.isTypeDefinition);
}
/**
* `true` if the variable is valid in a value context, false otherwise
* @public
*/
get isValueVariable() {
if (this.defs.length === 0) {
// we don't statically know whether this is a type or a value
return true;
}
return this.defs.some(def => def.isVariableDefinition);
}
}
exports.Variable = Variable;

View File

@@ -0,0 +1,7 @@
export * from './error.js';
export * from './struct.js';
export * from './structs/coercions.js';
export * from './structs/refinements.js';
export * from './structs/types.js';
export * from './structs/utilities.js';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1,206 @@
# convert-source-map [![Build Status][ci-image]][ci-url]
Converts a source-map from/to different formats and allows adding/changing properties.
```js
var convert = require('convert-source-map');
var json = convert
.fromComment('//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQvZm9vLm1pbi5qcyIsInNvdXJjZXMiOlsic3JjL2Zvby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIvIn0=')
.toJSON();
var modified = convert
.fromComment('//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQvZm9vLm1pbi5qcyIsInNvdXJjZXMiOlsic3JjL2Zvby5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIvIn0=')
.setProperty('sources', [ 'SRC/FOO.JS' ])
.toJSON();
console.log(json);
console.log(modified);
```
```json
{"version":3,"file":"build/foo.min.js","sources":["src/foo.js"],"names":[],"mappings":"AAAA","sourceRoot":"/"}
{"version":3,"file":"build/foo.min.js","sources":["SRC/FOO.JS"],"names":[],"mappings":"AAAA","sourceRoot":"/"}
```
## Upgrading
Prior to v2.0.0, the `fromMapFileComment` and `fromMapFileSource` functions took a String directory path and used that to resolve & read the source map file from the filesystem. However, this made the library limited to nodejs environments and broke on sources with querystrings.
In v2.0.0, you now need to pass a function that does the file reading. It will receive the source filename as a String that you can resolve to a filesystem path, URL, or anything else.
If you are using `convert-source-map` in nodejs and want the previous behavior, you'll use a function like such:
```diff
+ var fs = require('fs'); // Import the fs module to read a file
+ var path = require('path'); // Import the path module to resolve a path against your directory
- var conv = convert.fromMapFileSource(css, '../my-dir');
+ var conv = convert.fromMapFileSource(css, function (filename) {
+ return fs.readFileSync(path.resolve('../my-dir', filename), 'utf-8');
+ });
```
## API
### fromObject(obj)
Returns source map converter from given object.
### fromJSON(json)
Returns source map converter from given json string.
### fromURI(uri)
Returns source map converter from given uri encoded json string.
### fromBase64(base64)
Returns source map converter from given base64 encoded json string.
### fromComment(comment)
Returns source map converter from given base64 or uri encoded json string prefixed with `//# sourceMappingURL=...`.
### fromMapFileComment(comment, readMap)
Returns source map converter from given `filename` by parsing `//# sourceMappingURL=filename`.
`readMap` must be a function which receives the source map filename and returns either a String or Buffer of the source map (if read synchronously), or a `Promise` containing a String or Buffer of the source map (if read asynchronously).
If `readMap` doesn't return a `Promise`, `fromMapFileComment` will return a source map converter synchronously.
If `readMap` returns a `Promise`, `fromMapFileComment` will also return `Promise`. The `Promise` will be either resolved with the source map converter or rejected with an error.
#### Examples
**Synchronous read in Node.js:**
```js
var convert = require('convert-source-map');
var fs = require('fs');
function readMap(filename) {
return fs.readFileSync(filename, 'utf8');
}
var json = convert
.fromMapFileComment('//# sourceMappingURL=map-file-comment.css.map', readMap)
.toJSON();
console.log(json);
```
**Asynchronous read in Node.js:**
```js
var convert = require('convert-source-map');
var { promises: fs } = require('fs'); // Notice the `promises` import
function readMap(filename) {
return fs.readFile(filename, 'utf8');
}
var converter = await convert.fromMapFileComment('//# sourceMappingURL=map-file-comment.css.map', readMap)
var json = converter.toJSON();
console.log(json);
```
**Asynchronous read in the browser:**
```js
var convert = require('convert-source-map');
async function readMap(url) {
const res = await fetch(url);
return res.text();
}
const converter = await convert.fromMapFileComment('//# sourceMappingURL=map-file-comment.css.map', readMap)
var json = converter.toJSON();
console.log(json);
```
### fromSource(source)
Finds last sourcemap comment in file and returns source map converter or returns `null` if no source map comment was found.
### fromMapFileSource(source, readMap)
Finds last sourcemap comment in file and returns source map converter or returns `null` if no source map comment was found.
`readMap` must be a function which receives the source map filename and returns either a String or Buffer of the source map (if read synchronously), or a `Promise` containing a String or Buffer of the source map (if read asynchronously).
If `readMap` doesn't return a `Promise`, `fromMapFileSource` will return a source map converter synchronously.
If `readMap` returns a `Promise`, `fromMapFileSource` will also return `Promise`. The `Promise` will be either resolved with the source map converter or rejected with an error.
### toObject()
Returns a copy of the underlying source map.
### toJSON([space])
Converts source map to json string. If `space` is given (optional), this will be passed to
[JSON.stringify](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify) when the
JSON string is generated.
### toURI()
Converts source map to uri encoded json string.
### toBase64()
Converts source map to base64 encoded json string.
### toComment([options])
Converts source map to an inline comment that can be appended to the source-file.
By default, the comment is formatted like: `//# sourceMappingURL=...`, which you would
normally see in a JS source file.
When `options.encoding == 'uri'`, the data will be uri encoded, otherwise they will be base64 encoded.
When `options.multiline == true`, the comment is formatted like: `/*# sourceMappingURL=... */`, which you would find in a CSS source file.
### addProperty(key, value)
Adds given property to the source map. Throws an error if property already exists.
### setProperty(key, value)
Sets given property to the source map. If property doesn't exist it is added, otherwise its value is updated.
### getProperty(key)
Gets given property of the source map.
### removeComments(src)
Returns `src` with all source map comments removed
### removeMapFileComments(src)
Returns `src` with all source map comments pointing to map files removed.
### commentRegex
Provides __a fresh__ RegExp each time it is accessed. Can be used to find source map comments.
Breaks down a source map comment into groups: Groups: 1: media type, 2: MIME type, 3: charset, 4: encoding, 5: data.
### mapFileCommentRegex
Provides __a fresh__ RegExp each time it is accessed. Can be used to find source map comments pointing to map files.
### generateMapFileComment(file, [options])
Returns a comment that links to an external source map via `file`.
By default, the comment is formatted like: `//# sourceMappingURL=...`, which you would normally see in a JS source file.
When `options.multiline == true`, the comment is formatted like: `/*# sourceMappingURL=... */`, which you would find in a CSS source file.
[ci-url]: https://github.com/thlorenz/convert-source-map/actions?query=workflow:ci
[ci-image]: https://img.shields.io/github/workflow/status/thlorenz/convert-source-map/CI?style=flat-square

View File

@@ -0,0 +1,106 @@
/*! *****************************************************************************
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"/>
interface MapConstructor {
/**
* Groups members of an iterable according to the return value of the passed callback.
* @param items An iterable.
* @param keySelector A callback which will be invoked for each item in items.
*/
groupBy<K, T>(
items: Iterable<T>,
keySelector: (item: T, index: number) => K,
): Map<K, T[]>;
}
interface ReadonlySetLike<T> {
/**
* Despite its name, returns an iterator of the values in the set-like.
*/
keys(): Iterator<T>;
/**
* @returns a boolean indicating whether an element with the specified value exists in the set-like or not.
*/
has(value: T): boolean;
/**
* @returns the number of (unique) elements in the set-like.
*/
readonly size: number;
}
interface Set<T> {
/**
* @returns a new Set containing all the elements in this Set and also all the elements in the argument.
*/
union<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a new Set containing all the elements which are both in this Set and in the argument.
*/
intersection<U>(other: ReadonlySetLike<U>): Set<T & U>;
/**
* @returns a new Set containing all the elements in this Set which are not also in the argument.
*/
difference<U>(other: ReadonlySetLike<U>): Set<T>;
/**
* @returns a new Set containing all the elements which are in either this Set or in the argument, but not in both.
*/
symmetricDifference<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a boolean indicating whether all the elements in this Set are also in the argument.
*/
isSubsetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether all the elements in the argument are also in this Set.
*/
isSupersetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether this Set has no elements in common with the argument.
*/
isDisjointFrom(other: ReadonlySetLike<unknown>): boolean;
}
interface ReadonlySet<T> {
/**
* @returns a new Set containing all the elements in this Set and also all the elements in the argument.
*/
union<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a new Set containing all the elements which are both in this Set and in the argument.
*/
intersection<U>(other: ReadonlySetLike<U>): Set<T & U>;
/**
* @returns a new Set containing all the elements in this Set which are not also in the argument.
*/
difference<U>(other: ReadonlySetLike<U>): Set<T>;
/**
* @returns a new Set containing all the elements which are in either this Set or in the argument, but not in both.
*/
symmetricDifference<U>(other: ReadonlySetLike<U>): Set<T | U>;
/**
* @returns a boolean indicating whether all the elements in this Set are also in the argument.
*/
isSubsetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether all the elements in the argument are also in this Set.
*/
isSupersetOf(other: ReadonlySetLike<unknown>): boolean;
/**
* @returns a boolean indicating whether this Set has no elements in common with the argument.
*/
isDisjointFrom(other: ReadonlySetLike<unknown>): boolean;
}

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.escapeRegExp = escapeRegExp;
/**
* Lodash <https://lodash.com/>
* Released under MIT license <https://lodash.com/license>
*/
const reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
const reHasRegExpChar = RegExp(reRegExpChar.source);
function escapeRegExp(string = '') {
return string && reHasRegExpChar.test(string)
? string.replaceAll(reRegExpChar, '\\$&')
: string;
}

View File

@@ -0,0 +1,12 @@
import type { TSESTreeOptions } from '../parser-options';
import type { ParseSettings } from './index';
/**
* Checks for a matching TSConfig to a file including its parent directories,
* permanently caching results under each directory it checks.
*
* @remarks
* We don't (yet!) have a way to attach file watchers on disk, but still need to
* cache file checks for rapid subsequent calls to fs.existsSync. See discussion
* in https://github.com/typescript-eslint/typescript-eslint/issues/101.
*/
export declare function getProjectConfigFiles(parseSettings: Pick<ParseSettings, 'filePath' | 'tsconfigMatchCache' | 'tsconfigRootDir'>, project: TSESTreeOptions['project']): string[] | null;

View File

@@ -0,0 +1,62 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABILITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
declare namespace Intl {
interface NumberFormatOptionsUseGroupingRegistry {
min2: never;
auto: never;
always: never;
}
interface NumberFormatOptionsSignDisplayRegistry {
negative: never;
}
interface NumberFormatRangePartTypeRegistry extends NumberFormatPartTypeRegistry {
approximatelySign: never;
}
type NumberFormatRangePartTypes = keyof NumberFormatRangePartTypeRegistry;
interface NumberFormatOptions {
roundingPriority?: "auto" | "morePrecision" | "lessPrecision" | undefined;
roundingIncrement?: 1 | 2 | 5 | 10 | 20 | 25 | 50 | 100 | 200 | 250 | 500 | 1000 | 2000 | 2500 | 5000 | undefined;
roundingMode?: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven" | undefined;
trailingZeroDisplay?: "auto" | "stripIfInteger" | undefined;
}
interface ResolvedNumberFormatOptions {
roundingPriority: "auto" | "morePrecision" | "lessPrecision";
roundingMode: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven";
roundingIncrement: 1 | 2 | 5 | 10 | 20 | 25 | 50 | 100 | 200 | 250 | 500 | 1000 | 2000 | 2500 | 5000;
trailingZeroDisplay: "auto" | "stripIfInteger";
}
interface NumberRangeFormatPart {
type: NumberFormatRangePartTypes;
value: string;
source: "startRange" | "endRange" | "shared";
}
type StringNumericLiteral = `${number}` | "Infinity" | "-Infinity" | "+Infinity";
interface NumberFormat {
format(value: number | bigint | StringNumericLiteral): string;
formatToParts(value: number | bigint | StringNumericLiteral): NumberFormatPart[];
formatRange(start: number | bigint | StringNumericLiteral, end: number | bigint | StringNumericLiteral): string;
formatRangeToParts(start: number | bigint | StringNumericLiteral, end: number | bigint | StringNumericLiteral): NumberRangeFormatPart[];
}
}

View File

@@ -0,0 +1,70 @@
import * as tinybench from 'tinybench';
import { VitestRunner, VitestRunnerImportSource, Suite, File, Task, CancelReason, Test, TestContext, ImportDuration, createTaskCollector, getCurrentSuite, getCurrentTest, getHooks, getFn } from '@vitest/runner';
export { VitestRunner } from '@vitest/runner';
import { S as SerializedConfig } from './chunks/config.d.A1h_Y6Jt.js';
import { T as Traces } from './chunks/traces.d.D2T_R8rx.js';
import { createChainable, matchesTags } from '@vitest/runner/utils';
import { g as getBenchFn, a as getBenchOptions } from './chunks/suite.d.udJtyAgw.js';
import '@vitest/pretty-format';
import '@vitest/snapshot';
import '@vitest/utils/diff';
import './chunks/benchmark.d.DAaHLpsq.js';
declare class NodeBenchmarkRunner implements VitestRunner {
config: SerializedConfig;
private moduleRunner;
constructor(config: SerializedConfig);
importTinybench(): Promise<typeof tinybench>;
importFile(filepath: string, source: VitestRunnerImportSource): unknown;
runSuite(suite: Suite): Promise<void>;
runTask(): Promise<void>;
}
declare class TestRunner implements VitestRunner {
config: SerializedConfig;
private snapshotClient;
private workerState;
private moduleRunner;
private cancelRun;
private assertionsErrors;
pool: string;
private _otel;
viteEnvironment: string;
private viteModuleRunner;
constructor(config: SerializedConfig);
importFile(filepath: string, source: VitestRunnerImportSource): unknown;
onCollectStart(file: File): void;
onCleanupWorkerContext(listener: () => unknown): void;
onAfterRunFiles(): void;
onAfterRunSuite(suite: Suite): Promise<void>;
onAfterRunTask(test: Task): void;
cancel(_reason: CancelReason): void;
injectValue(key: string): any;
onBeforeRunTask(test: Task): Promise<void>;
onBeforeRunSuite(suite: Suite): Promise<void>;
onBeforeTryTask(test: Task): void;
onAfterTryTask(test: Test): void;
extendTaskContext(context: TestContext): TestContext;
getImportDurations(): Record<string, ImportDuration>;
trace: <T>(name: string, attributes: Record<string, any> | (() => T), cb?: () => T) => T;
__setTraces(traces: Traces): void;
static createTaskCollector: typeof createTaskCollector;
static getCurrentSuite: typeof getCurrentSuite;
static getCurrentTest: typeof getCurrentTest;
static createChainable: typeof createChainable;
static getSuiteHooks: typeof getHooks;
static getTestFn: typeof getFn;
static setSuiteHooks: typeof getHooks;
static setTestFn: typeof getFn;
static matchesTags: typeof matchesTags;
/**
* @deprecated
*/
static getBenchFn: typeof getBenchFn;
/**
* @deprecated
*/
static getBenchOptions: typeof getBenchOptions;
}
export { NodeBenchmarkRunner, TestRunner as VitestTestRunner };

View File

@@ -0,0 +1,5 @@
'use strict'
const compare = require('./compare')
const neq = (a, b, loose) => compare(a, b, loose) !== 0
module.exports = neq

View File

@@ -0,0 +1,57 @@
var fs = require('fs')
var core
if (process.platform === 'win32' || global.TESTING_WINDOWS) {
core = require('./windows.js')
} else {
core = require('./mode.js')
}
module.exports = isexe
isexe.sync = sync
function isexe (path, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
}
if (!cb) {
if (typeof Promise !== 'function') {
throw new TypeError('callback not provided')
}
return new Promise(function (resolve, reject) {
isexe(path, options || {}, function (er, is) {
if (er) {
reject(er)
} else {
resolve(is)
}
})
})
}
core(path, options || {}, function (er, is) {
// ignore EACCES because that just means we aren't allowed to run it
if (er) {
if (er.code === 'EACCES' || options && options.ignoreErrors) {
er = null
is = false
}
}
cb(er, is)
})
}
function sync (path, options) {
// my kingdom for a filtered catch
try {
return core.sync(path, options || {})
} catch (er) {
if (options && options.ignoreErrors || er.code === 'EACCES') {
return false
} else {
throw er
}
}
}

View File

@@ -0,0 +1,285 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@typescript-eslint/utils");
const tsutils = __importStar(require("ts-api-utils"));
const ts = __importStar(require("typescript"));
const util_1 = require("../util");
exports.default = (0, util_1.createRule)({
name: 'no-unnecessary-boolean-literal-compare',
meta: {
type: 'suggestion',
docs: {
description: 'Disallow unnecessary equality comparisons against boolean literals',
recommended: 'strict',
requiresTypeChecking: true,
},
fixable: 'code',
messages: {
comparingNullableToFalse: 'This expression unnecessarily compares a nullable boolean value to false instead of using the ?? operator to provide a default.',
comparingNullableToTrueDirect: 'This expression unnecessarily compares a nullable boolean value to true instead of using it directly.',
comparingNullableToTrueNegated: 'This expression unnecessarily compares a nullable boolean value to true instead of negating it.',
direct: 'This expression unnecessarily compares a boolean value to a boolean instead of using it directly.',
negated: 'This expression unnecessarily compares a boolean value to a boolean instead of negating it.',
noStrictNullCheck: 'This rule requires the `strictNullChecks` compiler option to be turned on to function correctly.',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
allowComparingNullableBooleansToFalse: {
type: 'boolean',
description: 'Whether to allow comparisons between nullable boolean variables and `false`.',
},
allowComparingNullableBooleansToTrue: {
type: 'boolean',
description: 'Whether to allow comparisons between nullable boolean variables and `true`.',
},
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: {
type: 'boolean',
description: 'Unless this is set to `true`, the rule will error on every file whose `tsconfig.json` does _not_ have the `strictNullChecks` compiler option (or `strict`) set to `true`.',
},
},
},
],
},
defaultOptions: [
{
allowComparingNullableBooleansToFalse: true,
allowComparingNullableBooleansToTrue: true,
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false,
},
],
create(context, [options]) {
const services = (0, util_1.getParserServices)(context);
const checker = services.program.getTypeChecker();
const compilerOptions = services.program.getCompilerOptions();
const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks');
if (!isStrictNullChecks &&
options.allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing !== true) {
context.report({
loc: {
start: { column: 0, line: 0 },
end: { column: 0, line: 0 },
},
messageId: 'noStrictNullCheck',
});
}
function getBooleanComparison(node) {
const comparison = deconstructComparison(node);
if (!comparison) {
return undefined;
}
const { constraintType, isTypeParameter } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(comparison.expression));
if (isTypeParameter && constraintType == null) {
return undefined;
}
if (isBooleanType(constraintType)) {
return {
...comparison,
expressionIsNullableBoolean: false,
};
}
if (isNullableBoolean(constraintType)) {
return {
...comparison,
expressionIsNullableBoolean: true,
};
}
return undefined;
}
function isBooleanType(expressionType) {
return tsutils.isTypeFlagSet(expressionType, ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral);
}
/**
* checks if the expressionType is a union that
* 1) contains at least one nullish type (null or undefined)
* 2) contains at least once boolean type (true or false or boolean)
* 3) does not contain any types besides nullish and boolean types
*/
function isNullableBoolean(expressionType) {
if (!expressionType.isUnion()) {
return false;
}
const { types } = expressionType;
const nonNullishTypes = types.filter(type => !tsutils.isTypeFlagSet(type, ts.TypeFlags.Undefined | ts.TypeFlags.Null));
const hasNonNullishType = nonNullishTypes.length > 0;
if (!hasNonNullishType) {
return false;
}
const hasNullableType = nonNullishTypes.length < types.length;
if (!hasNullableType) {
return false;
}
const allNonNullishTypesAreBoolean = nonNullishTypes.every(isBooleanType);
if (!allNonNullishTypesAreBoolean) {
return false;
}
return true;
}
function deconstructComparison(node) {
const comparisonType = getEqualsKind(node.operator);
if (!comparisonType) {
return undefined;
}
for (const [against, expression] of [
[node.right, node.left],
[node.left, node.right],
]) {
if (against.type !== utils_1.AST_NODE_TYPES.Literal ||
typeof against.value !== 'boolean') {
continue;
}
const booleanLiteral = against.value ? 'true' : 'false';
const negated = !comparisonType.isPositive;
return {
booleanLiteral,
expression,
negated,
};
}
return undefined;
}
function nodeIsUnaryNegation(node) {
return (node.type === utils_1.AST_NODE_TYPES.UnaryExpression && node.operator === '!');
}
return {
BinaryExpression(node) {
const comparison = getBooleanComparison(node);
if (comparison == null) {
return;
}
if (comparison.expressionIsNullableBoolean) {
if (comparison.booleanLiteral === 'true' &&
options.allowComparingNullableBooleansToTrue) {
return;
}
if (comparison.booleanLiteral === 'false' &&
options.allowComparingNullableBooleansToFalse) {
return;
}
}
context.report({
node,
messageId: comparison.expressionIsNullableBoolean
? comparison.booleanLiteral === 'true'
? comparison.negated
? 'comparingNullableToTrueNegated'
: 'comparingNullableToTrueDirect'
: 'comparingNullableToFalse'
: comparison.negated
? 'negated'
: 'direct',
fix(fixer) {
const isWrappedInUnaryNegation = nodeIsUnaryNegation(node.parent);
const mutatedNode = isWrappedInUnaryNegation ? node.parent : node;
// Whether the truth table of the overall expression being replaced
// is negated, _ignoring the nullish cases_.
const isOverallNegated = booleanXor(isWrappedInUnaryNegation, comparison.negated, comparison.booleanLiteral === 'false');
// we'll build up the replacement text from the compared expression outwards.
let replacementText = context.sourceCode.getText(comparison.expression);
let mayNeedParentheses = !(0, util_1.isStrongPrecedenceNode)(comparison.expression);
const fixWouldReturnExpressionDirectly = !isOverallNegated && comparison.expressionIsNullableBoolean;
if (fixWouldReturnExpressionDirectly &&
!(0, util_1.isConditionalTest)(mutatedNode)) {
if (mayNeedParentheses) {
replacementText = parenthesize(replacementText);
}
replacementText = `${replacementText} ?? false`;
mayNeedParentheses = true;
}
else {
// In maybeNullish === false, nullish values have the same truth table
// as `true`.
if (comparison.expressionIsNullableBoolean &&
comparison.booleanLiteral === 'false') {
if (mayNeedParentheses) {
replacementText = parenthesize(replacementText);
}
replacementText = `${replacementText} ?? true`;
mayNeedParentheses = true;
}
if (isOverallNegated) {
if (mayNeedParentheses) {
replacementText = parenthesize(replacementText);
}
replacementText = `!${replacementText}`;
mayNeedParentheses = false;
}
}
if (mayNeedParentheses && (0, util_1.isWeakPrecedenceParent)(mutatedNode)) {
replacementText = parenthesize(replacementText);
}
return fixer.replaceText(mutatedNode, replacementText);
},
});
},
};
},
});
function getEqualsKind(operator) {
switch (operator) {
case '!=':
return {
isPositive: false,
isStrict: false,
};
case '!==':
return {
isPositive: false,
isStrict: true,
};
case '==':
return {
isPositive: true,
isStrict: false,
};
case '===':
return {
isPositive: true,
isStrict: true,
};
default:
return undefined;
}
}
function booleanXor(arg0, ...args) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion
return args.reduce((acc, curr) => acc !== Boolean(curr), Boolean(arg0));
}
function parenthesize(text) {
return `(${text})`;
}

View File

@@ -0,0 +1,141 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const util = __importStar(require("../core/util.cjs"));
const error = () => {
const Sizable = {
string: { unit: "توکي", verb: "ولري" },
file: { unit: "بایټس", verb: "ولري" },
array: { unit: "توکي", verb: "ولري" },
set: { unit: "توکي", verb: "ولري" },
};
function getSizing(origin) {
return Sizable[origin] ?? null;
}
const FormatDictionary = {
regex: "ورودي",
email: "بریښنالیک",
url: "یو آر ال",
emoji: "ایموجي",
uuid: "UUID",
uuidv4: "UUIDv4",
uuidv6: "UUIDv6",
nanoid: "nanoid",
guid: "GUID",
cuid: "cuid",
cuid2: "cuid2",
ulid: "ULID",
xid: "XID",
ksuid: "KSUID",
datetime: "نیټه او وخت",
date: "نېټه",
time: "وخت",
duration: "موده",
ipv4: "د IPv4 پته",
ipv6: "د IPv6 پته",
cidrv4: "د IPv4 ساحه",
cidrv6: "د IPv6 ساحه",
base64: "base64-encoded متن",
base64url: "base64url-encoded متن",
json_string: "JSON متن",
e164: "د E.164 شمېره",
jwt: "JWT",
template_literal: "ورودي",
};
const TypeDictionary = {
nan: "NaN",
number: "عدد",
array: "ارې",
};
return (issue) => {
switch (issue.code) {
case "invalid_type": {
const expected = TypeDictionary[issue.expected] ?? issue.expected;
const receivedType = util.parsedType(issue.input);
const received = TypeDictionary[receivedType] ?? receivedType;
if (/^[A-Z]/.test(issue.expected)) {
return `ناسم ورودي: باید instanceof ${issue.expected} وای, مګر ${received} ترلاسه شو`;
}
return `ناسم ورودي: باید ${expected} وای, مګر ${received} ترلاسه شو`;
}
case "invalid_value":
if (issue.values.length === 1) {
return `ناسم ورودي: باید ${util.stringifyPrimitive(issue.values[0])} وای`;
}
return `ناسم انتخاب: باید یو له ${util.joinValues(issue.values, "|")} څخه وای`;
case "too_big": {
const adj = issue.inclusive ? "<=" : "<";
const sizing = getSizing(issue.origin);
if (sizing) {
return `ډیر لوی: ${issue.origin ?? "ارزښت"} باید ${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 ? "کلیډونه" : "کلیډ"}: ${util.joinValues(issue.keys, ", ")}`;
case "invalid_key":
return `ناسم کلیډ په ${issue.origin} کې`;
case "invalid_union":
return `ناسمه ورودي`;
case "invalid_element":
return `ناسم عنصر په ${issue.origin} کې`;
default:
return `ناسمه ورودي`;
}
};
};
function default_1() {
return {
localeError: error(),
};
}
module.exports = exports.default;