WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
import type { AST_NODE_TYPES, AST_TOKEN_TYPES } from '../ts-estree';
|
||||
import type { ClassicConfig } from './Config';
|
||||
import type { Linter } from './Linter';
|
||||
import type { ParserOptions } from './ParserOptions';
|
||||
import type { ReportDescriptorMessageData, RuleCreateFunction, RuleModule, SharedConfigurationSettings } from './Rule';
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface ValidTestCase<Options extends readonly unknown[]> {
|
||||
/**
|
||||
* Code for the test case.
|
||||
*/
|
||||
readonly code: string;
|
||||
/**
|
||||
* Environments for the test case.
|
||||
*/
|
||||
readonly env?: Readonly<Linter.EnvironmentConfig>;
|
||||
/**
|
||||
* The fake filename for the test case. Useful for rules that make assertion about filenames.
|
||||
*/
|
||||
readonly filename?: string;
|
||||
/**
|
||||
* The additional global variables.
|
||||
*/
|
||||
readonly globals?: Readonly<Linter.GlobalsConfig>;
|
||||
/**
|
||||
* Name for the test case.
|
||||
*/
|
||||
readonly name?: string;
|
||||
/**
|
||||
* Run this case exclusively for debugging in supported test frameworks.
|
||||
*/
|
||||
readonly only?: boolean;
|
||||
/**
|
||||
* Options for the test case.
|
||||
*/
|
||||
readonly options?: Readonly<Options>;
|
||||
/**
|
||||
* The absolute path for the parser.
|
||||
*/
|
||||
readonly parser?: string;
|
||||
/**
|
||||
* Options for the parser.
|
||||
*/
|
||||
readonly parserOptions?: Readonly<ParserOptions>;
|
||||
/**
|
||||
* Settings for the test case.
|
||||
*/
|
||||
readonly settings?: Readonly<SharedConfigurationSettings>;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface SuggestionOutput<MessageIds extends string> {
|
||||
/**
|
||||
* The data used to fill the message template.
|
||||
*/
|
||||
readonly data?: ReportDescriptorMessageData;
|
||||
/**
|
||||
* Reported message ID.
|
||||
*/
|
||||
readonly messageId: MessageIds;
|
||||
/**
|
||||
* NOTE: Suggestions will be applied as a stand-alone change, without triggering multi-pass fixes.
|
||||
* Each individual error has its own suggestion, so you have to show the correct, _isolated_ output for each suggestion.
|
||||
*/
|
||||
readonly output: string;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface InvalidTestCase<MessageIds extends string, Options extends readonly unknown[]> extends ValidTestCase<Options> {
|
||||
/**
|
||||
* Expected errors.
|
||||
*/
|
||||
readonly errors: readonly TestCaseError<MessageIds>[];
|
||||
/**
|
||||
* The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested.
|
||||
*/
|
||||
readonly output?: string | string[] | null;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface TestCaseError<MessageIds extends string> {
|
||||
/**
|
||||
* The 1-based column number of the reported start location.
|
||||
*/
|
||||
readonly column?: number;
|
||||
/**
|
||||
* The data used to fill the message template.
|
||||
*/
|
||||
readonly data?: ReportDescriptorMessageData;
|
||||
/**
|
||||
* The 1-based column number of the reported end location.
|
||||
*/
|
||||
readonly endColumn?: number;
|
||||
/**
|
||||
* The 1-based line number of the reported end location.
|
||||
*/
|
||||
readonly endLine?: number;
|
||||
/**
|
||||
* The 1-based line number of the reported start location.
|
||||
*/
|
||||
readonly line?: number;
|
||||
/**
|
||||
* Reported message ID.
|
||||
*/
|
||||
readonly messageId: MessageIds;
|
||||
/**
|
||||
* Reported suggestions.
|
||||
*/
|
||||
readonly suggestions?: readonly SuggestionOutput<MessageIds>[] | null;
|
||||
/**
|
||||
* The type of the reported AST node.
|
||||
*/
|
||||
readonly type?: AST_NODE_TYPES | AST_TOKEN_TYPES;
|
||||
}
|
||||
/**
|
||||
* @param text a string describing the rule
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export type RuleTesterTestFrameworkFunction = (text: string, callback: () => void) => void;
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface RunTests<MessageIds extends string, Options extends readonly unknown[]> {
|
||||
readonly invalid: readonly InvalidTestCase<MessageIds, Options>[];
|
||||
readonly valid: readonly (string | ValidTestCase<Options>)[];
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export interface RuleTesterConfig extends ClassicConfig.Config {
|
||||
readonly parser: string;
|
||||
readonly parserOptions?: Readonly<ParserOptions>;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
declare class RuleTesterBase {
|
||||
/**
|
||||
* Creates a new instance of RuleTester.
|
||||
* @param testerConfig extra configuration for the tester
|
||||
*/
|
||||
constructor(testerConfig?: RuleTesterConfig);
|
||||
/**
|
||||
* Adds a new rule test to execute.
|
||||
* @param ruleName The name of the rule to run.
|
||||
* @param rule The rule to test.
|
||||
* @param tests The collection of tests to run.
|
||||
*/
|
||||
run<MessageIds extends string, Options extends readonly unknown[]>(ruleName: string, rule: RuleModule<MessageIds, Options>, tests: RunTests<MessageIds, Options>): void;
|
||||
/**
|
||||
* If you supply a value to this property, the rule tester will call this instead of using the version defined on
|
||||
* the global namespace.
|
||||
*/
|
||||
static get describe(): RuleTesterTestFrameworkFunction;
|
||||
static set describe(value: RuleTesterTestFrameworkFunction | undefined);
|
||||
/**
|
||||
* If you supply a value to this property, the rule tester will call this instead of using the version defined on
|
||||
* the global namespace.
|
||||
*/
|
||||
static get it(): RuleTesterTestFrameworkFunction;
|
||||
static set it(value: RuleTesterTestFrameworkFunction | undefined);
|
||||
/**
|
||||
* If you supply a value to this property, the rule tester will call this instead of using the version defined on
|
||||
* the global namespace.
|
||||
*/
|
||||
static get itOnly(): RuleTesterTestFrameworkFunction;
|
||||
static set itOnly(value: RuleTesterTestFrameworkFunction | undefined);
|
||||
/**
|
||||
* Define a rule for one particular run of tests.
|
||||
*/
|
||||
defineRule<MessageIds extends string, Options extends readonly unknown[]>(name: string, rule: RuleCreateFunction<MessageIds, Options> | RuleModule<MessageIds, Options>): void;
|
||||
}
|
||||
declare const RuleTester_base: typeof RuleTesterBase;
|
||||
/**
|
||||
* @deprecated Use `@typescript-eslint/rule-tester` instead.
|
||||
*/
|
||||
export declare class RuleTester extends RuleTester_base {
|
||||
}
|
||||
export {};
|
||||
@@ -0,0 +1,97 @@
|
||||
import { CommentDirectiveType } from "#enums/commentDirectiveType";
|
||||
import { LanguageVariant } from "#enums/languageVariant";
|
||||
import { RegularExpressionFlags } from "#enums/regularExpressionFlags";
|
||||
import { ScriptTarget } from "#enums/scriptTarget";
|
||||
import { SyntaxKind } from "#enums/syntaxKind";
|
||||
import { TokenFlags } from "#enums/tokenFlags";
|
||||
import type { JsxTokenSyntaxKind, KeywordSyntaxKind } from "./ast.ts";
|
||||
export type JSDocTokenKind = SyntaxKind.EndOfFile | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.OpenParenToken | SyntaxKind.CloseParenToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.HashToken | SyntaxKind.Unknown | KeywordSyntaxKind;
|
||||
export interface CommentDirective {
|
||||
range: {
|
||||
pos: number;
|
||||
end: number;
|
||||
};
|
||||
type: CommentDirectiveType;
|
||||
}
|
||||
export declare function tokenIsIdentifierOrKeyword(token: SyntaxKind): boolean;
|
||||
export declare function tokenIsIdentifierOrKeywordOrGreaterThan(token: SyntaxKind): boolean;
|
||||
export interface Scanner {
|
||||
getTokenFullStart(): number;
|
||||
getToken(): SyntaxKind;
|
||||
getTokenStart(): number;
|
||||
getTokenEnd(): number;
|
||||
getTokenText(): string;
|
||||
getTokenValue(): string;
|
||||
hasUnicodeEscape(): boolean;
|
||||
hasExtendedUnicodeEscape(): boolean;
|
||||
hasPrecedingLineBreak(): boolean;
|
||||
hasPrecedingJSDocComment(): boolean;
|
||||
hasPrecedingJSDocLeadingAsterisks(): boolean;
|
||||
hasPrecedingJSDocWithDeprecatedTag(): boolean;
|
||||
hasPrecedingJSDocWithSeeOrLink(): boolean;
|
||||
isIdentifier(): boolean;
|
||||
isReservedWord(): boolean;
|
||||
isUnterminated(): boolean;
|
||||
getNumericLiteralFlags(): TokenFlags;
|
||||
getCommentDirectives(): CommentDirective[] | undefined;
|
||||
getTokenFlags(): TokenFlags;
|
||||
reScanGreaterToken(): SyntaxKind;
|
||||
reScanSlashToken(): SyntaxKind;
|
||||
reScanAsteriskEqualsToken(): SyntaxKind;
|
||||
reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind;
|
||||
reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind;
|
||||
scanJsxIdentifier(): SyntaxKind;
|
||||
scanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxAttributeValue(): SyntaxKind;
|
||||
reScanJsxToken(allowMultilineJsxText?: boolean): JsxTokenSyntaxKind;
|
||||
reScanLessThanToken(): SyntaxKind;
|
||||
reScanHashToken(): SyntaxKind;
|
||||
reScanQuestionToken(): SyntaxKind;
|
||||
reScanInvalidIdentifier(): SyntaxKind;
|
||||
scanJsxToken(): JsxTokenSyntaxKind;
|
||||
scanJsDocToken(): JSDocTokenKind;
|
||||
scanJSDocCommentTextToken(inBackticks: boolean): JSDocTokenKind | SyntaxKind.JSDocCommentTextToken;
|
||||
scan(): SyntaxKind;
|
||||
getText(): string;
|
||||
clearCommentDirectives(): void;
|
||||
setText(text: string | undefined, start?: number, length?: number): void;
|
||||
setLanguageVariant(variant: LanguageVariant): void;
|
||||
resetTokenState(pos: number): void;
|
||||
setSkipJsDocLeadingAsterisks(skip: boolean): void;
|
||||
lookAhead<T>(callback: () => T): T;
|
||||
scanRange<T>(start: number, length: number, callback: () => T): T;
|
||||
tryScan<T>(callback: () => T): T;
|
||||
}
|
||||
export declare const textToKeywordObj: Record<string, KeywordSyntaxKind>;
|
||||
export declare function isUnicodeIdentifierStart(code: number): boolean;
|
||||
export declare function tokenToString(t: SyntaxKind): string | undefined;
|
||||
export declare function stringToToken(s: string): SyntaxKind | undefined;
|
||||
export declare function characterCodeToRegularExpressionFlag(ch: number): RegularExpressionFlags | undefined;
|
||||
export declare function computeLineStarts(text: string): number[];
|
||||
export declare function isWhiteSpaceLike(ch: number): boolean;
|
||||
export declare function isWhiteSpaceSingleLine(ch: number): boolean;
|
||||
export declare function isLineBreak(ch: number): boolean;
|
||||
export declare function couldStartTrivia(text: string, pos: number): boolean;
|
||||
export declare function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments?: boolean, inJSDoc?: boolean): number;
|
||||
export type CommentKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia;
|
||||
export interface CommentRange {
|
||||
pos: number;
|
||||
end: number;
|
||||
hasTrailingNewLine?: boolean;
|
||||
kind: CommentKind;
|
||||
}
|
||||
export declare function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined;
|
||||
export declare function forEachLeadingCommentRange<U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined;
|
||||
export declare function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined;
|
||||
export declare function forEachTrailingCommentRange<U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined;
|
||||
export declare function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined;
|
||||
export declare function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T, initial: U): U | undefined;
|
||||
export declare function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined;
|
||||
export declare function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined;
|
||||
export declare function getShebang(text: string): string | undefined;
|
||||
export declare function isIdentifierStart(ch: number, _languageVersion?: ScriptTarget): boolean;
|
||||
export declare function isIdentifierPart(ch: number, _languageVersion?: ScriptTarget, identifierVariant?: LanguageVariant): boolean;
|
||||
export declare function isIdentifierText(name: string, _languageVersion?: ScriptTarget, identifierVariant?: LanguageVariant): boolean;
|
||||
export declare function utf16EncodeAsString(codePoint: number): string;
|
||||
export declare function createScanner(skipTrivia: boolean, languageVariant?: LanguageVariant, textInitial?: string, start?: number, length?: number): Scanner;
|
||||
//# sourceMappingURL=scanner.d.ts.map
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var proc = require('child_process')
|
||||
var os = require('os')
|
||||
var path = require('path')
|
||||
|
||||
if (!buildFromSource()) {
|
||||
proc.exec('node-gyp-build-test', function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
if (verbose()) console.error(stderr)
|
||||
preinstall()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
preinstall()
|
||||
}
|
||||
|
||||
function build () {
|
||||
var win32 = os.platform() === 'win32'
|
||||
var shell = win32
|
||||
var args = [win32 ? 'node-gyp.cmd' : 'node-gyp', 'rebuild']
|
||||
|
||||
try {
|
||||
var pkg = require('node-gyp/package.json')
|
||||
args = [
|
||||
process.execPath,
|
||||
path.join(require.resolve('node-gyp/package.json'), '..', typeof pkg.bin === 'string' ? pkg.bin : pkg.bin['node-gyp']),
|
||||
'rebuild'
|
||||
]
|
||||
shell = false
|
||||
} catch (_) {}
|
||||
|
||||
proc.spawn(args[0], args.slice(1), { stdio: 'inherit', shell, windowsHide: true }).on('exit', function (code) {
|
||||
if (code || !process.argv[3]) process.exit(code)
|
||||
exec(process.argv[3]).on('exit', function (code) {
|
||||
process.exit(code)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function preinstall () {
|
||||
if (!process.argv[2]) return build()
|
||||
exec(process.argv[2]).on('exit', function (code) {
|
||||
if (code) process.exit(code)
|
||||
build()
|
||||
})
|
||||
}
|
||||
|
||||
function exec (cmd) {
|
||||
if (process.platform !== 'win32') {
|
||||
var shell = os.platform() === 'android' ? 'sh' : true
|
||||
return proc.spawn(cmd, [], {
|
||||
shell,
|
||||
stdio: 'inherit'
|
||||
})
|
||||
}
|
||||
|
||||
return proc.spawn(cmd, [], {
|
||||
windowsVerbatimArguments: true,
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
windowsHide: true
|
||||
})
|
||||
}
|
||||
|
||||
function buildFromSource () {
|
||||
return hasFlag('--build-from-source') || process.env.npm_config_build_from_source === 'true'
|
||||
}
|
||||
|
||||
function verbose () {
|
||||
return hasFlag('--verbose') || process.env.npm_config_loglevel === 'verbose'
|
||||
}
|
||||
|
||||
// TODO (next major): remove in favor of env.npm_config_* which works since npm
|
||||
// 0.1.8 while npm_config_argv will stop working in npm 7. See npm/rfcs#90
|
||||
function hasFlag (flag) {
|
||||
if (!process.env.npm_config_argv) return false
|
||||
|
||||
try {
|
||||
return JSON.parse(process.env.npm_config_argv).original.indexOf(flag) !== -1
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 base-x contributors
|
||||
Copyright (c) 2014-2018 The Bitcoin Core developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,182 @@
|
||||
"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-inferrable-types',
|
||||
meta: {
|
||||
type: 'suggestion',
|
||||
docs: {
|
||||
description: 'Disallow explicit type declarations for variables or parameters initialized to a number, string, or boolean',
|
||||
recommended: 'stylistic',
|
||||
},
|
||||
fixable: 'code',
|
||||
messages: {
|
||||
noInferrableType: 'Type {{type}} trivially inferred from a {{type}} literal, remove type annotation.',
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
ignoreParameters: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore function parameters.',
|
||||
},
|
||||
ignoreProperties: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore class properties.',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultOptions: [
|
||||
{
|
||||
ignoreParameters: false,
|
||||
ignoreProperties: false,
|
||||
},
|
||||
],
|
||||
create(context, [{ ignoreParameters, ignoreProperties }]) {
|
||||
function isFunctionCall(init, callName) {
|
||||
const node = (0, util_1.skipChainExpression)(init);
|
||||
return (node.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
||||
node.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
|
||||
node.callee.name === callName);
|
||||
}
|
||||
function isLiteral(init, typeName) {
|
||||
return (init.type === utils_1.AST_NODE_TYPES.Literal && typeof init.value === typeName);
|
||||
}
|
||||
function isIdentifier(init, ...names) {
|
||||
return (init.type === utils_1.AST_NODE_TYPES.Identifier && names.includes(init.name));
|
||||
}
|
||||
function hasUnaryPrefix(init, ...operators) {
|
||||
return (init.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
||||
operators.includes(init.operator));
|
||||
}
|
||||
const keywordMap = {
|
||||
[utils_1.AST_NODE_TYPES.TSBigIntKeyword]: 'bigint',
|
||||
[utils_1.AST_NODE_TYPES.TSBooleanKeyword]: 'boolean',
|
||||
[utils_1.AST_NODE_TYPES.TSNullKeyword]: 'null',
|
||||
[utils_1.AST_NODE_TYPES.TSNumberKeyword]: 'number',
|
||||
[utils_1.AST_NODE_TYPES.TSStringKeyword]: 'string',
|
||||
[utils_1.AST_NODE_TYPES.TSSymbolKeyword]: 'symbol',
|
||||
[utils_1.AST_NODE_TYPES.TSUndefinedKeyword]: 'undefined',
|
||||
};
|
||||
/**
|
||||
* Returns whether a node has an inferrable value or not
|
||||
*/
|
||||
function isInferrable(annotation, init) {
|
||||
switch (annotation.type) {
|
||||
case utils_1.AST_NODE_TYPES.TSBigIntKeyword: {
|
||||
// note that bigint cannot have + prefixed to it
|
||||
const unwrappedInit = hasUnaryPrefix(init, '-')
|
||||
? init.argument
|
||||
: init;
|
||||
return (isFunctionCall(unwrappedInit, 'BigInt') ||
|
||||
unwrappedInit.type === utils_1.AST_NODE_TYPES.Literal);
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSBooleanKeyword:
|
||||
return (hasUnaryPrefix(init, '!') ||
|
||||
isFunctionCall(init, 'Boolean') ||
|
||||
isLiteral(init, 'boolean'));
|
||||
case utils_1.AST_NODE_TYPES.TSNumberKeyword: {
|
||||
const unwrappedInit = hasUnaryPrefix(init, '+', '-')
|
||||
? init.argument
|
||||
: init;
|
||||
return (isIdentifier(unwrappedInit, 'Infinity', 'NaN') ||
|
||||
isFunctionCall(unwrappedInit, 'Number') ||
|
||||
isLiteral(unwrappedInit, 'number'));
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSNullKeyword:
|
||||
return init.type === utils_1.AST_NODE_TYPES.Literal && init.value == null;
|
||||
case utils_1.AST_NODE_TYPES.TSStringKeyword:
|
||||
return (isFunctionCall(init, 'String') ||
|
||||
isLiteral(init, 'string') ||
|
||||
init.type === utils_1.AST_NODE_TYPES.TemplateLiteral);
|
||||
case utils_1.AST_NODE_TYPES.TSSymbolKeyword:
|
||||
return isFunctionCall(init, 'Symbol');
|
||||
case utils_1.AST_NODE_TYPES.TSTypeReference: {
|
||||
if (annotation.typeName.type === utils_1.AST_NODE_TYPES.Identifier &&
|
||||
annotation.typeName.name === 'RegExp') {
|
||||
const isRegExpLiteral = init.type === utils_1.AST_NODE_TYPES.Literal &&
|
||||
init.value instanceof RegExp;
|
||||
const isRegExpNewCall = init.type === utils_1.AST_NODE_TYPES.NewExpression &&
|
||||
init.callee.type === utils_1.AST_NODE_TYPES.Identifier &&
|
||||
init.callee.name === 'RegExp';
|
||||
const isRegExpCall = isFunctionCall(init, 'RegExp');
|
||||
return isRegExpLiteral || isRegExpCall || isRegExpNewCall;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSUndefinedKeyword:
|
||||
return (hasUnaryPrefix(init, 'void') || isIdentifier(init, 'undefined'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Reports an inferrable type declaration, if any
|
||||
*/
|
||||
function reportInferrableType(node, typeNode, initNode) {
|
||||
if (!typeNode || !initNode) {
|
||||
return;
|
||||
}
|
||||
if (!isInferrable(typeNode.typeAnnotation, initNode)) {
|
||||
return;
|
||||
}
|
||||
const type = typeNode.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference
|
||||
? // TODO - if we add more references
|
||||
'RegExp'
|
||||
: keywordMap[typeNode.typeAnnotation.type];
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noInferrableType',
|
||||
data: {
|
||||
type,
|
||||
},
|
||||
*fix(fixer) {
|
||||
if ((node.type === utils_1.AST_NODE_TYPES.AssignmentPattern &&
|
||||
node.left.optional) ||
|
||||
(node.type === utils_1.AST_NODE_TYPES.PropertyDefinition && node.definite)) {
|
||||
yield fixer.remove((0, util_1.nullThrows)(context.sourceCode.getTokenBefore(typeNode), util_1.NullThrowsReasons.MissingToken('token before', 'type node')));
|
||||
}
|
||||
yield fixer.remove(typeNode);
|
||||
},
|
||||
});
|
||||
}
|
||||
function inferrableVariableVisitor(node) {
|
||||
reportInferrableType(node, node.id.typeAnnotation, node.init);
|
||||
}
|
||||
function inferrableParameterVisitor(node) {
|
||||
if (ignoreParameters) {
|
||||
return;
|
||||
}
|
||||
node.params.forEach(param => {
|
||||
if (param.type === utils_1.AST_NODE_TYPES.TSParameterProperty) {
|
||||
param = param.parameter;
|
||||
}
|
||||
if (param.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
|
||||
reportInferrableType(param, param.left.typeAnnotation, param.right);
|
||||
}
|
||||
});
|
||||
}
|
||||
function inferrablePropertyVisitor(node) {
|
||||
// We ignore `readonly` because of Microsoft/TypeScript#14416
|
||||
// Essentially a readonly property without a type
|
||||
// will result in its value being the type, leading to
|
||||
// compile errors if the type is stripped.
|
||||
if (ignoreProperties || node.readonly || node.optional) {
|
||||
return;
|
||||
}
|
||||
reportInferrableType(node, node.typeAnnotation, node.value);
|
||||
}
|
||||
return {
|
||||
AccessorProperty: inferrablePropertyVisitor,
|
||||
ArrowFunctionExpression: inferrableParameterVisitor,
|
||||
FunctionDeclaration: inferrableParameterVisitor,
|
||||
FunctionExpression: inferrableParameterVisitor,
|
||||
PropertyDefinition: inferrablePropertyVisitor,
|
||||
VariableDeclarator: inferrableVariableVisitor,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,614 @@
|
||||
"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 });
|
||||
exports.analyzeChain = analyzeChain;
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const ts_api_utils_1 = require("ts-api-utils");
|
||||
const ts = __importStar(require("typescript"));
|
||||
const util_1 = require("../../util");
|
||||
const checkNullishAndReport_1 = require("./checkNullishAndReport");
|
||||
const compareNodes_1 = require("./compareNodes");
|
||||
const gatherLogicalOperands_1 = require("./gatherLogicalOperands");
|
||||
function includesType(parserServices, node, typeFlagIn) {
|
||||
const typeFlag = typeFlagIn | ts.TypeFlags.Any | ts.TypeFlags.Unknown;
|
||||
const types = (0, ts_api_utils_1.unionConstituents)(parserServices.getTypeAtLocation(node));
|
||||
for (const type of types) {
|
||||
if ((0, util_1.isTypeFlagSet)(type, typeFlag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isValidAndLastChainOperand(ComparisonValueType, comparisonType, parserServices) {
|
||||
const type = parserServices.getTypeAtLocation(ComparisonValueType);
|
||||
const ANY_UNKNOWN_FLAGS = ts.TypeFlags.Any | ts.TypeFlags.Unknown;
|
||||
const types = (0, ts_api_utils_1.unionConstituents)(type);
|
||||
switch (comparisonType) {
|
||||
case gatherLogicalOperands_1.ComparisonType.Equal: {
|
||||
const isNullish = types.some(t => (0, util_1.isTypeFlagSet)(t, ANY_UNKNOWN_FLAGS | ts.TypeFlags.Null | ts.TypeFlags.Undefined));
|
||||
return !isNullish;
|
||||
}
|
||||
case gatherLogicalOperands_1.ComparisonType.StrictEqual: {
|
||||
const isUndefined = types.some(t => (0, util_1.isTypeFlagSet)(t, ANY_UNKNOWN_FLAGS | ts.TypeFlags.Undefined));
|
||||
return !isUndefined;
|
||||
}
|
||||
case gatherLogicalOperands_1.ComparisonType.NotStrictEqual: {
|
||||
return types.every(t => (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.Undefined));
|
||||
}
|
||||
case gatherLogicalOperands_1.ComparisonType.NotEqual: {
|
||||
return types.every(t => (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.Undefined | ts.TypeFlags.Null));
|
||||
}
|
||||
}
|
||||
}
|
||||
function isValidOrLastChainOperand(ComparisonValueType, comparisonType, parserServices) {
|
||||
const type = parserServices.getTypeAtLocation(ComparisonValueType);
|
||||
const ANY_UNKNOWN_FLAGS = ts.TypeFlags.Any | ts.TypeFlags.Unknown;
|
||||
const types = (0, ts_api_utils_1.unionConstituents)(type);
|
||||
switch (comparisonType) {
|
||||
case gatherLogicalOperands_1.ComparisonType.NotEqual: {
|
||||
const isNullish = types.some(t => (0, util_1.isTypeFlagSet)(t, ANY_UNKNOWN_FLAGS | ts.TypeFlags.Null | ts.TypeFlags.Undefined));
|
||||
return !isNullish;
|
||||
}
|
||||
case gatherLogicalOperands_1.ComparisonType.NotStrictEqual: {
|
||||
const isUndefined = types.some(t => (0, util_1.isTypeFlagSet)(t, ANY_UNKNOWN_FLAGS | ts.TypeFlags.Undefined));
|
||||
return !isUndefined;
|
||||
}
|
||||
case gatherLogicalOperands_1.ComparisonType.Equal:
|
||||
return types.every(t => (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.Undefined | ts.TypeFlags.Null));
|
||||
case gatherLogicalOperands_1.ComparisonType.StrictEqual:
|
||||
return types.every(t => (0, util_1.isTypeFlagSet)(t, ts.TypeFlags.Undefined));
|
||||
}
|
||||
}
|
||||
const analyzeAndChainOperand = (parserServices, operand, index, chain) => {
|
||||
switch (operand.comparisonType) {
|
||||
case gatherLogicalOperands_1.NullishComparisonType.Boolean:
|
||||
case gatherLogicalOperands_1.NullishComparisonType.NotEqualNullOrUndefined:
|
||||
return [operand];
|
||||
case gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualNull: {
|
||||
// handle `x !== null && x !== undefined`
|
||||
const nextOperand = chain.at(index + 1);
|
||||
if (nextOperand?.comparisonType ===
|
||||
gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualUndefined &&
|
||||
(0, compareNodes_1.compareNodes)(operand.comparedName, nextOperand.comparedName) ===
|
||||
compareNodes_1.NodeComparisonResult.Equal) {
|
||||
return [operand, nextOperand];
|
||||
}
|
||||
if (nextOperand &&
|
||||
!includesType(parserServices, operand.comparedName, ts.TypeFlags.Undefined)) {
|
||||
// we know the next operand is not an `undefined` check and that this
|
||||
// operand includes `undefined` - which means that making this an
|
||||
// optional chain would change the runtime behavior of the expression
|
||||
return [operand];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualUndefined: {
|
||||
// handle `x !== undefined && x !== null`
|
||||
const nextOperand = chain.at(index + 1);
|
||||
if (nextOperand?.comparisonType ===
|
||||
gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualNull &&
|
||||
(0, compareNodes_1.compareNodes)(operand.comparedName, nextOperand.comparedName) ===
|
||||
compareNodes_1.NodeComparisonResult.Equal) {
|
||||
return [operand, nextOperand];
|
||||
}
|
||||
if (includesType(parserServices, operand.comparedName, ts.TypeFlags.Null)) {
|
||||
// we know the next operand is not a `null` check and that this
|
||||
// operand includes `null` - which means that making this an
|
||||
// optional chain would change the runtime behavior of the expression
|
||||
return null;
|
||||
}
|
||||
return [operand];
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const analyzeOrChainOperand = (parserServices, operand, index, chain) => {
|
||||
switch (operand.comparisonType) {
|
||||
case gatherLogicalOperands_1.NullishComparisonType.NotBoolean:
|
||||
case gatherLogicalOperands_1.NullishComparisonType.EqualNullOrUndefined:
|
||||
return [operand];
|
||||
case gatherLogicalOperands_1.NullishComparisonType.StrictEqualNull: {
|
||||
// handle `x === null || x === undefined`
|
||||
const nextOperand = chain.at(index + 1);
|
||||
if (nextOperand?.comparisonType ===
|
||||
gatherLogicalOperands_1.NullishComparisonType.StrictEqualUndefined &&
|
||||
(0, compareNodes_1.compareNodes)(operand.comparedName, nextOperand.comparedName) ===
|
||||
compareNodes_1.NodeComparisonResult.Equal) {
|
||||
return [operand, nextOperand];
|
||||
}
|
||||
if (includesType(parserServices, operand.comparedName, ts.TypeFlags.Undefined)) {
|
||||
// we know the next operand is not an `undefined` check and that this
|
||||
// operand includes `undefined` - which means that making this an
|
||||
// optional chain would change the runtime behavior of the expression
|
||||
return null;
|
||||
}
|
||||
return [operand];
|
||||
}
|
||||
case gatherLogicalOperands_1.NullishComparisonType.StrictEqualUndefined: {
|
||||
// handle `x === undefined || x === null`
|
||||
const nextOperand = chain.at(index + 1);
|
||||
if (nextOperand?.comparisonType === gatherLogicalOperands_1.NullishComparisonType.StrictEqualNull &&
|
||||
(0, compareNodes_1.compareNodes)(operand.comparedName, nextOperand.comparedName) ===
|
||||
compareNodes_1.NodeComparisonResult.Equal) {
|
||||
return [operand, nextOperand];
|
||||
}
|
||||
if (includesType(parserServices, operand.comparedName, ts.TypeFlags.Null)) {
|
||||
// we know the next operand is not a `null` check and that this
|
||||
// operand includes `null` - which means that making this an
|
||||
// optional chain would change the runtime behavior of the expression
|
||||
return null;
|
||||
}
|
||||
return [operand];
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const resolveOperandSubset = (previousOperand, lastChainOperand) => {
|
||||
const isNameSubset = (0, compareNodes_1.compareNodes)(previousOperand.comparedName, lastChainOperand.comparedName) === compareNodes_1.NodeComparisonResult.Subset;
|
||||
if (lastChainOperand.yoda !== gatherLogicalOperands_1.Yoda.Unknown) {
|
||||
return {
|
||||
comparedName: lastChainOperand.comparedName,
|
||||
comparisonValue: lastChainOperand.comparisonValue,
|
||||
isSubset: isNameSubset,
|
||||
isYoda: lastChainOperand.yoda === gatherLogicalOperands_1.Yoda.Yes,
|
||||
};
|
||||
}
|
||||
const isValueSubset = (0, compareNodes_1.compareNodes)(previousOperand.comparedName, lastChainOperand.comparisonValue) === compareNodes_1.NodeComparisonResult.Subset;
|
||||
if (isNameSubset && !isValueSubset) {
|
||||
return {
|
||||
comparedName: lastChainOperand.comparedName,
|
||||
comparisonValue: lastChainOperand.comparisonValue,
|
||||
isSubset: true,
|
||||
isYoda: false,
|
||||
};
|
||||
}
|
||||
if (!isNameSubset && isValueSubset) {
|
||||
return {
|
||||
comparedName: lastChainOperand.comparisonValue,
|
||||
comparisonValue: lastChainOperand.comparedName,
|
||||
isSubset: true,
|
||||
isYoda: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
comparedName: lastChainOperand.comparisonValue,
|
||||
comparisonValue: lastChainOperand.comparisonValue,
|
||||
isSubset: false,
|
||||
isYoda: true,
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Returns the range that needs to be reported from the chain.
|
||||
* @param chain The chain of logical expressions.
|
||||
* @param boundary The boundary range that the range to report cannot fall outside.
|
||||
* @param sourceCode The source code to get tokens.
|
||||
* @returns The range to report.
|
||||
*/
|
||||
function getReportRange(chain, boundary, sourceCode) {
|
||||
const leftNode = chain[0].node;
|
||||
const rightNode = chain[chain.length - 1].node;
|
||||
let leftMost = (0, util_1.nullThrows)(sourceCode.getFirstToken(leftNode), util_1.NullThrowsReasons.MissingToken('any token', leftNode.type));
|
||||
let rightMost = (0, util_1.nullThrows)(sourceCode.getLastToken(rightNode), util_1.NullThrowsReasons.MissingToken('any token', rightNode.type));
|
||||
while (leftMost.range[0] > boundary[0]) {
|
||||
const token = sourceCode.getTokenBefore(leftMost);
|
||||
if (!token || !(0, util_1.isOpeningParenToken)(token) || token.range[0] < boundary[0]) {
|
||||
break;
|
||||
}
|
||||
leftMost = token;
|
||||
}
|
||||
while (rightMost.range[1] < boundary[1]) {
|
||||
const token = sourceCode.getTokenAfter(rightMost);
|
||||
if (!token || !(0, util_1.isClosingParenToken)(token) || token.range[1] > boundary[1]) {
|
||||
break;
|
||||
}
|
||||
rightMost = token;
|
||||
}
|
||||
return [leftMost.range[0], rightMost.range[1]];
|
||||
}
|
||||
function getReportDescriptor(sourceCode, parserServices, node, operator, options, subChain, lastChain) {
|
||||
const chain = lastChain ? [...subChain, lastChain] : subChain;
|
||||
const lastOperand = chain[chain.length - 1];
|
||||
let useSuggestionFixer;
|
||||
if (options.allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing ===
|
||||
true) {
|
||||
// user has opted-in to the unsafe behavior
|
||||
useSuggestionFixer = false;
|
||||
}
|
||||
// optional chain specifically will union `undefined` into the final type
|
||||
// so we need to make sure that there is at least one operand that includes
|
||||
// `undefined`, or else we're going to change the final type - which is
|
||||
// unsafe and might cause downstream type errors.
|
||||
else if (lastChain) {
|
||||
useSuggestionFixer = true;
|
||||
}
|
||||
else if (lastOperand.comparisonType === gatherLogicalOperands_1.NullishComparisonType.EqualNullOrUndefined ||
|
||||
lastOperand.comparisonType ===
|
||||
gatherLogicalOperands_1.NullishComparisonType.NotEqualNullOrUndefined ||
|
||||
lastOperand.comparisonType === gatherLogicalOperands_1.NullishComparisonType.StrictEqualUndefined ||
|
||||
lastOperand.comparisonType ===
|
||||
gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualUndefined ||
|
||||
(operator === '||' &&
|
||||
lastOperand.comparisonType === gatherLogicalOperands_1.NullishComparisonType.NotBoolean)) {
|
||||
// we know the last operand is an equality check - so the change in types
|
||||
// DOES NOT matter and will not change the runtime result or cause a type
|
||||
// check error
|
||||
useSuggestionFixer = false;
|
||||
}
|
||||
else {
|
||||
useSuggestionFixer = true;
|
||||
for (const operand of chain) {
|
||||
if (includesType(parserServices, operand.node, ts.TypeFlags.Undefined)) {
|
||||
useSuggestionFixer = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO - we could further reduce the false-positive rate of this check by
|
||||
// checking for cases where the change in types don't matter like
|
||||
// the test location of an if/while/etc statement.
|
||||
// but it's quite complex to do this without false-negatives, so
|
||||
// for now we'll just be over-eager with our matching.
|
||||
//
|
||||
// it's MUCH better to false-positive here and only provide a
|
||||
// suggestion fixer, rather than false-negative and autofix to
|
||||
// broken code.
|
||||
}
|
||||
// In its most naive form we could just slap `?.` for every single part of the
|
||||
// chain. However this would be undesirable because it'd create unnecessary
|
||||
// conditions in the user's code where there were none before - and it would
|
||||
// cause errors with rules like our `no-unnecessary-condition`.
|
||||
//
|
||||
// Instead we want to include the minimum number of `?.` required to correctly
|
||||
// unify the code into a single chain. Naively you might think that we can
|
||||
// just take the final operand add `?.` after the locations from the previous
|
||||
// operands - however this won't be correct either because earlier operands
|
||||
// can include a necessary `?.` that's not needed or included in a later
|
||||
// operand.
|
||||
//
|
||||
// So instead what we need to do is to start at the first operand and
|
||||
// iteratively diff it against the next operand, and add the difference to the
|
||||
// first operand.
|
||||
//
|
||||
// eg
|
||||
// `foo && foo.bar && foo.bar.baz?.bam && foo.bar.baz.bam()`
|
||||
// 1) `foo`
|
||||
// 2) diff(`foo`, `foo.bar`) = `.bar`
|
||||
// 3) result = `foo?.bar`
|
||||
// 4) diff(`foo.bar`, `foo.bar.baz?.bam`) = `.baz?.bam`
|
||||
// 5) result = `foo?.bar?.baz?.bam`
|
||||
// 6) diff(`foo.bar.baz?.bam`, `foo.bar.baz.bam()`) = `()`
|
||||
// 7) result = `foo?.bar?.baz?.bam?.()`
|
||||
const parts = [];
|
||||
for (const current of chain) {
|
||||
const nextOperand = flattenChainExpression(sourceCode, current.comparedName);
|
||||
const diff = nextOperand.slice(parts.length);
|
||||
if (diff.length > 0) {
|
||||
if (parts.length > 0) {
|
||||
// we need to make the first operand of the diff optional so it matches the
|
||||
// logic before merging
|
||||
// foo.bar && foo.bar.baz
|
||||
// diff = .baz
|
||||
// result = foo.bar?.baz
|
||||
diff[0].optional = true;
|
||||
}
|
||||
parts.push(...diff);
|
||||
}
|
||||
}
|
||||
let newCode = parts
|
||||
.map(part => {
|
||||
let str = '';
|
||||
if (part.optional) {
|
||||
str += '?.';
|
||||
}
|
||||
else {
|
||||
if (part.nonNull) {
|
||||
str += '!';
|
||||
}
|
||||
if (part.requiresDot) {
|
||||
str += '.';
|
||||
}
|
||||
}
|
||||
if (part.precedence !== util_1.OperatorPrecedence.Invalid &&
|
||||
part.precedence < util_1.OperatorPrecedence.Member) {
|
||||
str += `(${part.text})`;
|
||||
}
|
||||
else {
|
||||
str += part.text;
|
||||
}
|
||||
return str;
|
||||
})
|
||||
.join('');
|
||||
if (lastOperand.node.type === utils_1.AST_NODE_TYPES.BinaryExpression) {
|
||||
// retain the ending comparison for cases like
|
||||
// x && x.a != null
|
||||
// x && typeof x.a !== 'undefined'
|
||||
const operator = lastOperand.node.operator;
|
||||
const { left, right } = (() => {
|
||||
if (lastOperand.isYoda) {
|
||||
const unaryOperator = lastOperand.node.right.type === utils_1.AST_NODE_TYPES.UnaryExpression
|
||||
? `${lastOperand.node.right.operator} `
|
||||
: '';
|
||||
return {
|
||||
left: sourceCode.getText(lastOperand.node.left),
|
||||
right: unaryOperator + newCode,
|
||||
};
|
||||
}
|
||||
const unaryOperator = lastOperand.node.left.type === utils_1.AST_NODE_TYPES.UnaryExpression
|
||||
? `${lastOperand.node.left.operator} `
|
||||
: '';
|
||||
return {
|
||||
left: unaryOperator + newCode,
|
||||
right: sourceCode.getText(lastOperand.node.right),
|
||||
};
|
||||
})();
|
||||
newCode = `${left} ${operator} ${right}`;
|
||||
}
|
||||
else if (lastOperand.comparisonType === gatherLogicalOperands_1.NullishComparisonType.NotBoolean) {
|
||||
newCode = `!${newCode}`;
|
||||
}
|
||||
const reportRange = getReportRange(chain, node.range, sourceCode);
|
||||
const fix = fixer => {
|
||||
let unclosedParens = 0;
|
||||
const tokensInRange = sourceCode.getTokens(node, {
|
||||
filter: token => token.range[0] >= reportRange[0] && token.range[1] <= reportRange[1],
|
||||
});
|
||||
for (const token of tokensInRange) {
|
||||
if ((0, util_1.isOpeningParenToken)(token)) {
|
||||
unclosedParens++;
|
||||
}
|
||||
else if ((0, util_1.isClosingParenToken)(token)) {
|
||||
unclosedParens--;
|
||||
}
|
||||
}
|
||||
if (unclosedParens > 0 && reportRange[1] < node.range[1]) {
|
||||
const openParensOutsideRange = [];
|
||||
const unmatchedCloseParens = [];
|
||||
const tokensOutRange = sourceCode.getTokens(node, {
|
||||
filter: token => token.range[1] > reportRange[1],
|
||||
});
|
||||
for (const token of tokensOutRange) {
|
||||
if ((0, util_1.isOpeningParenToken)(token)) {
|
||||
openParensOutsideRange.push(token.range[0]);
|
||||
}
|
||||
if ((0, util_1.isClosingParenToken)(token)) {
|
||||
if (openParensOutsideRange.length > 0) {
|
||||
openParensOutsideRange.pop();
|
||||
}
|
||||
else {
|
||||
unmatchedCloseParens.push(token.range[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
let leftCode = sourceCode.getText(node);
|
||||
unmatchedCloseParens.reverse();
|
||||
for (const unmatchedParenIndex of unmatchedCloseParens) {
|
||||
leftCode =
|
||||
leftCode.slice(0, unmatchedParenIndex) +
|
||||
leftCode.slice(unmatchedParenIndex + 1);
|
||||
}
|
||||
leftCode = leftCode.slice(reportRange[1]);
|
||||
return fixer.replaceTextRange(node.range, newCode + leftCode);
|
||||
}
|
||||
return fixer.replaceTextRange(reportRange, newCode);
|
||||
};
|
||||
return {
|
||||
loc: {
|
||||
end: sourceCode.getLocFromIndex(reportRange[1]),
|
||||
start: sourceCode.getLocFromIndex(reportRange[0]),
|
||||
},
|
||||
messageId: 'preferOptionalChain',
|
||||
...(0, util_1.getFixOrSuggest)({
|
||||
fixOrSuggest: useSuggestionFixer ? 'suggest' : 'fix',
|
||||
suggestion: {
|
||||
fix,
|
||||
messageId: 'optionalChainSuggest',
|
||||
},
|
||||
}),
|
||||
};
|
||||
function flattenChainExpression(sourceCode, node) {
|
||||
switch (node.type) {
|
||||
case utils_1.AST_NODE_TYPES.ChainExpression:
|
||||
return flattenChainExpression(sourceCode, node.expression);
|
||||
case utils_1.AST_NODE_TYPES.CallExpression: {
|
||||
const argumentsText = (() => {
|
||||
const closingParenToken = (0, util_1.nullThrows)(sourceCode.getLastToken(node), util_1.NullThrowsReasons.MissingToken('closing parenthesis', node.type));
|
||||
const openingParenToken = (0, util_1.nullThrows)(sourceCode.getFirstTokenBetween(node.typeArguments ?? node.callee, closingParenToken, util_1.isOpeningParenToken), util_1.NullThrowsReasons.MissingToken('opening parenthesis', node.type));
|
||||
return sourceCode.text.substring(openingParenToken.range[0], closingParenToken.range[1]);
|
||||
})();
|
||||
const typeArgumentsText = (() => {
|
||||
if (node.typeArguments == null) {
|
||||
return '';
|
||||
}
|
||||
return sourceCode.getText(node.typeArguments);
|
||||
})();
|
||||
return [
|
||||
...flattenChainExpression(sourceCode, node.callee),
|
||||
{
|
||||
nonNull: false,
|
||||
optional: node.optional,
|
||||
// no precedence for this
|
||||
precedence: util_1.OperatorPrecedence.Invalid,
|
||||
requiresDot: false,
|
||||
text: typeArgumentsText + argumentsText,
|
||||
},
|
||||
];
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.MemberExpression: {
|
||||
const propertyText = sourceCode.getText(node.property);
|
||||
return [
|
||||
...flattenChainExpression(sourceCode, node.object),
|
||||
{
|
||||
nonNull: node.object.type === utils_1.AST_NODE_TYPES.TSNonNullExpression,
|
||||
optional: node.optional,
|
||||
precedence: node.computed
|
||||
? // computed is already wrapped in [] so no need to wrap in () as well
|
||||
util_1.OperatorPrecedence.Invalid
|
||||
: (0, util_1.getOperatorPrecedenceForNode)(node.property),
|
||||
requiresDot: !node.computed,
|
||||
text: node.computed ? `[${propertyText}]` : propertyText,
|
||||
},
|
||||
];
|
||||
}
|
||||
case utils_1.AST_NODE_TYPES.TSNonNullExpression:
|
||||
return flattenChainExpression(sourceCode, node.expression);
|
||||
default:
|
||||
return [
|
||||
{
|
||||
nonNull: false,
|
||||
optional: false,
|
||||
precedence: (0, util_1.getOperatorPrecedenceForNode)(node),
|
||||
requiresDot: false,
|
||||
text: sourceCode.getText(node),
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
function analyzeChain(context, parserServices, options, node, operator, chain, lastChainOperand) {
|
||||
// need at least 2 operands in a chain for it to be a chain
|
||||
if (chain.length + (lastChainOperand ? 1 : 0) <= 1 ||
|
||||
/* istanbul ignore next -- previous checks make this unreachable, but keep it for exhaustiveness check */
|
||||
operator === '??') {
|
||||
return;
|
||||
}
|
||||
const analyzeOperand = (() => {
|
||||
switch (operator) {
|
||||
case '&&':
|
||||
return analyzeAndChainOperand;
|
||||
case '||':
|
||||
return analyzeOrChainOperand;
|
||||
}
|
||||
})();
|
||||
// Things like x !== null && x !== undefined have two nodes, but they are
|
||||
// one logical unit here, so we'll allow them to be grouped.
|
||||
let subChain = [];
|
||||
let lastChain = undefined;
|
||||
const maybeReportThenReset = (newChainSeed) => {
|
||||
if (subChain.length + (lastChain ? 1 : 0) > 1) {
|
||||
const subChainFlat = subChain.flat();
|
||||
const maybeNullishNodes = lastChain
|
||||
? subChainFlat.map(({ node }) => node)
|
||||
: subChainFlat.slice(0, -1).map(({ node }) => node);
|
||||
(0, checkNullishAndReport_1.checkNullishAndReport)(context, parserServices, options, maybeNullishNodes, getReportDescriptor(context.sourceCode, parserServices, node, operator, options, subChainFlat, lastChain));
|
||||
}
|
||||
// we've reached the end of a chain of logical expressions
|
||||
// i.e. the current operand doesn't belong to the previous chain.
|
||||
//
|
||||
// we don't want to throw away the current operand otherwise we will skip it
|
||||
// and that can cause us to miss chains. So instead we seed the new chain
|
||||
// with the current operand
|
||||
//
|
||||
// eg this means we can catch cases like:
|
||||
// unrelated != null && foo != null && foo.bar != null;
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ first "chain"
|
||||
// ^^^^^^^^^^^ newChainSeed
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ second chain
|
||||
subChain = newChainSeed ? [newChainSeed] : [];
|
||||
lastChain = undefined;
|
||||
};
|
||||
for (let i = 0; i < chain.length; i += 1) {
|
||||
const lastOperand = subChain.flat().at(-1);
|
||||
const operand = chain[i];
|
||||
const validatedOperands = analyzeOperand(parserServices, operand, i, chain);
|
||||
if (!validatedOperands) {
|
||||
// TODO - #7170
|
||||
// check if the name is a superset/equal - if it is, then it likely
|
||||
// intended to be part of the chain and something we should include in the
|
||||
// report, eg
|
||||
// foo == null || foo.bar;
|
||||
// ^^^^^^^^^^^ valid OR chain
|
||||
// ^^^^^^^ invalid OR chain logical, but still part of
|
||||
// the chain for combination purposes
|
||||
if (lastOperand) {
|
||||
const comparisonResult = (0, compareNodes_1.compareNodes)(lastOperand.comparedName, operand.comparedName);
|
||||
switch (operand.comparisonType) {
|
||||
case gatherLogicalOperands_1.NullishComparisonType.StrictEqualUndefined:
|
||||
case gatherLogicalOperands_1.NullishComparisonType.NotStrictEqualUndefined: {
|
||||
if (comparisonResult === compareNodes_1.NodeComparisonResult.Subset) {
|
||||
lastChain = operand;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
maybeReportThenReset();
|
||||
continue;
|
||||
}
|
||||
// in case multiple operands were consumed - make sure to correctly increment the index
|
||||
i += validatedOperands.length - 1;
|
||||
const currentOperand = validatedOperands[0];
|
||||
if (lastOperand) {
|
||||
const comparisonResult = (0, compareNodes_1.compareNodes)(lastOperand.comparedName,
|
||||
// purposely inspect and push the last operand because the prior operands don't matter
|
||||
// this also means we won't false-positive in cases like
|
||||
// foo !== null && foo !== undefined
|
||||
validatedOperands[validatedOperands.length - 1].comparedName);
|
||||
if (comparisonResult === compareNodes_1.NodeComparisonResult.Subset) {
|
||||
// the operands are comparable, so we can continue searching
|
||||
subChain.push(currentOperand);
|
||||
}
|
||||
else if (comparisonResult === compareNodes_1.NodeComparisonResult.Invalid) {
|
||||
maybeReportThenReset(validatedOperands);
|
||||
}
|
||||
else {
|
||||
// purposely don't push this case because the node is a no-op and if
|
||||
// we consider it then we might report on things like
|
||||
// foo && foo
|
||||
}
|
||||
}
|
||||
else {
|
||||
subChain.push(currentOperand);
|
||||
}
|
||||
}
|
||||
const lastOperand = subChain.flat().at(-1);
|
||||
if (lastOperand && lastChainOperand) {
|
||||
const isValidLastChainOperand = operator === '&&'
|
||||
? isValidAndLastChainOperand
|
||||
: isValidOrLastChainOperand;
|
||||
const { comparedName, comparisonValue, isSubset, isYoda } = resolveOperandSubset(lastOperand, lastChainOperand);
|
||||
if (isSubset &&
|
||||
isValidLastChainOperand(comparisonValue, lastChainOperand.comparisonType, parserServices)) {
|
||||
lastChain = {
|
||||
...lastChainOperand,
|
||||
comparedName,
|
||||
comparisonValue,
|
||||
isYoda,
|
||||
};
|
||||
}
|
||||
}
|
||||
// check the leftovers
|
||||
maybeReportThenReset();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import type { FlatConfig } from '@typescript-eslint/utils/ts-eslint';
|
||||
export default _default;
|
||||
/**
|
||||
* Contains all of `stylistic`, along with additional stylistic rules that require type information.
|
||||
* @see {@link https://typescript-eslint.io/users/configs#stylistic-type-checked}
|
||||
*/
|
||||
declare function _default(plugin: FlatConfig.Plugin, parser: FlatConfig.Parser): FlatConfig.ConfigArray;
|
||||
@@ -0,0 +1,270 @@
|
||||
"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 });
|
||||
exports.isStaticMemberAccessOfValue = exports.MemberNameType = void 0;
|
||||
exports.isDefinitionFile = isDefinitionFile;
|
||||
exports.upperCaseFirst = upperCaseFirst;
|
||||
exports.arrayGroupByToMap = arrayGroupByToMap;
|
||||
exports.arraysAreEqual = arraysAreEqual;
|
||||
exports.findFirstResult = findFirstResult;
|
||||
exports.getNameFromIndexSignature = getNameFromIndexSignature;
|
||||
exports.getNameFromMember = getNameFromMember;
|
||||
exports.getEnumNames = getEnumNames;
|
||||
exports.formatWordList = formatWordList;
|
||||
exports.findLastIndex = findLastIndex;
|
||||
exports.typeNodeRequiresParentheses = typeNodeRequiresParentheses;
|
||||
exports.isRestParameterDeclaration = isRestParameterDeclaration;
|
||||
exports.isParenlessArrowFunction = isParenlessArrowFunction;
|
||||
exports.getStaticMemberAccessValue = getStaticMemberAccessValue;
|
||||
const type_utils_1 = require("@typescript-eslint/type-utils");
|
||||
const utils_1 = require("@typescript-eslint/utils");
|
||||
const ts = __importStar(require("typescript"));
|
||||
const astUtils_1 = require("./astUtils");
|
||||
const DEFINITION_EXTENSIONS = [
|
||||
ts.Extension.Dts,
|
||||
ts.Extension.Dcts,
|
||||
ts.Extension.Dmts,
|
||||
];
|
||||
/**
|
||||
* Check if the context file name is *.d.ts or *.d.tsx
|
||||
*/
|
||||
function isDefinitionFile(fileName) {
|
||||
const lowerFileName = fileName.toLowerCase();
|
||||
for (const definitionExt of DEFINITION_EXTENSIONS) {
|
||||
if (lowerFileName.endsWith(definitionExt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return /\.d\.(ts|cts|mts|.*\.ts)$/.test(lowerFileName);
|
||||
}
|
||||
/**
|
||||
* Upper cases the first character or the string
|
||||
*/
|
||||
function upperCaseFirst(str) {
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
}
|
||||
function arrayGroupByToMap(array, getKey) {
|
||||
const groups = new Map();
|
||||
for (const item of array) {
|
||||
const key = getKey(item);
|
||||
const existing = groups.get(key);
|
||||
if (existing) {
|
||||
existing.push(item);
|
||||
}
|
||||
else {
|
||||
groups.set(key, [item]);
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
function arraysAreEqual(a, b, eq) {
|
||||
return (a === b ||
|
||||
(a != null && a.length === b?.length && a.every((x, idx) => eq(x, b[idx]))));
|
||||
}
|
||||
/** Returns the first non-`undefined` result. */
|
||||
function findFirstResult(inputs, getResult) {
|
||||
for (const element of inputs) {
|
||||
const result = getResult(element);
|
||||
// eslint-disable-next-line @typescript-eslint/internal/eqeq-nullish
|
||||
if (result !== undefined) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Gets a string representation of the name of the index signature.
|
||||
*/
|
||||
function getNameFromIndexSignature(node) {
|
||||
const propName = node.parameters.find((parameter) => parameter.type === utils_1.AST_NODE_TYPES.Identifier);
|
||||
return propName ? propName.name : '(index signature)';
|
||||
}
|
||||
var MemberNameType;
|
||||
(function (MemberNameType) {
|
||||
MemberNameType[MemberNameType["Private"] = 1] = "Private";
|
||||
MemberNameType[MemberNameType["Quoted"] = 2] = "Quoted";
|
||||
MemberNameType[MemberNameType["Normal"] = 3] = "Normal";
|
||||
MemberNameType[MemberNameType["Expression"] = 4] = "Expression";
|
||||
})(MemberNameType || (exports.MemberNameType = MemberNameType = {}));
|
||||
/**
|
||||
* Gets a string name representation of the name of the given MethodDefinition
|
||||
* or PropertyDefinition node, with handling for computed property names.
|
||||
*/
|
||||
function getNameFromMember(member, sourceCode) {
|
||||
if (member.key.type === utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return {
|
||||
name: member.key.name,
|
||||
type: MemberNameType.Normal,
|
||||
};
|
||||
}
|
||||
if (member.key.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
||||
return {
|
||||
name: `#${member.key.name}`,
|
||||
type: MemberNameType.Private,
|
||||
};
|
||||
}
|
||||
if (member.key.type === utils_1.AST_NODE_TYPES.Literal) {
|
||||
const name = `${member.key.value}`;
|
||||
if ((0, type_utils_1.requiresQuoting)(name)) {
|
||||
return {
|
||||
name: `"${name}"`,
|
||||
type: MemberNameType.Quoted,
|
||||
};
|
||||
}
|
||||
return {
|
||||
name,
|
||||
type: MemberNameType.Normal,
|
||||
};
|
||||
}
|
||||
return {
|
||||
name: sourceCode.text.slice(...member.key.range),
|
||||
type: MemberNameType.Expression,
|
||||
};
|
||||
}
|
||||
function getEnumNames(myEnum) {
|
||||
return Object.keys(myEnum).filter(x => isNaN(Number(x)));
|
||||
}
|
||||
/**
|
||||
* Given an array of words, returns an English-friendly concatenation, separated with commas, with
|
||||
* the `and` clause inserted before the last item.
|
||||
*
|
||||
* Example: ['foo', 'bar', 'baz' ] returns the string "foo, bar, and baz".
|
||||
*/
|
||||
function formatWordList(words) {
|
||||
if (!words.length) {
|
||||
return '';
|
||||
}
|
||||
if (words.length === 1) {
|
||||
return words[0];
|
||||
}
|
||||
return [words.slice(0, -1).join(', '), words.slice(-1)[0]].join(' and ');
|
||||
}
|
||||
/**
|
||||
* Iterates the array in reverse and returns the index of the first element it
|
||||
* finds which passes the predicate function.
|
||||
*
|
||||
* @returns Returns the index of the element if it finds it or -1 otherwise.
|
||||
*/
|
||||
function findLastIndex(members, predicate) {
|
||||
let idx = members.length - 1;
|
||||
while (idx >= 0) {
|
||||
const valid = predicate(members[idx]);
|
||||
if (valid) {
|
||||
return idx;
|
||||
}
|
||||
idx--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function typeNodeRequiresParentheses(node, text) {
|
||||
return (node.type === utils_1.AST_NODE_TYPES.TSFunctionType ||
|
||||
node.type === utils_1.AST_NODE_TYPES.TSConstructorType ||
|
||||
node.type === utils_1.AST_NODE_TYPES.TSConditionalType ||
|
||||
(node.type === utils_1.AST_NODE_TYPES.TSUnionType && text.startsWith('|')) ||
|
||||
(node.type === utils_1.AST_NODE_TYPES.TSIntersectionType && text.startsWith('&')));
|
||||
}
|
||||
function isRestParameterDeclaration(decl) {
|
||||
return ts.isParameter(decl) && decl.dotDotDotToken != null;
|
||||
}
|
||||
function isParenlessArrowFunction(node, sourceCode) {
|
||||
return (node.params.length === 1 && !(0, astUtils_1.isParenthesized)(node.params[0], sourceCode));
|
||||
}
|
||||
/**
|
||||
* Gets a member being accessed or declared if its value can be determined statically, and
|
||||
* resolves it to the string or symbol value that will be used as the actual member
|
||||
* access key at runtime. Otherwise, returns `undefined`.
|
||||
*
|
||||
* ```ts
|
||||
* x.member // returns 'member'
|
||||
* ^^^^^^^^
|
||||
*
|
||||
* x?.member // returns 'member' (optional chaining is treated the same)
|
||||
* ^^^^^^^^^
|
||||
*
|
||||
* x['value'] // returns 'value'
|
||||
* ^^^^^^^^^^
|
||||
*
|
||||
* x[Math.random()] // returns undefined (not a static value)
|
||||
* ^^^^^^^^^^^^^^^^
|
||||
*
|
||||
* arr[0] // returns '0' (NOT 0)
|
||||
* ^^^^^^
|
||||
*
|
||||
* arr[0n] // returns '0' (NOT 0n)
|
||||
* ^^^^^^^
|
||||
*
|
||||
* const s = Symbol.for('symbolName')
|
||||
* x[s] // returns `Symbol.for('symbolName')` (since it's a static/global symbol)
|
||||
* ^^^^
|
||||
*
|
||||
* const us = Symbol('symbolName')
|
||||
* x[us] // returns undefined (since it's a unique symbol, so not statically analyzable)
|
||||
* ^^^^^
|
||||
*
|
||||
* var object = {
|
||||
* 1234: '4567', // returns '1234' (NOT 1234)
|
||||
* ^^^^^^^^^^^^
|
||||
* method() { } // returns 'method'
|
||||
* ^^^^^^^^^^^^
|
||||
* }
|
||||
*
|
||||
* class WithMembers {
|
||||
* foo: string // returns 'foo'
|
||||
* ^^^^^^^^^^^
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
function getStaticMemberAccessValue(node, { sourceCode }) {
|
||||
const key = node.type === utils_1.AST_NODE_TYPES.MemberExpression ? node.property : node.key;
|
||||
const { type } = key;
|
||||
if (!node.computed &&
|
||||
(type === utils_1.AST_NODE_TYPES.Identifier ||
|
||||
type === utils_1.AST_NODE_TYPES.PrivateIdentifier)) {
|
||||
return key.name;
|
||||
}
|
||||
const result = (0, astUtils_1.getStaticValue)(key, sourceCode.getScope(node));
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
const { value } = result;
|
||||
return typeof value === 'symbol' ? value : String(value);
|
||||
}
|
||||
/**
|
||||
* Answers whether the member expression looks like
|
||||
* `x.value`, `x['value']`,
|
||||
* or even `const v = 'value'; x[v]` (or optional variants thereof).
|
||||
*/
|
||||
const isStaticMemberAccessOfValue = (memberExpression, context, ...values) => values.includes(getStaticMemberAccessValue(memberExpression, context));
|
||||
exports.isStaticMemberAccessOfValue = isStaticMemberAccessOfValue;
|
||||
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const { join } = require('path')
|
||||
const ThreadStream = require('..')
|
||||
const { file } = require('./helper')
|
||||
|
||||
const MAX = 1000
|
||||
|
||||
let str = ''
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
str += 'hello'
|
||||
}
|
||||
|
||||
test('base', function (t, done) {
|
||||
const dest = file()
|
||||
const stream = new ThreadStream({
|
||||
filename: join(__dirname, 'to-file.js'),
|
||||
workerData: { dest }
|
||||
})
|
||||
let runs = 0
|
||||
function benchThreadStream () {
|
||||
if (++runs === 1000) {
|
||||
stream.end()
|
||||
return
|
||||
}
|
||||
|
||||
for (let i = 0; i < MAX; i++) {
|
||||
stream.write(str)
|
||||
}
|
||||
setImmediate(benchThreadStream)
|
||||
}
|
||||
benchThreadStream()
|
||||
stream.on('finish', function () {
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { Linter } from './Linter';
|
||||
export declare namespace Processor {
|
||||
interface ProcessorMeta {
|
||||
/**
|
||||
* The unique name of the processor.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The a string identifying the version of the processor.
|
||||
*/
|
||||
version?: string;
|
||||
}
|
||||
type PreProcess = (text: string, filename: string) => (string | {
|
||||
filename: string;
|
||||
text: string;
|
||||
})[];
|
||||
type PostProcess = (messagesList: Linter.LintMessage[][], filename: string) => Linter.LintMessage[];
|
||||
interface ProcessorModule {
|
||||
/**
|
||||
* Information about the processor to uniquely identify it when serializing.
|
||||
*/
|
||||
meta?: ProcessorMeta;
|
||||
/**
|
||||
* The function to merge messages.
|
||||
*/
|
||||
postprocess?: PostProcess;
|
||||
/**
|
||||
* The function to extract code blocks.
|
||||
*/
|
||||
preprocess?: PreProcess;
|
||||
/**
|
||||
* If `true` then it means the processor supports autofix.
|
||||
*/
|
||||
supportsAutofix?: boolean;
|
||||
}
|
||||
/**
|
||||
* A loose definition of the ParserModule type for use with configs
|
||||
* This type intended to relax validation of configs so that parsers that have
|
||||
* different AST types or scope managers can still be passed to configs
|
||||
*
|
||||
* @see {@link LooseRuleDefinition}, {@link LooseParserModule}
|
||||
*/
|
||||
interface LooseProcessorModule {
|
||||
/**
|
||||
* Information about the processor to uniquely identify it when serializing.
|
||||
*/
|
||||
meta?: {
|
||||
[K in keyof ProcessorMeta]?: ProcessorMeta[K] | undefined;
|
||||
};
|
||||
/**
|
||||
* The function to merge messages.
|
||||
*/
|
||||
postprocess?: (messagesList: any, filename: string) => any;
|
||||
/**
|
||||
* The function to extract code blocks.
|
||||
*/
|
||||
preprocess?: (text: string, filename: string) => any;
|
||||
/**
|
||||
* If `true` then it means the processor supports autofix.
|
||||
*/
|
||||
supportsAutofix?: boolean | undefined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_ts_param.js";
|
||||
@@ -0,0 +1,61 @@
|
||||
type Pathname = string
|
||||
|
||||
interface TestResult {
|
||||
ignored: boolean
|
||||
unignored: boolean
|
||||
}
|
||||
|
||||
export interface Ignore {
|
||||
/**
|
||||
* Adds one or several rules to the current manager.
|
||||
* @param {string[]} patterns
|
||||
* @returns IgnoreBase
|
||||
*/
|
||||
add(patterns: string | Ignore | readonly (string | Ignore)[]): this
|
||||
|
||||
/**
|
||||
* Filters the given array of pathnames, and returns the filtered array.
|
||||
* NOTICE that each path here should be a relative path to the root of your repository.
|
||||
* @param paths the array of paths to be filtered.
|
||||
* @returns The filtered array of paths
|
||||
*/
|
||||
filter(pathnames: readonly Pathname[]): Pathname[]
|
||||
|
||||
/**
|
||||
* Creates a filter function which could filter
|
||||
* an array of paths with Array.prototype.filter.
|
||||
*/
|
||||
createFilter(): (pathname: Pathname) => boolean
|
||||
|
||||
/**
|
||||
* Returns Boolean whether pathname should be ignored.
|
||||
* @param {string} pathname a path to check
|
||||
* @returns boolean
|
||||
*/
|
||||
ignores(pathname: Pathname): boolean
|
||||
|
||||
/**
|
||||
* Returns whether pathname should be ignored or unignored
|
||||
* @param {string} pathname a path to check
|
||||
* @returns TestResult
|
||||
*/
|
||||
test(pathname: Pathname): TestResult
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
ignorecase?: boolean
|
||||
// For compatibility
|
||||
ignoreCase?: boolean
|
||||
allowRelativePaths?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new ignore manager.
|
||||
*/
|
||||
declare function ignore(options?: Options): Ignore
|
||||
|
||||
declare namespace ignore {
|
||||
export function isPathValid (pathname: string): boolean
|
||||
}
|
||||
|
||||
export default ignore
|
||||
@@ -0,0 +1,377 @@
|
||||
"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 util_1 = require("../util");
|
||||
const promiseUtils_1 = require("../util/promiseUtils");
|
||||
const messageBase = 'Promises must be awaited, end with a call to .catch, or end with a call to .then with a rejection handler.';
|
||||
const messageBaseVoid = 'Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler' +
|
||||
' or be explicitly marked as ignored with the `void` operator.';
|
||||
const messageRejectionHandler = 'A rejection handler that is not a function will be ignored.';
|
||||
const messagePromiseArray = "An array of Promises may be unintentional. Consider handling the promises' fulfillment or rejection with Promise.all or similar.";
|
||||
const messagePromiseArrayVoid = "An array of Promises may be unintentional. Consider handling the promises' fulfillment or rejection with Promise.all or similar," +
|
||||
' or explicitly marking the expression as ignored with the `void` operator.';
|
||||
exports.default = (0, util_1.createRule)({
|
||||
name: 'no-floating-promises',
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Require Promise-like statements to be handled appropriately',
|
||||
recommended: 'recommended',
|
||||
requiresTypeChecking: true,
|
||||
},
|
||||
hasSuggestions: true,
|
||||
messages: {
|
||||
floating: messageBase,
|
||||
floatingFixAwait: 'Add await operator.',
|
||||
floatingFixVoid: 'Add void operator to ignore.',
|
||||
floatingPromiseArray: messagePromiseArray,
|
||||
floatingPromiseArrayVoid: messagePromiseArrayVoid,
|
||||
floatingUselessRejectionHandler: `${messageBase} ${messageRejectionHandler}`,
|
||||
floatingUselessRejectionHandlerVoid: `${messageBaseVoid} ${messageRejectionHandler}`,
|
||||
floatingVoid: messageBaseVoid,
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
allowForKnownSafeCalls: {
|
||||
...util_1.readonlynessOptionsSchema.properties.allow,
|
||||
description: 'Type specifiers of functions whose calls are safe to float.',
|
||||
},
|
||||
allowForKnownSafePromises: {
|
||||
...util_1.readonlynessOptionsSchema.properties.allow,
|
||||
description: 'Type specifiers that are known to be safe to float.',
|
||||
},
|
||||
checkThenables: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to check all "Thenable"s, not just the built-in Promise type.',
|
||||
},
|
||||
ignoreIIFE: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore async IIFEs (Immediately Invoked Function Expressions).',
|
||||
},
|
||||
ignoreVoid: {
|
||||
type: 'boolean',
|
||||
description: 'Whether to ignore `void` expressions.',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultOptions: [
|
||||
{
|
||||
allowForKnownSafeCalls: util_1.readonlynessOptionsDefaults.allow,
|
||||
allowForKnownSafePromises: util_1.readonlynessOptionsDefaults.allow,
|
||||
checkThenables: false,
|
||||
ignoreIIFE: false,
|
||||
ignoreVoid: true,
|
||||
},
|
||||
],
|
||||
create(context, [options]) {
|
||||
const services = (0, util_1.getParserServices)(context);
|
||||
const checker = services.program.getTypeChecker();
|
||||
const { checkThenables } = options;
|
||||
// TODO: #5439
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
const allowForKnownSafePromises = options.allowForKnownSafePromises;
|
||||
const allowForKnownSafeCalls = options.allowForKnownSafeCalls;
|
||||
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
||||
return {
|
||||
ExpressionStatement(node) {
|
||||
if (options.ignoreIIFE && isAsyncIife(node)) {
|
||||
return;
|
||||
}
|
||||
const expression = (0, util_1.skipChainExpression)(node.expression);
|
||||
if (isKnownSafePromiseCall(expression)) {
|
||||
return;
|
||||
}
|
||||
const { isUnhandled, nonFunctionHandler, promiseArray } = isUnhandledPromise(checker, expression);
|
||||
if (isUnhandled) {
|
||||
if (promiseArray) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: options.ignoreVoid
|
||||
? 'floatingPromiseArrayVoid'
|
||||
: 'floatingPromiseArray',
|
||||
});
|
||||
}
|
||||
else if (options.ignoreVoid) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: nonFunctionHandler
|
||||
? 'floatingUselessRejectionHandlerVoid'
|
||||
: 'floatingVoid',
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'floatingFixVoid',
|
||||
fix(fixer) {
|
||||
if ((0, util_1.isParenthesized)(expression, context.sourceCode) ||
|
||||
(0, util_1.getOperatorPrecedenceForNode)(expression) >
|
||||
util_1.OperatorPrecedence.Unary) {
|
||||
return fixer.insertTextBefore(node, 'void ');
|
||||
}
|
||||
return [
|
||||
fixer.insertTextBefore(node, 'void ('),
|
||||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'),
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
messageId: 'floatingFixAwait',
|
||||
fix: (fixer) => addAwait(fixer, expression, node),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
else {
|
||||
context.report({
|
||||
node,
|
||||
messageId: nonFunctionHandler
|
||||
? 'floatingUselessRejectionHandler'
|
||||
: 'floating',
|
||||
suggest: [
|
||||
{
|
||||
messageId: 'floatingFixAwait',
|
||||
fix: (fixer) => addAwait(fixer, expression, node),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
function addAwait(fixer, expression, node) {
|
||||
if (expression.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
||||
expression.operator === 'void') {
|
||||
return fixer.replaceTextRange([expression.range[0], expression.range[0] + 4], 'await');
|
||||
}
|
||||
if ((0, util_1.isParenthesized)(expression, context.sourceCode) ||
|
||||
(0, util_1.getOperatorPrecedenceForNode)(expression) > util_1.OperatorPrecedence.Unary) {
|
||||
return fixer.insertTextBefore(node, 'await ');
|
||||
}
|
||||
return [
|
||||
fixer.insertTextBefore(node, 'await ('),
|
||||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'),
|
||||
];
|
||||
}
|
||||
function isKnownSafePromiseCall(node) {
|
||||
if (node.type !== utils_1.AST_NODE_TYPES.CallExpression) {
|
||||
return false;
|
||||
}
|
||||
const type = services.getTypeAtLocation(node.callee);
|
||||
if ((0, util_1.valueMatchesSomeSpecifier)(node.callee, allowForKnownSafeCalls, services.program, type)) {
|
||||
return true;
|
||||
}
|
||||
return (0, util_1.typeMatchesSomeSpecifier)(type, allowForKnownSafeCalls, services.program);
|
||||
}
|
||||
function isAsyncIife(node) {
|
||||
if (node.expression.type !== utils_1.AST_NODE_TYPES.CallExpression) {
|
||||
return false;
|
||||
}
|
||||
return (node.expression.callee.type ===
|
||||
utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
||||
node.expression.callee.type === utils_1.AST_NODE_TYPES.FunctionExpression);
|
||||
}
|
||||
function isValidRejectionHandler(rejectionHandler) {
|
||||
return (services.program
|
||||
.getTypeChecker()
|
||||
.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(rejectionHandler))
|
||||
.getCallSignatures().length > 0);
|
||||
}
|
||||
function isUnhandledPromise(checker, node) {
|
||||
if (node.type === utils_1.AST_NODE_TYPES.AssignmentExpression) {
|
||||
return { isUnhandled: false };
|
||||
}
|
||||
// First, check expressions whose resulting types may not be promise-like
|
||||
if (node.type === utils_1.AST_NODE_TYPES.SequenceExpression) {
|
||||
// Any child in a comma expression could return a potentially unhandled
|
||||
// promise, so we check them all regardless of whether the final returned
|
||||
// value is promise-like.
|
||||
return (node.expressions
|
||||
.map(item => isUnhandledPromise(checker, item))
|
||||
.find(result => result.isUnhandled) ?? { isUnhandled: false });
|
||||
}
|
||||
if (!options.ignoreVoid &&
|
||||
node.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
||||
node.operator === 'void') {
|
||||
// Similarly, a `void` expression always returns undefined, so we need to
|
||||
// see what's inside it without checking the type of the overall expression.
|
||||
return isUnhandledPromise(checker, node.argument);
|
||||
}
|
||||
const tsNode = services.esTreeNodeToTSNodeMap.get(node);
|
||||
// Check the type. At this point it can't be unhandled if it isn't a promise
|
||||
// or array thereof.
|
||||
if (isPromiseArray(tsNode)) {
|
||||
return { isUnhandled: true, promiseArray: true };
|
||||
}
|
||||
// await expression addresses promises, but not promise arrays.
|
||||
if (node.type === utils_1.AST_NODE_TYPES.AwaitExpression) {
|
||||
// you would think this wouldn't be strictly necessary, since we're
|
||||
// anyway checking the type of the expression, but, unfortunately TS
|
||||
// reports the result of `await (promise as Promise<number> & number)`
|
||||
// as `Promise<number> & number` instead of `number`.
|
||||
return { isUnhandled: false };
|
||||
}
|
||||
if (!isPromiseLike(tsNode)) {
|
||||
return { isUnhandled: false };
|
||||
}
|
||||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
||||
// If the outer expression is a call, a `.catch()` or `.then()` with
|
||||
// rejection handler handles the promise.
|
||||
const promiseHandlingMethodCall = (0, promiseUtils_1.parseCatchCall)(node, context) ?? (0, promiseUtils_1.parseThenCall)(node, context);
|
||||
if (promiseHandlingMethodCall != null) {
|
||||
const onRejected = promiseHandlingMethodCall.onRejected;
|
||||
if (onRejected != null) {
|
||||
if (isValidRejectionHandler(onRejected)) {
|
||||
return { isUnhandled: false };
|
||||
}
|
||||
return { isUnhandled: true, nonFunctionHandler: true };
|
||||
}
|
||||
return { isUnhandled: true };
|
||||
}
|
||||
const promiseFinallyCall = (0, promiseUtils_1.parseFinallyCall)(node, context);
|
||||
if (promiseFinallyCall != null) {
|
||||
return isUnhandledPromise(checker, promiseFinallyCall.object);
|
||||
}
|
||||
// All other cases are unhandled.
|
||||
return { isUnhandled: true };
|
||||
}
|
||||
if (node.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
|
||||
// We must be getting the promise-like value from one of the branches of the
|
||||
// ternary. Check them directly.
|
||||
const alternateResult = isUnhandledPromise(checker, node.alternate);
|
||||
if (alternateResult.isUnhandled) {
|
||||
return alternateResult;
|
||||
}
|
||||
return isUnhandledPromise(checker, node.consequent);
|
||||
}
|
||||
if (node.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
|
||||
const leftResult = isUnhandledPromise(checker, node.left);
|
||||
if (leftResult.isUnhandled) {
|
||||
return leftResult;
|
||||
}
|
||||
return isUnhandledPromise(checker, node.right);
|
||||
}
|
||||
// Anything else is unhandled.
|
||||
return { isUnhandled: true };
|
||||
}
|
||||
function isPromiseArray(node) {
|
||||
const type = getTypeAtLocation(checker, node);
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
for (const ty of tsutils
|
||||
.unionConstituents(type)
|
||||
.map(t => checker.getApparentType(t))) {
|
||||
if (checker.isArrayType(ty)) {
|
||||
const arrayType = checker.getTypeArguments(ty)[0];
|
||||
if (isPromiseLike(node, arrayType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (checker.isTupleType(ty)) {
|
||||
for (const tupleElementType of checker.getTypeArguments(ty)) {
|
||||
if (isPromiseLike(node, tupleElementType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isPromiseLike(node, type) {
|
||||
type ??= checker.getTypeAtLocation(node);
|
||||
// The highest priority is to allow anything allowlisted
|
||||
if ((0, util_1.typeMatchesSomeSpecifier)(type, allowForKnownSafePromises, services.program)) {
|
||||
return false;
|
||||
}
|
||||
// Otherwise, we always consider the built-in Promise to be Promise-like...
|
||||
const typeParts = tsutils.unionConstituents(checker.getApparentType(type));
|
||||
if (typeParts.some(typePart => (0, util_1.isBuiltinSymbolLike)(services.program, typePart, 'Promise'))) {
|
||||
return true;
|
||||
}
|
||||
// ...and only check all Thenables if explicitly told to
|
||||
if (!checkThenables) {
|
||||
return false;
|
||||
}
|
||||
// Modified from tsutils.isThenable() to only consider thenables which can be
|
||||
// rejected/caught via a second parameter. Original source (MIT licensed):
|
||||
//
|
||||
// https://github.com/ajafff/tsutils/blob/49d0d31050b44b81e918eae4fbaf1dfe7b7286af/util/type.ts#L95-L125
|
||||
for (const ty of typeParts) {
|
||||
const then = ty.getProperty('then');
|
||||
if (then == null) {
|
||||
continue;
|
||||
}
|
||||
const thenType = checker.getTypeOfSymbolAtLocation(then, node);
|
||||
if (hasMatchingSignature(thenType, signature => signature.parameters.length >= 2 &&
|
||||
isFunctionParam(checker, signature.parameters[0], node) &&
|
||||
isFunctionParam(checker, signature.parameters[1], node))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
function hasMatchingSignature(type, matcher) {
|
||||
for (const t of tsutils.unionConstituents(type)) {
|
||||
if (t.getCallSignatures().some(matcher)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isFunctionParam(checker, param, node) {
|
||||
const type = checker.getApparentType(checker.getTypeOfSymbolAtLocation(param, node));
|
||||
for (const t of tsutils.unionConstituents(type)) {
|
||||
if (t.getCallSignatures().length !== 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function getTypeAtLocation(checker, node) {
|
||||
try {
|
||||
return checker.getTypeAtLocation(node);
|
||||
}
|
||||
catch {
|
||||
// Workaround for https://github.com/typescript-eslint/typescript-eslint/issues/11947
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "esrecurse",
|
||||
"description": "ECMAScript AST recursive visitor",
|
||||
"homepage": "https://github.com/estools/esrecurse",
|
||||
"main": "esrecurse.js",
|
||||
"version": "4.3.0",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "https://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/estools/esrecurse.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-register": "^6.24.1",
|
||||
"chai": "^4.0.2",
|
||||
"esprima": "^4.0.0",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-bump": "^2.7.0",
|
||||
"gulp-eslint": "^4.0.0",
|
||||
"gulp-filter": "^5.0.0",
|
||||
"gulp-git": "^2.4.1",
|
||||
"gulp-mocha": "^4.3.1",
|
||||
"gulp-tag-version": "^1.2.1",
|
||||
"jsdoc": "^3.3.0-alpha10",
|
||||
"minimist": "^1.1.0"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "gulp travis",
|
||||
"unit-test": "gulp test",
|
||||
"lint": "gulp lint"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"es2015"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "caracteres", verb: "tener" },
|
||||
file: { unit: "bytes", verb: "tener" },
|
||||
array: { unit: "elementos", verb: "tener" },
|
||||
set: { unit: "elementos", verb: "tener" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const FormatDictionary: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "entrada",
|
||||
email: "dirección de correo electrónico",
|
||||
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: "fecha y hora ISO",
|
||||
date: "fecha ISO",
|
||||
time: "hora ISO",
|
||||
duration: "duración ISO",
|
||||
ipv4: "dirección IPv4",
|
||||
ipv6: "dirección IPv6",
|
||||
cidrv4: "rango IPv4",
|
||||
cidrv6: "rango IPv6",
|
||||
base64: "cadena codificada en base64",
|
||||
base64url: "URL codificada en base64",
|
||||
json_string: "cadena JSON",
|
||||
e164: "número E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "entrada",
|
||||
};
|
||||
|
||||
const TypeDictionary: {
|
||||
[k in errors.$ZodInvalidTypeExpected | (string & {})]?: string;
|
||||
} = {
|
||||
nan: "NaN",
|
||||
string: "texto",
|
||||
number: "número",
|
||||
boolean: "booleano",
|
||||
array: "arreglo",
|
||||
object: "objeto",
|
||||
set: "conjunto",
|
||||
file: "archivo",
|
||||
date: "fecha",
|
||||
bigint: "número grande",
|
||||
symbol: "símbolo",
|
||||
undefined: "indefinido",
|
||||
null: "nulo",
|
||||
function: "función",
|
||||
map: "mapa",
|
||||
record: "registro",
|
||||
tuple: "tupla",
|
||||
enum: "enumeración",
|
||||
union: "unión",
|
||||
literal: "literal",
|
||||
promise: "promesa",
|
||||
void: "vacío",
|
||||
never: "nunca",
|
||||
unknown: "desconocido",
|
||||
any: "cualquiera",
|
||||
};
|
||||
|
||||
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 `Entrada inválida: se esperaba instanceof ${issue.expected}, recibido ${received}`;
|
||||
}
|
||||
return `Entrada inválida: se esperaba ${expected}, recibido ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Entrada inválida: se esperaba ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Opción inválida: se esperaba una de ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = TypeDictionary[issue.origin] ?? issue.origin;
|
||||
if (sizing)
|
||||
return `Demasiado grande: se esperaba que ${origin ?? "valor"} tuviera ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementos"}`;
|
||||
return `Demasiado grande: se esperaba que ${origin ?? "valor"} fuera ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = TypeDictionary[issue.origin] ?? issue.origin;
|
||||
if (sizing) {
|
||||
return `Demasiado pequeño: se esperaba que ${origin} tuviera ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Demasiado pequeño: se esperaba que ${origin} fuera ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `Cadena inválida: debe comenzar con "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `Cadena inválida: debe terminar en "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `Cadena inválida: debe incluir "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `Cadena inválida: debe coincidir con el patrón ${_issue.pattern}`;
|
||||
return `Inválido ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Número inválido: debe ser múltiplo de ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Llave${issue.keys.length > 1 ? "s" : ""} desconocida${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Llave inválida en ${TypeDictionary[issue.origin] ?? issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Entrada inválida";
|
||||
case "invalid_element":
|
||||
return `Valor inválido en ${TypeDictionary[issue.origin] ?? issue.origin}`;
|
||||
default:
|
||||
return `Entrada inválida`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
var OverloadYield = require("./OverloadYield.js");
|
||||
var regeneratorDefine = require("./regeneratorDefine.js");
|
||||
function AsyncIterator(t, e) {
|
||||
function n(r, o, i, f) {
|
||||
try {
|
||||
var c = t[r](o),
|
||||
u = c.value;
|
||||
return u instanceof OverloadYield ? e.resolve(u.v).then(function (t) {
|
||||
n("next", t, i, f);
|
||||
}, function (t) {
|
||||
n("throw", t, i, f);
|
||||
}) : e.resolve(u).then(function (t) {
|
||||
c.value = t, i(c);
|
||||
}, function (t) {
|
||||
return n("throw", t, i, f);
|
||||
});
|
||||
} catch (t) {
|
||||
f(t);
|
||||
}
|
||||
}
|
||||
var r;
|
||||
this.next || (regeneratorDefine(AsyncIterator.prototype), regeneratorDefine(AsyncIterator.prototype, "function" == typeof Symbol && Symbol.asyncIterator || "@asyncIterator", function () {
|
||||
return this;
|
||||
})), regeneratorDefine(this, "_invoke", function (t, o, i) {
|
||||
function f() {
|
||||
return new e(function (e, r) {
|
||||
n(t, i, e, r);
|
||||
});
|
||||
}
|
||||
return r = r ? r.then(f, f) : f();
|
||||
}, !0);
|
||||
}
|
||||
module.exports = AsyncIterator, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
const { parentPort } = require('worker_threads')
|
||||
|
||||
parentPort.postMessage({
|
||||
code: 'CUSTOM-WORKER-CALLED'
|
||||
})
|
||||
|
||||
require('../lib/worker')
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_async_to_generator.cjs",
|
||||
"module": "../../esm/_async_to_generator.js"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*! *****************************************************************************
|
||||
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.
|
||||
***************************************************************************** */
|
||||
|
||||
|
||||
interface RegExpMatchArray {
|
||||
indices?: RegExpIndicesArray;
|
||||
}
|
||||
|
||||
interface RegExpExecArray {
|
||||
indices?: RegExpIndicesArray;
|
||||
}
|
||||
|
||||
interface RegExpIndicesArray extends Array<[number, number] | undefined> {
|
||||
groups?: {
|
||||
[key: string]: [number, number];
|
||||
};
|
||||
}
|
||||
|
||||
interface RegExp {
|
||||
/**
|
||||
* Returns a Boolean value indicating the state of the hasIndices flag (d) used with a regular expression.
|
||||
* Default is false. Read-only.
|
||||
*/
|
||||
readonly hasIndices: boolean;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export declare function parserSeemsToBeTSESLint(parser: string | undefined): boolean;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
'use strict'
|
||||
|
||||
module.exports.isClean = Symbol('isClean')
|
||||
|
||||
module.exports.my = Symbol('my')
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"diagnosticCategory.enum.d.ts","sourceRoot":"","sources":["../../src/enums/diagnosticCategory.enum.ts"],"names":[],"mappings":"AAEA,oBAAY,kBAAkB;IAC1B,OAAO,IAAI;IACX,KAAK,IAAI;IACT,UAAU,IAAI;IACd,OAAO,IAAI;CACd"}
|
||||
@@ -0,0 +1,420 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.blake2s = exports.BLAKE2s = exports.blake2b = exports.BLAKE2b = exports.BLAKE2 = void 0;
|
||||
exports.compress = compress;
|
||||
/**
|
||||
* blake2b (64-bit) & blake2s (8 to 32-bit) hash functions.
|
||||
* b could have been faster, but there is no fast u64 in js, so s is 1.5x faster.
|
||||
* @module
|
||||
*/
|
||||
const _blake_ts_1 = require("./_blake.js");
|
||||
const _md_ts_1 = require("./_md.js");
|
||||
const u64 = require("./_u64.js");
|
||||
// prettier-ignore
|
||||
const utils_ts_1 = require("./utils.js");
|
||||
// Same as SHA512_IV, but swapped endianness: LE instead of BE. iv[1] is iv[0], etc.
|
||||
const B2B_IV = /* @__PURE__ */ Uint32Array.from([
|
||||
0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a,
|
||||
0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19,
|
||||
]);
|
||||
// Temporary buffer
|
||||
const BBUF = /* @__PURE__ */ new Uint32Array(32);
|
||||
// Mixing function G splitted in two halfs
|
||||
function G1b(a, b, c, d, msg, x) {
|
||||
// NOTE: V is LE here
|
||||
const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
|
||||
let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
|
||||
let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
|
||||
let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
|
||||
let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
|
||||
// v[a] = (v[a] + v[b] + x) | 0;
|
||||
let ll = u64.add3L(Al, Bl, Xl);
|
||||
Ah = u64.add3H(ll, Ah, Bh, Xh);
|
||||
Al = ll | 0;
|
||||
// v[d] = rotr(v[d] ^ v[a], 32)
|
||||
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
|
||||
({ Dh, Dl } = { Dh: u64.rotr32H(Dh, Dl), Dl: u64.rotr32L(Dh, Dl) });
|
||||
// v[c] = (v[c] + v[d]) | 0;
|
||||
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl));
|
||||
// v[b] = rotr(v[b] ^ v[c], 24)
|
||||
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
|
||||
({ Bh, Bl } = { Bh: u64.rotrSH(Bh, Bl, 24), Bl: u64.rotrSL(Bh, Bl, 24) });
|
||||
(BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah);
|
||||
(BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh);
|
||||
(BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch);
|
||||
(BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh);
|
||||
}
|
||||
function G2b(a, b, c, d, msg, x) {
|
||||
// NOTE: V is LE here
|
||||
const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
|
||||
let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
|
||||
let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
|
||||
let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
|
||||
let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
|
||||
// v[a] = (v[a] + v[b] + x) | 0;
|
||||
let ll = u64.add3L(Al, Bl, Xl);
|
||||
Ah = u64.add3H(ll, Ah, Bh, Xh);
|
||||
Al = ll | 0;
|
||||
// v[d] = rotr(v[d] ^ v[a], 16)
|
||||
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
|
||||
({ Dh, Dl } = { Dh: u64.rotrSH(Dh, Dl, 16), Dl: u64.rotrSL(Dh, Dl, 16) });
|
||||
// v[c] = (v[c] + v[d]) | 0;
|
||||
({ h: Ch, l: Cl } = u64.add(Ch, Cl, Dh, Dl));
|
||||
// v[b] = rotr(v[b] ^ v[c], 63)
|
||||
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
|
||||
({ Bh, Bl } = { Bh: u64.rotrBH(Bh, Bl, 63), Bl: u64.rotrBL(Bh, Bl, 63) });
|
||||
(BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah);
|
||||
(BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh);
|
||||
(BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch);
|
||||
(BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh);
|
||||
}
|
||||
function checkBlake2Opts(outputLen, opts = {}, keyLen, saltLen, persLen) {
|
||||
(0, utils_ts_1.anumber)(keyLen);
|
||||
if (outputLen < 0 || outputLen > keyLen)
|
||||
throw new Error('outputLen bigger than keyLen');
|
||||
const { key, salt, personalization } = opts;
|
||||
if (key !== undefined && (key.length < 1 || key.length > keyLen))
|
||||
throw new Error('key length must be undefined or 1..' + keyLen);
|
||||
if (salt !== undefined && salt.length !== saltLen)
|
||||
throw new Error('salt must be undefined or ' + saltLen);
|
||||
if (personalization !== undefined && personalization.length !== persLen)
|
||||
throw new Error('personalization must be undefined or ' + persLen);
|
||||
}
|
||||
/** Class, from which others are subclassed. */
|
||||
class BLAKE2 extends utils_ts_1.Hash {
|
||||
constructor(blockLen, outputLen) {
|
||||
super();
|
||||
this.finished = false;
|
||||
this.destroyed = false;
|
||||
this.length = 0;
|
||||
this.pos = 0;
|
||||
(0, utils_ts_1.anumber)(blockLen);
|
||||
(0, utils_ts_1.anumber)(outputLen);
|
||||
this.blockLen = blockLen;
|
||||
this.outputLen = outputLen;
|
||||
this.buffer = new Uint8Array(blockLen);
|
||||
this.buffer32 = (0, utils_ts_1.u32)(this.buffer);
|
||||
}
|
||||
update(data) {
|
||||
(0, utils_ts_1.aexists)(this);
|
||||
data = (0, utils_ts_1.toBytes)(data);
|
||||
(0, utils_ts_1.abytes)(data);
|
||||
// Main difference with other hashes: there is flag for last block,
|
||||
// so we cannot process current block before we know that there
|
||||
// is the next one. This significantly complicates logic and reduces ability
|
||||
// to do zero-copy processing
|
||||
const { blockLen, buffer, buffer32 } = this;
|
||||
const len = data.length;
|
||||
const offset = data.byteOffset;
|
||||
const buf = data.buffer;
|
||||
for (let pos = 0; pos < len;) {
|
||||
// If buffer is full and we still have input (don't process last block, same as blake2s)
|
||||
if (this.pos === blockLen) {
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
this.compress(buffer32, 0, false);
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
this.pos = 0;
|
||||
}
|
||||
const take = Math.min(blockLen - this.pos, len - pos);
|
||||
const dataOffset = offset + pos;
|
||||
// full block && aligned to 4 bytes && not last in input
|
||||
if (take === blockLen && !(dataOffset % 4) && pos + take < len) {
|
||||
const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4));
|
||||
(0, utils_ts_1.swap32IfBE)(data32);
|
||||
for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) {
|
||||
this.length += blockLen;
|
||||
this.compress(data32, pos32, false);
|
||||
}
|
||||
(0, utils_ts_1.swap32IfBE)(data32);
|
||||
continue;
|
||||
}
|
||||
buffer.set(data.subarray(pos, pos + take), this.pos);
|
||||
this.pos += take;
|
||||
this.length += take;
|
||||
pos += take;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
digestInto(out) {
|
||||
(0, utils_ts_1.aexists)(this);
|
||||
(0, utils_ts_1.aoutput)(out, this);
|
||||
const { pos, buffer32 } = this;
|
||||
this.finished = true;
|
||||
// Padding
|
||||
(0, utils_ts_1.clean)(this.buffer.subarray(pos));
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
this.compress(buffer32, 0, true);
|
||||
(0, utils_ts_1.swap32IfBE)(buffer32);
|
||||
const out32 = (0, utils_ts_1.u32)(out);
|
||||
this.get().forEach((v, i) => (out32[i] = (0, utils_ts_1.swap8IfBE)(v)));
|
||||
}
|
||||
digest() {
|
||||
const { buffer, outputLen } = this;
|
||||
this.digestInto(buffer);
|
||||
const res = buffer.slice(0, outputLen);
|
||||
this.destroy();
|
||||
return res;
|
||||
}
|
||||
_cloneInto(to) {
|
||||
const { buffer, length, finished, destroyed, outputLen, pos } = this;
|
||||
to || (to = new this.constructor({ dkLen: outputLen }));
|
||||
to.set(...this.get());
|
||||
to.buffer.set(buffer);
|
||||
to.destroyed = destroyed;
|
||||
to.finished = finished;
|
||||
to.length = length;
|
||||
to.pos = pos;
|
||||
// @ts-ignore
|
||||
to.outputLen = outputLen;
|
||||
return to;
|
||||
}
|
||||
clone() {
|
||||
return this._cloneInto();
|
||||
}
|
||||
}
|
||||
exports.BLAKE2 = BLAKE2;
|
||||
class BLAKE2b extends BLAKE2 {
|
||||
constructor(opts = {}) {
|
||||
const olen = opts.dkLen === undefined ? 64 : opts.dkLen;
|
||||
super(128, olen);
|
||||
// Same as SHA-512, but LE
|
||||
this.v0l = B2B_IV[0] | 0;
|
||||
this.v0h = B2B_IV[1] | 0;
|
||||
this.v1l = B2B_IV[2] | 0;
|
||||
this.v1h = B2B_IV[3] | 0;
|
||||
this.v2l = B2B_IV[4] | 0;
|
||||
this.v2h = B2B_IV[5] | 0;
|
||||
this.v3l = B2B_IV[6] | 0;
|
||||
this.v3h = B2B_IV[7] | 0;
|
||||
this.v4l = B2B_IV[8] | 0;
|
||||
this.v4h = B2B_IV[9] | 0;
|
||||
this.v5l = B2B_IV[10] | 0;
|
||||
this.v5h = B2B_IV[11] | 0;
|
||||
this.v6l = B2B_IV[12] | 0;
|
||||
this.v6h = B2B_IV[13] | 0;
|
||||
this.v7l = B2B_IV[14] | 0;
|
||||
this.v7h = B2B_IV[15] | 0;
|
||||
checkBlake2Opts(olen, opts, 64, 16, 16);
|
||||
let { key, personalization, salt } = opts;
|
||||
let keyLength = 0;
|
||||
if (key !== undefined) {
|
||||
key = (0, utils_ts_1.toBytes)(key);
|
||||
keyLength = key.length;
|
||||
}
|
||||
this.v0l ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24);
|
||||
if (salt !== undefined) {
|
||||
salt = (0, utils_ts_1.toBytes)(salt);
|
||||
const slt = (0, utils_ts_1.u32)(salt);
|
||||
this.v4l ^= (0, utils_ts_1.swap8IfBE)(slt[0]);
|
||||
this.v4h ^= (0, utils_ts_1.swap8IfBE)(slt[1]);
|
||||
this.v5l ^= (0, utils_ts_1.swap8IfBE)(slt[2]);
|
||||
this.v5h ^= (0, utils_ts_1.swap8IfBE)(slt[3]);
|
||||
}
|
||||
if (personalization !== undefined) {
|
||||
personalization = (0, utils_ts_1.toBytes)(personalization);
|
||||
const pers = (0, utils_ts_1.u32)(personalization);
|
||||
this.v6l ^= (0, utils_ts_1.swap8IfBE)(pers[0]);
|
||||
this.v6h ^= (0, utils_ts_1.swap8IfBE)(pers[1]);
|
||||
this.v7l ^= (0, utils_ts_1.swap8IfBE)(pers[2]);
|
||||
this.v7h ^= (0, utils_ts_1.swap8IfBE)(pers[3]);
|
||||
}
|
||||
if (key !== undefined) {
|
||||
// Pad to blockLen and update
|
||||
const tmp = new Uint8Array(this.blockLen);
|
||||
tmp.set(key);
|
||||
this.update(tmp);
|
||||
}
|
||||
}
|
||||
// prettier-ignore
|
||||
get() {
|
||||
let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this;
|
||||
return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h];
|
||||
}
|
||||
// prettier-ignore
|
||||
set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) {
|
||||
this.v0l = v0l | 0;
|
||||
this.v0h = v0h | 0;
|
||||
this.v1l = v1l | 0;
|
||||
this.v1h = v1h | 0;
|
||||
this.v2l = v2l | 0;
|
||||
this.v2h = v2h | 0;
|
||||
this.v3l = v3l | 0;
|
||||
this.v3h = v3h | 0;
|
||||
this.v4l = v4l | 0;
|
||||
this.v4h = v4h | 0;
|
||||
this.v5l = v5l | 0;
|
||||
this.v5h = v5h | 0;
|
||||
this.v6l = v6l | 0;
|
||||
this.v6h = v6h | 0;
|
||||
this.v7l = v7l | 0;
|
||||
this.v7h = v7h | 0;
|
||||
}
|
||||
compress(msg, offset, isLast) {
|
||||
this.get().forEach((v, i) => (BBUF[i] = v)); // First half from state.
|
||||
BBUF.set(B2B_IV, 16); // Second half from IV.
|
||||
let { h, l } = u64.fromBig(BigInt(this.length));
|
||||
BBUF[24] = B2B_IV[8] ^ l; // Low word of the offset.
|
||||
BBUF[25] = B2B_IV[9] ^ h; // High word.
|
||||
// Invert all bits for last block
|
||||
if (isLast) {
|
||||
BBUF[28] = ~BBUF[28];
|
||||
BBUF[29] = ~BBUF[29];
|
||||
}
|
||||
let j = 0;
|
||||
const s = _blake_ts_1.BSIGMA;
|
||||
for (let i = 0; i < 12; i++) {
|
||||
G1b(0, 4, 8, 12, msg, offset + 2 * s[j++]);
|
||||
G2b(0, 4, 8, 12, msg, offset + 2 * s[j++]);
|
||||
G1b(1, 5, 9, 13, msg, offset + 2 * s[j++]);
|
||||
G2b(1, 5, 9, 13, msg, offset + 2 * s[j++]);
|
||||
G1b(2, 6, 10, 14, msg, offset + 2 * s[j++]);
|
||||
G2b(2, 6, 10, 14, msg, offset + 2 * s[j++]);
|
||||
G1b(3, 7, 11, 15, msg, offset + 2 * s[j++]);
|
||||
G2b(3, 7, 11, 15, msg, offset + 2 * s[j++]);
|
||||
G1b(0, 5, 10, 15, msg, offset + 2 * s[j++]);
|
||||
G2b(0, 5, 10, 15, msg, offset + 2 * s[j++]);
|
||||
G1b(1, 6, 11, 12, msg, offset + 2 * s[j++]);
|
||||
G2b(1, 6, 11, 12, msg, offset + 2 * s[j++]);
|
||||
G1b(2, 7, 8, 13, msg, offset + 2 * s[j++]);
|
||||
G2b(2, 7, 8, 13, msg, offset + 2 * s[j++]);
|
||||
G1b(3, 4, 9, 14, msg, offset + 2 * s[j++]);
|
||||
G2b(3, 4, 9, 14, msg, offset + 2 * s[j++]);
|
||||
}
|
||||
this.v0l ^= BBUF[0] ^ BBUF[16];
|
||||
this.v0h ^= BBUF[1] ^ BBUF[17];
|
||||
this.v1l ^= BBUF[2] ^ BBUF[18];
|
||||
this.v1h ^= BBUF[3] ^ BBUF[19];
|
||||
this.v2l ^= BBUF[4] ^ BBUF[20];
|
||||
this.v2h ^= BBUF[5] ^ BBUF[21];
|
||||
this.v3l ^= BBUF[6] ^ BBUF[22];
|
||||
this.v3h ^= BBUF[7] ^ BBUF[23];
|
||||
this.v4l ^= BBUF[8] ^ BBUF[24];
|
||||
this.v4h ^= BBUF[9] ^ BBUF[25];
|
||||
this.v5l ^= BBUF[10] ^ BBUF[26];
|
||||
this.v5h ^= BBUF[11] ^ BBUF[27];
|
||||
this.v6l ^= BBUF[12] ^ BBUF[28];
|
||||
this.v6h ^= BBUF[13] ^ BBUF[29];
|
||||
this.v7l ^= BBUF[14] ^ BBUF[30];
|
||||
this.v7h ^= BBUF[15] ^ BBUF[31];
|
||||
(0, utils_ts_1.clean)(BBUF);
|
||||
}
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
(0, utils_ts_1.clean)(this.buffer32);
|
||||
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
exports.BLAKE2b = BLAKE2b;
|
||||
/**
|
||||
* Blake2b hash function. 64-bit. 1.5x slower than blake2s in JS.
|
||||
* @param msg - message that would be hashed
|
||||
* @param opts - dkLen output length, key for MAC mode, salt, personalization
|
||||
*/
|
||||
exports.blake2b = (0, utils_ts_1.createOptHasher)((opts) => new BLAKE2b(opts));
|
||||
// prettier-ignore
|
||||
function compress(s, offset, msg, rounds, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) {
|
||||
let j = 0;
|
||||
for (let i = 0; i < rounds; i++) {
|
||||
({ a: v0, b: v4, c: v8, d: v12 } = (0, _blake_ts_1.G1s)(v0, v4, v8, v12, msg[offset + s[j++]]));
|
||||
({ a: v0, b: v4, c: v8, d: v12 } = (0, _blake_ts_1.G2s)(v0, v4, v8, v12, msg[offset + s[j++]]));
|
||||
({ a: v1, b: v5, c: v9, d: v13 } = (0, _blake_ts_1.G1s)(v1, v5, v9, v13, msg[offset + s[j++]]));
|
||||
({ a: v1, b: v5, c: v9, d: v13 } = (0, _blake_ts_1.G2s)(v1, v5, v9, v13, msg[offset + s[j++]]));
|
||||
({ a: v2, b: v6, c: v10, d: v14 } = (0, _blake_ts_1.G1s)(v2, v6, v10, v14, msg[offset + s[j++]]));
|
||||
({ a: v2, b: v6, c: v10, d: v14 } = (0, _blake_ts_1.G2s)(v2, v6, v10, v14, msg[offset + s[j++]]));
|
||||
({ a: v3, b: v7, c: v11, d: v15 } = (0, _blake_ts_1.G1s)(v3, v7, v11, v15, msg[offset + s[j++]]));
|
||||
({ a: v3, b: v7, c: v11, d: v15 } = (0, _blake_ts_1.G2s)(v3, v7, v11, v15, msg[offset + s[j++]]));
|
||||
({ a: v0, b: v5, c: v10, d: v15 } = (0, _blake_ts_1.G1s)(v0, v5, v10, v15, msg[offset + s[j++]]));
|
||||
({ a: v0, b: v5, c: v10, d: v15 } = (0, _blake_ts_1.G2s)(v0, v5, v10, v15, msg[offset + s[j++]]));
|
||||
({ a: v1, b: v6, c: v11, d: v12 } = (0, _blake_ts_1.G1s)(v1, v6, v11, v12, msg[offset + s[j++]]));
|
||||
({ a: v1, b: v6, c: v11, d: v12 } = (0, _blake_ts_1.G2s)(v1, v6, v11, v12, msg[offset + s[j++]]));
|
||||
({ a: v2, b: v7, c: v8, d: v13 } = (0, _blake_ts_1.G1s)(v2, v7, v8, v13, msg[offset + s[j++]]));
|
||||
({ a: v2, b: v7, c: v8, d: v13 } = (0, _blake_ts_1.G2s)(v2, v7, v8, v13, msg[offset + s[j++]]));
|
||||
({ a: v3, b: v4, c: v9, d: v14 } = (0, _blake_ts_1.G1s)(v3, v4, v9, v14, msg[offset + s[j++]]));
|
||||
({ a: v3, b: v4, c: v9, d: v14 } = (0, _blake_ts_1.G2s)(v3, v4, v9, v14, msg[offset + s[j++]]));
|
||||
}
|
||||
return { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 };
|
||||
}
|
||||
const B2S_IV = _md_ts_1.SHA256_IV;
|
||||
class BLAKE2s extends BLAKE2 {
|
||||
constructor(opts = {}) {
|
||||
const olen = opts.dkLen === undefined ? 32 : opts.dkLen;
|
||||
super(64, olen);
|
||||
// Internal state, same as SHA-256
|
||||
this.v0 = B2S_IV[0] | 0;
|
||||
this.v1 = B2S_IV[1] | 0;
|
||||
this.v2 = B2S_IV[2] | 0;
|
||||
this.v3 = B2S_IV[3] | 0;
|
||||
this.v4 = B2S_IV[4] | 0;
|
||||
this.v5 = B2S_IV[5] | 0;
|
||||
this.v6 = B2S_IV[6] | 0;
|
||||
this.v7 = B2S_IV[7] | 0;
|
||||
checkBlake2Opts(olen, opts, 32, 8, 8);
|
||||
let { key, personalization, salt } = opts;
|
||||
let keyLength = 0;
|
||||
if (key !== undefined) {
|
||||
key = (0, utils_ts_1.toBytes)(key);
|
||||
keyLength = key.length;
|
||||
}
|
||||
this.v0 ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24);
|
||||
if (salt !== undefined) {
|
||||
salt = (0, utils_ts_1.toBytes)(salt);
|
||||
const slt = (0, utils_ts_1.u32)(salt);
|
||||
this.v4 ^= (0, utils_ts_1.swap8IfBE)(slt[0]);
|
||||
this.v5 ^= (0, utils_ts_1.swap8IfBE)(slt[1]);
|
||||
}
|
||||
if (personalization !== undefined) {
|
||||
personalization = (0, utils_ts_1.toBytes)(personalization);
|
||||
const pers = (0, utils_ts_1.u32)(personalization);
|
||||
this.v6 ^= (0, utils_ts_1.swap8IfBE)(pers[0]);
|
||||
this.v7 ^= (0, utils_ts_1.swap8IfBE)(pers[1]);
|
||||
}
|
||||
if (key !== undefined) {
|
||||
// Pad to blockLen and update
|
||||
(0, utils_ts_1.abytes)(key);
|
||||
const tmp = new Uint8Array(this.blockLen);
|
||||
tmp.set(key);
|
||||
this.update(tmp);
|
||||
}
|
||||
}
|
||||
get() {
|
||||
const { v0, v1, v2, v3, v4, v5, v6, v7 } = this;
|
||||
return [v0, v1, v2, v3, v4, v5, v6, v7];
|
||||
}
|
||||
// prettier-ignore
|
||||
set(v0, v1, v2, v3, v4, v5, v6, v7) {
|
||||
this.v0 = v0 | 0;
|
||||
this.v1 = v1 | 0;
|
||||
this.v2 = v2 | 0;
|
||||
this.v3 = v3 | 0;
|
||||
this.v4 = v4 | 0;
|
||||
this.v5 = v5 | 0;
|
||||
this.v6 = v6 | 0;
|
||||
this.v7 = v7 | 0;
|
||||
}
|
||||
compress(msg, offset, isLast) {
|
||||
const { h, l } = u64.fromBig(BigInt(this.length));
|
||||
// prettier-ignore
|
||||
const { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15 } = compress(_blake_ts_1.BSIGMA, offset, msg, 10, this.v0, this.v1, this.v2, this.v3, this.v4, this.v5, this.v6, this.v7, B2S_IV[0], B2S_IV[1], B2S_IV[2], B2S_IV[3], l ^ B2S_IV[4], h ^ B2S_IV[5], isLast ? ~B2S_IV[6] : B2S_IV[6], B2S_IV[7]);
|
||||
this.v0 ^= v0 ^ v8;
|
||||
this.v1 ^= v1 ^ v9;
|
||||
this.v2 ^= v2 ^ v10;
|
||||
this.v3 ^= v3 ^ v11;
|
||||
this.v4 ^= v4 ^ v12;
|
||||
this.v5 ^= v5 ^ v13;
|
||||
this.v6 ^= v6 ^ v14;
|
||||
this.v7 ^= v7 ^ v15;
|
||||
}
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
(0, utils_ts_1.clean)(this.buffer32);
|
||||
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
exports.BLAKE2s = BLAKE2s;
|
||||
/**
|
||||
* Blake2s hash function. Focuses on 8-bit to 32-bit platforms. 1.5x faster than blake2b in JS.
|
||||
* @param msg - message that would be hashed
|
||||
* @param opts - dkLen output length, key for MAC mode, salt, personalization
|
||||
*/
|
||||
exports.blake2s = (0, utils_ts_1.createOptHasher)((opts) => new BLAKE2s(opts));
|
||||
//# sourceMappingURL=blake2.js.map
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "pino-std-serializers",
|
||||
"version": "7.1.0",
|
||||
"description": "A collection of standard object serializers for Pino",
|
||||
"main": "index.js",
|
||||
"type": "commonjs",
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"lint-ci": "eslint --max-warnings=0 .",
|
||||
"test": "borp -p 'test/**/*.js'",
|
||||
"test-ci": "borp --coverage -p 'test/**/*.js'",
|
||||
"test-types": "tsc && tsd"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/pinojs/pino-std-serializers.git"
|
||||
},
|
||||
"keywords": [
|
||||
"pino",
|
||||
"logging"
|
||||
],
|
||||
"author": "James Sumners <james.sumners@gmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/pinojs/pino-std-serializers/issues"
|
||||
},
|
||||
"homepage": "https://github.com/pinojs/pino-std-serializers#readme",
|
||||
"devDependencies": {
|
||||
"@matteo.collina/tspl": "^0.2.0",
|
||||
"@types/node": "^25.0.3",
|
||||
"borp": "^0.21.0",
|
||||
"eslint": "^9.39.2",
|
||||
"neostandard": "^0.12.2",
|
||||
"tsd": "^0.33.0",
|
||||
"typescript": "~5.9.3"
|
||||
},
|
||||
"tsd": {
|
||||
"directory": "test/types"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
"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: "karakter", verb: "legyen" },
|
||||
file: { unit: "byte", verb: "legyen" },
|
||||
array: { unit: "elem", verb: "legyen" },
|
||||
set: { unit: "elem", verb: "legyen" },
|
||||
};
|
||||
function getSizing(origin) {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
const FormatDictionary = {
|
||||
regex: "bemenet",
|
||||
email: "email cím",
|
||||
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 időbélyeg",
|
||||
date: "ISO dátum",
|
||||
time: "ISO idő",
|
||||
duration: "ISO időintervallum",
|
||||
ipv4: "IPv4 cím",
|
||||
ipv6: "IPv6 cím",
|
||||
cidrv4: "IPv4 tartomány",
|
||||
cidrv6: "IPv6 tartomány",
|
||||
base64: "base64-kódolt string",
|
||||
base64url: "base64url-kódolt string",
|
||||
json_string: "JSON string",
|
||||
e164: "E.164 szám",
|
||||
jwt: "JWT",
|
||||
template_literal: "bemenet",
|
||||
};
|
||||
const TypeDictionary = {
|
||||
nan: "NaN",
|
||||
number: "szám",
|
||||
array: "tömb",
|
||||
};
|
||||
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 `Érvénytelen bemenet: a várt érték instanceof ${issue.expected}, a kapott érték ${received}`;
|
||||
}
|
||||
return `Érvénytelen bemenet: a várt érték ${expected}, a kapott érték ${received}`;
|
||||
}
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `Érvénytelen bemenet: a várt érték ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Érvénytelen opció: valamelyik érték várt ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Túl nagy: ${issue.origin ?? "érték"} mérete túl nagy ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elem"}`;
|
||||
return `Túl nagy: a bemeneti érték ${issue.origin ?? "érték"} túl nagy: ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Túl kicsi: a bemeneti érték ${issue.origin} mérete túl kicsi ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `Túl kicsi: a bemeneti érték ${issue.origin} túl kicsi ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue;
|
||||
if (_issue.format === "starts_with")
|
||||
return `Érvénytelen string: "${_issue.prefix}" értékkel kell kezdődnie`;
|
||||
if (_issue.format === "ends_with")
|
||||
return `Érvénytelen string: "${_issue.suffix}" értékkel kell végződnie`;
|
||||
if (_issue.format === "includes")
|
||||
return `Érvénytelen string: "${_issue.includes}" értéket kell tartalmaznia`;
|
||||
if (_issue.format === "regex")
|
||||
return `Érvénytelen string: ${_issue.pattern} mintának kell megfelelnie`;
|
||||
return `Érvénytelen ${FormatDictionary[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Érvénytelen szám: ${issue.divisor} többszörösének kell lennie`;
|
||||
case "unrecognized_keys":
|
||||
return `Ismeretlen kulcs${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Érvénytelen kulcs ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Érvénytelen bemenet";
|
||||
case "invalid_element":
|
||||
return `Érvénytelen érték: ${issue.origin}`;
|
||||
default:
|
||||
return `Érvénytelen bemenet`;
|
||||
}
|
||||
};
|
||||
};
|
||||
function default_1() {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
module.exports = exports.default;
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_set_prototype_of.cjs",
|
||||
"module": "../../esm/_set_prototype_of.js"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
nodeLinker: pnp
|
||||
pnpMode: loose
|
||||
pnpEnableEsmLoader: false
|
||||
packageExtensions:
|
||||
debug@*:
|
||||
dependencies:
|
||||
supports-color: '*'
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Un-escape a string that has been escaped with {@link escape}.
|
||||
*
|
||||
* If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then
|
||||
* square-bracket escapes are removed, but not backslash escapes.
|
||||
*
|
||||
* For example, it will turn the string `'[*]'` into `*`, but it will not
|
||||
* turn `'\\*'` into `'*'`, because `\` is a path separator in
|
||||
* `windowsPathsNoEscape` mode.
|
||||
*
|
||||
* When `windowsPathsNoEscape` is not set, then both square-bracket escapes and
|
||||
* backslash escapes are removed.
|
||||
*
|
||||
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
|
||||
* or unescaped.
|
||||
*
|
||||
* When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be
|
||||
* unescaped.
|
||||
*/
|
||||
export const unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true, } = {}) => {
|
||||
if (magicalBraces) {
|
||||
return windowsPathsNoEscape ?
|
||||
s.replace(/\[([^/\\])\]/g, '$1')
|
||||
: s
|
||||
.replace(/((?!\\).|^)\[([^/\\])\]/g, '$1$2')
|
||||
.replace(/\\([^/])/g, '$1');
|
||||
}
|
||||
return windowsPathsNoEscape ?
|
||||
s.replace(/\[([^/\\{}])\]/g, '$1')
|
||||
: s
|
||||
.replace(/((?!\\).|^)\[([^/\\{}])\]/g, '$1$2')
|
||||
.replace(/\\([^/{}])/g, '$1');
|
||||
};
|
||||
//# sourceMappingURL=unescape.js.map
|
||||
@@ -0,0 +1,123 @@
|
||||
declare class MockerRegistry {
|
||||
private readonly registryByUrl;
|
||||
private readonly registryById;
|
||||
clear(): void;
|
||||
keys(): IterableIterator<string>;
|
||||
add(mock: MockedModule): void;
|
||||
register(json: MockedModuleSerialized): MockedModule;
|
||||
register(type: "redirect", raw: string, id: string, url: string, redirect: string): RedirectedModule;
|
||||
register(type: "manual", raw: string, id: string, url: string, factory: () => any): ManualMockedModule;
|
||||
register(type: "automock", raw: string, id: string, url: string): AutomockedModule;
|
||||
register(type: "autospy", id: string, raw: string, url: string): AutospiedModule;
|
||||
delete(id: string): void;
|
||||
deleteById(id: string): void;
|
||||
get(id: string): MockedModule | undefined;
|
||||
getById(id: string): MockedModule | undefined;
|
||||
has(id: string): boolean;
|
||||
}
|
||||
type MockedModule = AutomockedModule | AutospiedModule | ManualMockedModule | RedirectedModule;
|
||||
type MockedModuleType = "automock" | "autospy" | "manual" | "redirect";
|
||||
type MockedModuleSerialized = AutomockedModuleSerialized | AutospiedModuleSerialized | ManualMockedModuleSerialized | RedirectedModuleSerialized;
|
||||
declare class AutomockedModule {
|
||||
raw: string;
|
||||
id: string;
|
||||
url: string;
|
||||
readonly type = "automock";
|
||||
constructor(raw: string, id: string, url: string);
|
||||
static fromJSON(data: AutomockedModuleSerialized): AutospiedModule;
|
||||
toJSON(): AutomockedModuleSerialized;
|
||||
}
|
||||
interface AutomockedModuleSerialized {
|
||||
type: "automock";
|
||||
url: string;
|
||||
raw: string;
|
||||
id: string;
|
||||
}
|
||||
declare class AutospiedModule {
|
||||
raw: string;
|
||||
id: string;
|
||||
url: string;
|
||||
readonly type = "autospy";
|
||||
constructor(raw: string, id: string, url: string);
|
||||
static fromJSON(data: AutospiedModuleSerialized): AutospiedModule;
|
||||
toJSON(): AutospiedModuleSerialized;
|
||||
}
|
||||
interface AutospiedModuleSerialized {
|
||||
type: "autospy";
|
||||
url: string;
|
||||
raw: string;
|
||||
id: string;
|
||||
}
|
||||
declare class RedirectedModule {
|
||||
raw: string;
|
||||
id: string;
|
||||
url: string;
|
||||
redirect: string;
|
||||
readonly type = "redirect";
|
||||
constructor(raw: string, id: string, url: string, redirect: string);
|
||||
static fromJSON(data: RedirectedModuleSerialized): RedirectedModule;
|
||||
toJSON(): RedirectedModuleSerialized;
|
||||
}
|
||||
interface RedirectedModuleSerialized {
|
||||
type: "redirect";
|
||||
url: string;
|
||||
id: string;
|
||||
raw: string;
|
||||
redirect: string;
|
||||
}
|
||||
declare class ManualMockedModule<T = any> {
|
||||
raw: string;
|
||||
id: string;
|
||||
url: string;
|
||||
factory: () => T;
|
||||
cache: T | undefined;
|
||||
readonly type = "manual";
|
||||
constructor(raw: string, id: string, url: string, factory: () => T);
|
||||
resolve(): T;
|
||||
static fromJSON(data: ManualMockedModuleSerialized, factory: () => any): ManualMockedModule;
|
||||
toJSON(): ManualMockedModuleSerialized;
|
||||
}
|
||||
interface ManualMockedModuleSerialized {
|
||||
type: "manual";
|
||||
url: string;
|
||||
id: string;
|
||||
raw: string;
|
||||
}
|
||||
|
||||
type Awaitable<T> = T | PromiseLike<T>;
|
||||
type ModuleMockFactoryWithHelper<M = unknown> = (importOriginal: <T extends M = M>() => Promise<T>) => Awaitable<Partial<M>>;
|
||||
type ModuleMockFactory = () => any;
|
||||
interface ModuleMockOptions {
|
||||
spy?: boolean;
|
||||
}
|
||||
interface ServerMockResolution {
|
||||
mockType: "manual" | "redirect" | "automock" | "autospy";
|
||||
resolvedId: string;
|
||||
resolvedUrl: string;
|
||||
needsInterop?: boolean;
|
||||
redirectUrl?: string | null;
|
||||
}
|
||||
interface ServerIdResolution {
|
||||
id: string;
|
||||
url: string;
|
||||
optimized: boolean;
|
||||
}
|
||||
interface ModuleMockContext {
|
||||
/**
|
||||
* When mocking with a factory, this refers to the module that imported the mock.
|
||||
*/
|
||||
callstack: null | string[];
|
||||
}
|
||||
interface TestModuleMocker {
|
||||
queueMock(id: string, importer: string, factoryOrOptions?: ModuleMockFactory | ModuleMockOptions): void;
|
||||
queueUnmock(id: string, importer: string): void;
|
||||
importActual<T>(rawId: string, importer: string, callstack?: string[] | null): Promise<T>;
|
||||
importMock(rawId: string, importer: string): Promise<any>;
|
||||
mockObject(object: Record<string | symbol, any>, moduleType?: "automock" | "autospy"): Record<string | symbol, any>;
|
||||
mockObject(object: Record<string | symbol, any>, mockExports: Record<string | symbol, any> | undefined, moduleType?: "automock" | "autospy"): Record<string | symbol, any>;
|
||||
getMockContext(): ModuleMockContext;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
export { AutomockedModule as A, MockerRegistry as M, RedirectedModule as R, AutospiedModule as h, ManualMockedModule as j };
|
||||
export type { ServerMockResolution as S, TestModuleMocker as T, MockedModule as a, ModuleMockOptions as b, ModuleMockFactoryWithHelper as c, MockedModuleType as d, ModuleMockContext as e, ServerIdResolution as f, AutomockedModuleSerialized as g, AutospiedModuleSerialized as i, ManualMockedModuleSerialized as k, MockedModuleSerialized as l, ModuleMockFactory as m, RedirectedModuleSerialized as n };
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "../../cjs/_create_super.cjs",
|
||||
"module": "../../esm/_create_super.js"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import Dispatcher from './dispatcher'
|
||||
|
||||
export default Dispatcher1Wrapper
|
||||
|
||||
declare class Dispatcher1Wrapper extends Dispatcher {
|
||||
constructor (dispatcher: Dispatcher)
|
||||
}
|
||||
Reference in New Issue
Block a user