WIP: bootstrap and partial real Solana watcher implementation

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

View File

@@ -0,0 +1,13 @@
# `@humanfs/types`
by [Nicholas C. Zakas](https://humanwhocodes.com)
If you find this useful, please consider supporting my work with a [donation](https://humanwhocodes.com/donate) or [nominate me](https://stars.github.com/nominate/) for a GitHub Star.
## Description
Additional type definitions for humanfs. These are used primarily to share type definitions across packages because there is no easy way to export imported type definitions using JavaScript and JSDoc.
## License
Apache 2.0

View File

@@ -0,0 +1,146 @@
/**
* @fileoverview Disallow mixed spaces and tabs for indentation
* @author Jary Niebur
* @deprecated in ESLint v8.53.0
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "no-mixed-spaces-and-tabs",
url: "https://eslint.style/rules/no-mixed-spaces-and-tabs",
},
},
],
},
type: "layout",
docs: {
description: "Disallow mixed spaces and tabs for indentation",
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-mixed-spaces-and-tabs",
},
schema: [
{
enum: ["smart-tabs", true, false],
},
],
messages: {
mixedSpacesAndTabs: "Mixed spaces and tabs.",
},
},
create(context) {
const sourceCode = context.sourceCode;
let smartTabs;
switch (context.options[0]) {
case true: // Support old syntax, maybe add deprecation warning here
case "smart-tabs":
smartTabs = true;
break;
default:
smartTabs = false;
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
"Program:exit"(node) {
const lines = sourceCode.lines,
comments = sourceCode.getAllComments(),
ignoredCommentLines = new Set();
// Add all lines except the first ones.
comments.forEach(comment => {
for (
let i = comment.loc.start.line + 1;
i <= comment.loc.end.line;
i++
) {
ignoredCommentLines.add(i);
}
});
/*
* At least one space followed by a tab
* or the reverse before non-tab/-space
* characters begin.
*/
let regex = /^(?=( +|\t+))\1(?:\t| )/u;
if (smartTabs) {
/*
* At least one space followed by a tab
* before non-tab/-space characters begin.
*/
// eslint-disable-next-line regexp/no-empty-lookarounds-assertion -- False positive
regex = /^(?=(\t*))\1(?=( +))\2\t/u;
}
lines.forEach((line, i) => {
const match = regex.exec(line);
if (match) {
const lineNumber = i + 1;
const loc = {
start: {
line: lineNumber,
column: match[0].length - 2,
},
end: {
line: lineNumber,
column: match[0].length,
},
};
if (!ignoredCommentLines.has(lineNumber)) {
const containingNode =
sourceCode.getNodeByRangeIndex(
sourceCode.getIndexFromLoc(loc.start),
);
if (!(
containingNode &&
["Literal", "TemplateElement"].includes(
containingNode.type,
)
)) {
context.report({
node,
loc,
messageId: "mixedSpacesAndTabs",
});
}
}
}
});
},
};
},
};

View File

@@ -0,0 +1,19 @@
import type { Node, SourceFile } from "./ast.ts";
export declare function getTokenAtPosition(sourceFile: SourceFile, position: number): Node;
export declare function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node;
export declare function getTouchingToken(sourceFile: SourceFile, position: number): Node;
/**
* Finds the token that starts immediately after `previousToken` ends, searching
* within `parent`. Returns `undefined` if no such token exists.
*/
export declare function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFile): Node | undefined;
/**
* Finds the leftmost token satisfying `position < token.end`.
* If the position is in the trivia of that leftmost token, or the token is invalid,
* returns the rightmost valid token with `token.end <= position`.
* Excludes `JsxText` tokens containing only whitespace.
*/
export declare function findPrecedingToken(sourceFile: SourceFile, position: number): Node | undefined;
/** @internal */
export declare function getTokenPosOfNode(node: Node, sourceFile: SourceFile, includeJSDoc?: boolean): number;
//# sourceMappingURL=astnav.d.ts.map

View File

@@ -0,0 +1,12 @@
/**
* @deprecated
* @module
*/
import { jubjub_findGroupHash, jubjub_groupHash, jubjub as jubjubn } from './misc.ts';
/** @deprecated use `import { jubjub } from '@noble/curves/misc.js';` */
export const jubjub: typeof jubjubn = jubjubn;
/** @deprecated use `import { jubjub_findGroupHash } from '@noble/curves/misc.js';` */
export const findGroupHash: typeof jubjub_findGroupHash = jubjub_findGroupHash;
/** @deprecated use `import { jubjub_groupHash } from '@noble/curves/misc.js';` */
export const groupHash: typeof jubjub_groupHash = jubjub_groupHash;

View File

@@ -0,0 +1,390 @@
const { test } = require('node:test')
const { strict: assert } = require('node:assert')
const slowRedact = require('../index.js')
const fastRedact = require('fast-redact')
test('integration: basic path redaction matches fast-redact', () => {
const obj = {
headers: {
cookie: 'secret-cookie',
authorization: 'Bearer token'
},
body: { message: 'hello' }
}
const slowResult = slowRedact({ paths: ['headers.cookie'] })(obj)
const fastResult = fastRedact({ paths: ['headers.cookie'] })(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: multiple paths match fast-redact', () => {
const obj = {
user: { name: 'john', password: 'secret' },
session: { token: 'abc123' }
}
const paths = ['user.password', 'session.token']
const slowResult = slowRedact({ paths })(obj)
const fastResult = fastRedact({ paths })(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: custom censor value matches fast-redact', () => {
const obj = { secret: 'hidden' }
const options = { paths: ['secret'], censor: '***' }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: bracket notation matches fast-redact', () => {
const obj = {
'weird-key': { 'another-weird': 'secret' },
normal: 'public'
}
const options = { paths: ['["weird-key"]["another-weird"]'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: array paths match fast-redact', () => {
const obj = {
users: [
{ name: 'john', password: 'secret1' },
{ name: 'jane', password: 'secret2' }
]
}
const options = { paths: ['users[0].password', 'users[1].password'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: wildcard at end matches fast-redact', () => {
const obj = {
secrets: {
key1: 'secret1',
key2: 'secret2'
},
public: 'data'
}
const options = { paths: ['secrets.*'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: wildcard with arrays matches fast-redact', () => {
const obj = {
items: ['secret1', 'secret2', 'secret3']
}
const options = { paths: ['items.*'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: intermediate wildcard matches fast-redact', () => {
const obj = {
users: {
user1: { password: 'secret1' },
user2: { password: 'secret2' }
}
}
const options = { paths: ['users.*.password'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: custom serialize function matches fast-redact', () => {
const obj = { secret: 'hidden', public: 'data' }
const options = {
paths: ['secret'],
serialize: (obj) => `custom:${JSON.stringify(obj)}`
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: nested paths match fast-redact', () => {
const obj = {
level1: {
level2: {
level3: {
secret: 'hidden'
}
}
}
}
const options = { paths: ['level1.level2.level3.secret'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: non-existent paths match fast-redact', () => {
const obj = { existing: 'value' }
const options = { paths: ['nonexistent.path'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: null and undefined handling - legitimate difference', () => {
const obj = {
nullValue: null,
undefinedValue: undefined,
nested: {
nullValue: null
}
}
const options = { paths: ['nullValue', 'nested.nullValue'] }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
// This is a legitimate behavioral difference:
// @pinojs/redact redacts null values, fast-redact doesn't
const slowParsed = JSON.parse(slowResult)
const fastParsed = JSON.parse(fastResult)
// @pinojs/redact redacts nulls
assert.strictEqual(slowParsed.nullValue, '[REDACTED]')
assert.strictEqual(slowParsed.nested.nullValue, '[REDACTED]')
// fast-redact preserves nulls
assert.strictEqual(fastParsed.nullValue, null)
assert.strictEqual(fastParsed.nested.nullValue, null)
})
test('integration: strict mode with primitives - different error handling', () => {
const options = { paths: ['test'], strict: true }
const slowRedactFn = slowRedact(options)
const fastRedactFn = fastRedact(options)
// @pinojs/redact handles primitives gracefully
const stringSlowResult = slowRedactFn('primitive')
assert.strictEqual(stringSlowResult, '"primitive"')
const numberSlowResult = slowRedactFn(42)
assert.strictEqual(numberSlowResult, '42')
// fast-redact throws an error for primitives in strict mode
assert.throws(() => {
fastRedactFn('primitive')
}, /primitives cannot be redacted/)
assert.throws(() => {
fastRedactFn(42)
}, /primitives cannot be redacted/)
})
test('integration: serialize false behavior difference', () => {
const slowObj = { secret: 'hidden' }
const fastObj = { secret: 'hidden' }
const options = { paths: ['secret'], serialize: false }
const slowResult = slowRedact(options)(slowObj)
const fastResult = fastRedact(options)(fastObj)
// Both should redact the secret
assert.strictEqual(slowResult.secret, '[REDACTED]')
assert.strictEqual(fastResult.secret, '[REDACTED]')
// @pinojs/redact always has restore method
assert.strictEqual(typeof slowResult.restore, 'function')
// @pinojs/redact should restore to original value
assert.strictEqual(slowResult.restore().secret, 'hidden')
// Key difference: original object state
// fast-redact mutates the original, @pinojs/redact doesn't
assert.strictEqual(slowObj.secret, 'hidden') // @pinojs/redact preserves original
assert.strictEqual(fastObj.secret, '[REDACTED]') // fast-redact mutates original
})
test('integration: censor function behavior', () => {
const obj = { secret: 'hidden' }
const options = {
paths: ['secret'],
censor: (value, path) => `REDACTED:${path}`
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: complex object with mixed patterns', () => {
const obj = {
users: [
{
id: 1,
name: 'john',
credentials: { password: 'secret1', apiKey: 'key1' }
},
{
id: 2,
name: 'jane',
credentials: { password: 'secret2', apiKey: 'key2' }
}
],
config: {
database: { password: 'db-secret' },
api: { keys: ['key1', 'key2', 'key3'] }
}
}
const options = {
paths: [
'users.*.credentials.password',
'users.*.credentials.apiKey',
'config.database.password',
'config.api.keys.*'
]
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
// Remove option integration tests - comparing with fast-redact
test('integration: remove option basic comparison with fast-redact', () => {
const obj = { username: 'john', password: 'secret123' }
const options = { paths: ['password'], remove: true }
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
// Verify the key is actually removed
const parsed = JSON.parse(slowResult)
assert.strictEqual(parsed.username, 'john')
assert.strictEqual('password' in parsed, false)
})
test('integration: remove option multiple paths comparison with fast-redact', () => {
const obj = {
user: { name: 'john', password: 'secret' },
session: { token: 'abc123', id: 'session1' }
}
const options = {
paths: ['user.password', 'session.token'],
remove: true
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: remove option wildcard comparison with fast-redact', () => {
const obj = {
secrets: {
key1: 'secret1',
key2: 'secret2'
},
public: 'data'
}
const options = {
paths: ['secrets.*'],
remove: true
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: remove option intermediate wildcard comparison with fast-redact', () => {
const obj = {
users: {
user1: { password: 'secret1', name: 'john' },
user2: { password: 'secret2', name: 'jane' }
}
}
const options = {
paths: ['users.*.password'],
remove: true
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
})
test('integration: remove option with custom censor comparison with fast-redact', () => {
const obj = { secret: 'hidden', public: 'data' }
const options = {
paths: ['secret'],
censor: '***',
remove: true
}
const slowResult = slowRedact(options)(obj)
const fastResult = fastRedact(options)(obj)
assert.strictEqual(slowResult, fastResult)
// With remove: true, censor value should be ignored
const parsed = JSON.parse(slowResult)
assert.strictEqual('secret' in parsed, false)
assert.strictEqual(parsed.public, 'data')
})
test('integration: remove option serialize false behavior - @pinojs/redact only', () => {
// fast-redact doesn't support remove option with serialize: false
// so we test @pinojs/redact's behavior only
const obj = { secret: 'hidden', public: 'data' }
const options = { paths: ['secret'], remove: true, serialize: false }
const result = slowRedact(options)(obj)
// Should have the key removed
assert.strictEqual('secret' in result, false)
assert.strictEqual(result.public, 'data')
// Should have restore method
assert.strictEqual(typeof result.restore, 'function')
// Original object should be preserved
assert.strictEqual(obj.secret, 'hidden')
// Restore should bring back the removed key
const restored = result.restore()
assert.strictEqual(restored.secret, 'hidden')
})

View File

@@ -0,0 +1,11 @@
'use strict';
const Parser = require('./Parser');
const emit = require('./utils/emit');
const make = options => emit(new Parser(options));
make.Parser = Parser;
make.parser = Parser.parser;
module.exports = make;

View File

@@ -0,0 +1,402 @@
/**
* @fileoverview Rule to check for the usage of var.
* @author Jamund Ferguson
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/** @typedef {import("eslint-scope").Scope} Scope */
/** @typedef {import("eslint-scope").Variable} Variable */
/** @typedef {import("eslint-scope").Reference} Reference */
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Check whether a given variable is a global variable or not.
* @param {Variable} variable The variable to check.
* @returns {boolean} `true` if the variable is a global variable.
*/
function isGlobal(variable) {
return Boolean(variable.scope) && variable.scope.type === "global";
}
/**
* Finds the nearest function scope or global scope walking up the scope
* hierarchy.
* @param {Scope} scope The scope to traverse.
* @returns {Scope} a function scope or global scope containing the given
* scope.
*/
function getEnclosingFunctionScope(scope) {
let currentScope = scope;
while (currentScope.type !== "function" && currentScope.type !== "global") {
currentScope = currentScope.upper;
}
return currentScope;
}
/**
* Checks whether the given variable has any references from a more specific
* function expression (i.e. a closure).
* @param {Variable} variable A variable to check.
* @returns {boolean} `true` if the variable is used from a closure.
*/
function isReferencedInClosure(variable) {
const enclosingFunctionScope = getEnclosingFunctionScope(variable.scope);
return variable.references.some(
reference =>
getEnclosingFunctionScope(reference.from) !==
enclosingFunctionScope,
);
}
/**
* Checks whether the given node is the assignee of a loop.
* @param {ASTNode} node A VariableDeclaration node to check.
* @returns {boolean} `true` if the declaration is assigned as part of loop
* iteration.
*/
function isLoopAssignee(node) {
return (
(node.parent.type === "ForOfStatement" ||
node.parent.type === "ForInStatement") &&
node === node.parent.left
);
}
/**
* Checks whether the given variable declaration is immediately initialized.
* @param {ASTNode} node A VariableDeclaration node to check.
* @returns {boolean} `true` if the declaration has an initializer.
*/
function isDeclarationInitialized(node) {
return node.declarations.every(declarator => declarator.init !== null);
}
const SCOPE_NODE_TYPE =
/^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/u;
/**
* Gets the scope node which directly contains a given node.
* @param {ASTNode} node A node to get. This is a `VariableDeclaration` or
* an `Identifier`.
* @returns {ASTNode} A scope node. This is one of `Program`, `BlockStatement`,
* `SwitchStatement`, `ForStatement`, `ForInStatement`, and
* `ForOfStatement`.
*/
function getScopeNode(node) {
for (
let currentNode = node;
currentNode;
currentNode = currentNode.parent
) {
if (SCOPE_NODE_TYPE.test(currentNode.type)) {
return currentNode;
}
}
/* c8 ignore next */
return null;
}
/**
* Checks whether a given variable is redeclared or not.
* @param {Variable} variable A variable to check.
* @returns {boolean} `true` if the variable is redeclared.
*/
function isRedeclared(variable) {
return variable.defs.length >= 2;
}
/**
* Checks whether a given variable is used from outside of the specified scope.
* @param {ASTNode} scopeNode A scope node to check.
* @returns {Function} The predicate function which checks whether a given
* variable is used from outside of the specified scope.
*/
function isUsedFromOutsideOf(scopeNode) {
/**
* Checks whether a given reference is inside of the specified scope or not.
* @param {Reference} reference A reference to check.
* @returns {boolean} `true` if the reference is inside of the specified
* scope.
*/
function isOutsideOfScope(reference) {
const scope = scopeNode.range;
const id = reference.identifier.range;
return id[0] < scope[0] || id[1] > scope[1];
}
return function (variable) {
return variable.references.some(isOutsideOfScope);
};
}
/**
* Creates the predicate function which checks whether a variable has their references in TDZ.
*
* The predicate function would return `true`:
*
* - if a reference is before the declarator. E.g. (var a = b, b = 1;)(var {a = b, b} = {};)
* - if a reference is in the expression of their default value. E.g. (var {a = a} = {};)
* - if a reference is in the expression of their initializer. E.g. (var a = a;)
* @param {ASTNode} node The initializer node of VariableDeclarator.
* @returns {Function} The predicate function.
* @private
*/
function hasReferenceInTDZ(node) {
const initStart = node.range[0];
const initEnd = node.range[1];
return variable => {
const id = variable.defs[0].name;
const idStart = id.range[0];
const defaultValue =
id.parent.type === "AssignmentPattern" ? id.parent.right : null;
const defaultStart = defaultValue && defaultValue.range[0];
const defaultEnd = defaultValue && defaultValue.range[1];
return variable.references.some(reference => {
const start = reference.identifier.range[0];
const end = reference.identifier.range[1];
return (
!reference.init &&
(start < idStart ||
(defaultValue !== null &&
start >= defaultStart &&
end <= defaultEnd) ||
(!astUtils.isFunction(node) &&
start >= initStart &&
end <= initEnd))
);
});
};
}
/**
* Checks whether a given variable has name that is allowed for 'var' declarations,
* but disallowed for `let` declarations.
* @param {Variable} variable The variable to check.
* @returns {boolean} `true` if the variable has a disallowed name.
*/
function hasNameDisallowedForLetDeclarations(variable) {
return variable.name === "let";
}
/**
* Checks whether a given variable has any references before its declaration.
* This is important because var allows hoisting, but let/const do not.
* @param {Variable} variable The variable to check.
* @returns {boolean} `true` if the variable is referenced before its declaration.
*/
function hasReferenceBeforeDeclaration(variable) {
const declarationStart = variable.defs[0].node.range[0];
return variable.references.some(reference => {
const referenceStart = reference.identifier.range[0];
/*
* Check if the reference occurs before the declaration.
* We don't need to check scopes because all references to this variable
* are already in variable.references (which only includes references
* that resolve to this specific variable binding).
*/
return !reference.init && referenceStart < declarationStart;
});
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "Require `let` or `const` instead of `var`",
dialects: ["JavaScript", "TypeScript"],
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-var",
},
schema: [],
fixable: "code",
messages: {
unexpectedVar: "Unexpected var, use let or const instead.",
},
},
create(context) {
const sourceCode = context.sourceCode;
/**
* Checks whether the variables which are defined by the given declarator node have their references in TDZ.
* @param {ASTNode} declarator The VariableDeclarator node to check.
* @returns {boolean} `true` if one of the variables which are defined by the given declarator node have their references in TDZ.
*/
function hasSelfReferenceInTDZ(declarator) {
if (!declarator.init) {
return false;
}
const variables = sourceCode.getDeclaredVariables(declarator);
return variables.some(hasReferenceInTDZ(declarator.init));
}
/**
* Checks whether it can fix a given variable declaration or not.
* It cannot fix if the following cases:
*
* - A variable is a global variable.
* - A variable is declared on a SwitchCase node.
* - A variable is redeclared.
* - A variable is used from outside the scope.
* - A variable is used from a closure within a loop.
* - A variable might be used before it is assigned within a loop.
* - A variable might be used in TDZ.
* - A variable is referenced before its declaration.
* - A variable is declared in statement position (e.g. a single-line `IfStatement`)
* - A variable has name that is disallowed for `let` declarations.
*
* ## A variable is declared on a SwitchCase node.
*
* If this rule modifies 'var' declarations on a SwitchCase node, it
* would generate the warnings of 'no-case-declarations' rule. And the
* 'eslint:recommended' preset includes 'no-case-declarations' rule, so
* this rule doesn't modify those declarations.
*
* ## A variable is redeclared.
*
* The language spec disallows redeclarations of `let` declarations.
* Those variables would cause syntax errors.
*
* ## A variable is used from outside the scope.
*
* The language spec disallows accesses from outside of the scope for
* `let` declarations. Those variables would cause reference errors.
*
* ## A variable is used from a closure within a loop.
*
* A `var` declaration within a loop shares the same variable instance
* across all loop iterations, while a `let` declaration creates a new
* instance for each iteration. This means if a variable in a loop is
* referenced by any closure, changing it from `var` to `let` would
* change the behavior in a way that is generally unsafe.
*
* ## A variable might be used before it is assigned within a loop.
*
* Within a loop, a `let` declaration without an initializer will be
* initialized to null, while a `var` declaration will retain its value
* from the previous iteration, so it is only safe to change `var` to
* `let` if we can statically determine that the variable is always
* assigned a value before its first access in the loop body. To keep
* the implementation simple, we only convert `var` to `let` within
* loops when the variable is a loop assignee or the declaration has an
* initializer.
* @param {ASTNode} node A variable declaration node to check.
* @returns {boolean} `true` if it can fix the node.
*/
function canFix(node) {
const variables = sourceCode.getDeclaredVariables(node);
const scopeNode = getScopeNode(node);
const parentStatementList = new Set([
...astUtils.STATEMENT_LIST_PARENTS,
"TSModuleBlock",
]);
if (
node.parent.type === "SwitchCase" ||
node.declarations.some(hasSelfReferenceInTDZ) ||
variables.some(isGlobal) ||
variables.some(isRedeclared) ||
variables.some(isUsedFromOutsideOf(scopeNode)) ||
variables.some(hasNameDisallowedForLetDeclarations) ||
variables.some(hasReferenceBeforeDeclaration)
) {
return false;
}
if (astUtils.isInLoop(node)) {
if (variables.some(isReferencedInClosure)) {
return false;
}
if (!isLoopAssignee(node) && !isDeclarationInitialized(node)) {
return false;
}
}
if (
!isLoopAssignee(node) &&
!(
node.parent.type === "ForStatement" &&
node.parent.init === node
) &&
!parentStatementList.has(node.parent.type)
) {
// If the declaration is not in a block, e.g. `if (foo) var bar = 1;`, then it can't be fixed.
return false;
}
return true;
}
/**
* Reports a given variable declaration node.
* @param {ASTNode} node A variable declaration node to report.
* @returns {void}
*/
function report(node) {
context.report({
node,
messageId: "unexpectedVar",
fix(fixer) {
const varToken = sourceCode.getFirstToken(node, {
filter: t => t.value === "var",
});
return canFix(node)
? fixer.replaceText(varToken, "let")
: null;
},
});
}
return {
"VariableDeclaration:exit"(node) {
if (node.kind !== "var") {
return;
}
if (
node.parent.type === "TSModuleBlock" &&
node.parent.parent.type === "TSModuleDeclaration" &&
node.parent.parent.global
) {
return;
}
report(node);
},
};
},
};

View File

@@ -0,0 +1,140 @@
import {AccountKeysFromLookups} from '../message/account-keys';
import assert from '../utils/assert';
import {toBuffer} from '../utils/to-buffer';
import {Blockhash} from '../blockhash';
import {Message, MessageV0, VersionedMessage} from '../message';
import {PublicKey} from '../publickey';
import {AddressLookupTableAccount} from '../programs';
import {AccountMeta, TransactionInstruction} from './legacy';
export type TransactionMessageArgs = {
payerKey: PublicKey;
instructions: Array<TransactionInstruction>;
recentBlockhash: Blockhash;
};
export type DecompileArgs =
| {
accountKeysFromLookups: AccountKeysFromLookups;
}
| {
addressLookupTableAccounts: AddressLookupTableAccount[];
};
export class TransactionMessage {
payerKey: PublicKey;
instructions: Array<TransactionInstruction>;
recentBlockhash: Blockhash;
constructor(args: TransactionMessageArgs) {
this.payerKey = args.payerKey;
this.instructions = args.instructions;
this.recentBlockhash = args.recentBlockhash;
}
static decompile(
message: VersionedMessage,
args?: DecompileArgs,
): TransactionMessage {
const {header, compiledInstructions, recentBlockhash} = message;
const {
numRequiredSignatures,
numReadonlySignedAccounts,
numReadonlyUnsignedAccounts,
} = header;
const numWritableSignedAccounts =
numRequiredSignatures - numReadonlySignedAccounts;
assert(numWritableSignedAccounts > 0, 'Message header is invalid');
const numWritableUnsignedAccounts =
message.staticAccountKeys.length -
numRequiredSignatures -
numReadonlyUnsignedAccounts;
assert(numWritableUnsignedAccounts >= 0, 'Message header is invalid');
const accountKeys = message.getAccountKeys(args);
const payerKey = accountKeys.get(0);
if (payerKey === undefined) {
throw new Error(
'Failed to decompile message because no account keys were found',
);
}
const instructions: TransactionInstruction[] = [];
for (const compiledIx of compiledInstructions) {
const keys: AccountMeta[] = [];
for (const keyIndex of compiledIx.accountKeyIndexes) {
const pubkey = accountKeys.get(keyIndex);
if (pubkey === undefined) {
throw new Error(
`Failed to find key for account key index ${keyIndex}`,
);
}
const isSigner = keyIndex < numRequiredSignatures;
let isWritable;
if (isSigner) {
isWritable = keyIndex < numWritableSignedAccounts;
} else if (keyIndex < accountKeys.staticAccountKeys.length) {
isWritable =
keyIndex - numRequiredSignatures < numWritableUnsignedAccounts;
} else {
isWritable =
keyIndex - accountKeys.staticAccountKeys.length <
// accountKeysFromLookups cannot be undefined because we already found a pubkey for this index above
accountKeys.accountKeysFromLookups!.writable.length;
}
keys.push({
pubkey,
isSigner: keyIndex < header.numRequiredSignatures,
isWritable,
});
}
const programId = accountKeys.get(compiledIx.programIdIndex);
if (programId === undefined) {
throw new Error(
`Failed to find program id for program id index ${compiledIx.programIdIndex}`,
);
}
instructions.push(
new TransactionInstruction({
programId,
data: toBuffer(compiledIx.data),
keys,
}),
);
}
return new TransactionMessage({
payerKey,
instructions,
recentBlockhash,
});
}
compileToLegacyMessage(): Message {
return Message.compile({
payerKey: this.payerKey,
recentBlockhash: this.recentBlockhash,
instructions: this.instructions,
});
}
compileToV0Message(
addressLookupTableAccounts?: AddressLookupTableAccount[],
): MessageV0 {
return MessageV0.compile({
payerKey: this.payerKey,
recentBlockhash: this.recentBlockhash,
instructions: this.instructions,
addressLookupTableAccounts,
});
}
}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClassNameDefinition = void 0;
const DefinitionBase_1 = require("./DefinitionBase");
const DefinitionType_1 = require("./DefinitionType");
class ClassNameDefinition extends DefinitionBase_1.DefinitionBase {
isTypeDefinition = true;
isVariableDefinition = true;
constructor(name, node) {
super(DefinitionType_1.DefinitionType.ClassName, name, node, null);
}
}
exports.ClassNameDefinition = ClassNameDefinition;

View File

@@ -0,0 +1,49 @@
// TODO: this is all copy pasted from Vite - can they expose a module that exports only constants?
const KNOWN_ASSET_TYPES = [
"apng",
"bmp",
"png",
"jpe?g",
"jfif",
"pjpeg",
"pjp",
"gif",
"svg",
"ico",
"webp",
"avif",
"mp4",
"webm",
"ogg",
"mp3",
"wav",
"flac",
"aac",
"woff2?",
"eot",
"ttf",
"otf",
"webmanifest",
"pdf",
"txt"
];
const KNOWN_ASSET_RE = new RegExp(`\\.(${KNOWN_ASSET_TYPES.join("|")})$`);
const CSS_LANGS_RE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
/**
* Prefix for resolved Ids that are not valid browser import specifiers
*/
const VALID_ID_PREFIX = `/@id/`;
/**
* Plugins that use 'virtual modules' (e.g. for helper functions), prefix the
* module ID with `\0`, a convention from the rollup ecosystem.
* This prevents other plugins from trying to process the id (like node resolution),
* and core features like sourcemaps can use this info to differentiate between
* virtual modules and regular files.
* `\0` is not a permitted char in import URLs so we have to replace them during
* import analysis. The id will be decoded back before entering the plugins pipeline.
* These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual
* modules in the browser end up encoded as `/@id/__x00__{id}`
*/
const NULL_BYTE_PLACEHOLDER = `__x00__`;
export { CSS_LANGS_RE, KNOWN_ASSET_RE, KNOWN_ASSET_TYPES, NULL_BYTE_PLACEHOLDER, VALID_ID_PREFIX };

View File

@@ -0,0 +1,95 @@
# Child loggers
Let's assume we want to have `"module":"foo"` added to every log within a
module `foo.js`.
To accomplish this, simply use a child logger:
```js
'use strict'
// imports a pino logger instance of `require('pino')()`
const parentLogger = require('./lib/logger')
const log = parentLogger.child({module: 'foo'})
function doSomething () {
log.info('doSomething invoked')
}
module.exports = {
doSomething
}
```
## Cost of child logging
Child logger creation is fast:
```
benchBunyanCreation*10000: 564.514ms
benchBoleCreation*10000: 283.276ms
benchPinoCreation*10000: 258.745ms
benchPinoExtremeCreation*10000: 150.506ms
```
Logging through a child logger has little performance penalty:
```
benchBunyanChild*10000: 556.275ms
benchBoleChild*10000: 288.124ms
benchPinoChild*10000: 231.695ms
benchPinoExtremeChild*10000: 122.117ms
```
Logging via the child logger of a child logger also has negligible overhead:
```
benchBunyanChildChild*10000: 559.082ms
benchPinoChildChild*10000: 229.264ms
benchPinoExtremeChildChild*10000: 127.753ms
```
## Duplicate keys caveat
Naming conflicts can arise between child loggers and
children of child loggers.
This isn't as bad as it sounds, even if the same keys between
parent and child loggers are used, Pino resolves the conflict in the sanest way.
For example, consider the following:
```js
const pino = require('pino')
pino(pino.destination('./my-log'))
.child({a: 'property'})
.child({a: 'prop'})
.info('howdy')
```
```sh
$ cat my-log
{"pid":95469,"hostname":"MacBook-Pro-3.home","level":30,"msg":"howdy","time":1459534114473,"a":"property","a":"prop"}
```
Notice how there are two keys named `a` in the JSON output. The sub-child's properties
appear after the parent child properties.
At some point, the logs will most likely be processed (for instance with a [transport](transports.md)),
and this generally involves parsing. `JSON.parse` will return an object where the conflicting
namespace holds the final value assigned to it:
```sh
$ cat my-log | node -e "process.stdin.once('data', (line) => console.log(JSON.stringify(JSON.parse(line))))"
{"pid":95469,"hostname":"MacBook-Pro-3.home","level":30,"msg":"howdy","time":"2016-04-01T18:08:34.473Z","a":"prop"}
```
Ultimately the conflict is resolved by taking the last value, which aligns with Bunyan's child logging
behavior.
There may be cases where this edge case becomes problematic if a JSON parser with alternative behavior
is used to process the logs. It's recommended to be conscious of namespace conflicts with child loggers,
in light of an expected log processing approach.
One of Pino's performance tricks is to avoid building objects and stringifying
them, so we're building strings instead. This is why duplicate keys between
parents and children will end up in the log output.

View File

@@ -0,0 +1,608 @@
"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: 'consistent-type-imports',
meta: {
type: 'suggestion',
docs: {
description: 'Enforce consistent usage of type imports',
},
fixable: 'code',
messages: {
avoidImportType: 'Use an `import` instead of an `import type`.',
noImportTypeAnnotations: '`import()` type annotations are forbidden.',
someImportsAreOnlyTypes: 'Imports {{typeImports}} are only used as type.',
typeOverValue: 'All imports in the declaration are only used as types. Use `import type`.',
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
disallowTypeAnnotations: {
type: 'boolean',
description: 'Whether to disallow type imports in type annotations (`import()`).',
},
fixStyle: {
type: 'string',
description: 'The expected type modifier to be added when an import is detected as used only in the type position.',
enum: ['separate-type-imports', 'inline-type-imports'],
},
prefer: {
type: 'string',
description: 'The expected import kind for type-only imports.',
enum: ['type-imports', 'no-type-imports'],
},
},
},
],
},
defaultOptions: [
{
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
prefer: 'type-imports',
},
],
create(context, [option]) {
const prefer = option.prefer ?? 'type-imports';
const disallowTypeAnnotations = option.disallowTypeAnnotations !== false;
const selectors = {};
if (disallowTypeAnnotations) {
selectors.TSImportType = (node) => {
context.report({
node,
messageId: 'noImportTypeAnnotations',
});
};
}
if (prefer === 'no-type-imports') {
return {
...selectors,
'ImportDeclaration[importKind = "type"]'(node) {
context.report({
node,
messageId: 'avoidImportType',
fix(fixer) {
return fixRemoveTypeSpecifierFromImportDeclaration(fixer, node);
},
});
},
'ImportSpecifier[importKind = "type"]'(node) {
context.report({
node,
messageId: 'avoidImportType',
fix(fixer) {
return fixRemoveTypeSpecifierFromImportSpecifier(fixer, node);
},
});
},
};
}
// prefer type imports
const fixStyle = option.fixStyle ?? 'separate-type-imports';
let hasDecoratorMetadata = false;
const sourceImportsMap = {};
const emitDecoratorMetadata = (0, util_1.getParserServices)(context, true).emitDecoratorMetadata ?? false;
const experimentalDecorators = (0, util_1.getParserServices)(context, true).experimentalDecorators ?? false;
if (experimentalDecorators && emitDecoratorMetadata) {
selectors.Decorator = () => {
hasDecoratorMetadata = true;
};
}
return {
...selectors,
ImportDeclaration(node) {
const source = node.source.value;
// sourceImports is the object containing all the specifics for a particular import source, type or value
sourceImportsMap[source] ??= {
reportValueImports: [], // if there is a mismatch where type importKind but value specifiers
source,
typeOnlyNamedImport: null, // if only type imports
valueImport: null, // if only value imports
valueOnlyNamedImport: null, // if only value imports with named specifiers
};
const sourceImports = sourceImportsMap[source];
if (node.importKind === 'type') {
if (!sourceImports.typeOnlyNamedImport &&
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) {
// definitely import type { TypeX }
sourceImports.typeOnlyNamedImport = node;
}
}
else if (!sourceImports.valueOnlyNamedImport &&
node.specifiers.length &&
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) {
sourceImports.valueOnlyNamedImport = node;
sourceImports.valueImport = node;
}
else if (!sourceImports.valueImport &&
node.specifiers.some(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier)) {
sourceImports.valueImport = node;
}
const typeSpecifiers = [];
const inlineTypeSpecifiers = [];
const valueSpecifiers = [];
const unusedSpecifiers = [];
for (const specifier of node.specifiers) {
if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
specifier.importKind === 'type') {
inlineTypeSpecifiers.push(specifier);
continue;
}
const [variable] = context.sourceCode.getDeclaredVariables(specifier);
if (variable.references.length === 0) {
unusedSpecifiers.push(specifier);
}
else {
const onlyHasTypeReferences = variable.references.every(ref => {
/**
* keep origin import kind when export
* export { Type }
* export default Type;
* export = Type;
*/
if ((ref.identifier.parent.type ===
utils_1.AST_NODE_TYPES.ExportSpecifier ||
ref.identifier.parent.type ===
utils_1.AST_NODE_TYPES.ExportDefaultDeclaration ||
ref.identifier.parent.type ===
utils_1.AST_NODE_TYPES.TSExportAssignment) &&
ref.isValueReference &&
ref.isTypeReference) {
return node.importKind === 'type';
}
if (ref.isValueReference) {
let parent = ref.identifier.parent;
let child = ref.identifier;
while (parent) {
switch (parent.type) {
// CASE 1:
// `type T = typeof foo` will create a value reference because "foo" must be a value type
// however this value reference is safe to use with type-only imports
case utils_1.AST_NODE_TYPES.TSTypeQuery:
return true;
case utils_1.AST_NODE_TYPES.TSQualifiedName:
// TSTypeQuery must have a TSESTree.EntityName as its child, so we can filter here and break early
if (parent.left !== child) {
return false;
}
child = parent;
parent = parent.parent;
continue;
// END CASE 1
//////////////
// CASE 2:
// `type T = { [foo]: string }` will create a value reference because "foo" must be a value type
// however this value reference is safe to use with type-only imports.
// Also this is represented as a non-type AST - hence it uses MemberExpression
case utils_1.AST_NODE_TYPES.TSPropertySignature:
return parent.key === child;
case utils_1.AST_NODE_TYPES.MemberExpression:
if (parent.object !== child) {
return false;
}
child = parent;
parent = parent.parent;
continue;
// END CASE 2
default:
return false;
}
}
}
return ref.isTypeReference;
});
if (onlyHasTypeReferences) {
typeSpecifiers.push(specifier);
}
else {
valueSpecifiers.push(specifier);
}
}
}
if (node.importKind === 'value' && typeSpecifiers.length) {
sourceImports.reportValueImports.push({
node,
inlineTypeSpecifiers,
typeSpecifiers,
unusedSpecifiers,
valueSpecifiers,
});
}
},
'Program:exit'() {
if (hasDecoratorMetadata) {
// Experimental decorator metadata is bowl of poop that cannot be
// supported based on pure syntactic analysis.
//
// So we can do one of two things:
// 1) add type-information to the rule in a breaking change and
// prevent users from using it so that we can fully support this
// case.
// 2) make the rule ignore all imports that are used in a file that
// might have decorator metadata.
//
// (1) is has huge impact and prevents the rule from being used by 99%
// of users Frankly - it's a straight-up bad option. So instead we
// choose with option (2) and just avoid reporting on any imports in a
// file with both emitDecoratorMetadata AND decorators
//
// For more context see the discussion in this issue and its linked
// issues:
// https://github.com/typescript-eslint/typescript-eslint/issues/5468
//
//
// NOTE - in TS 5.0 `experimentalDecorators` became the legacy option,
// replaced with un-flagged, stable decorators and thus the type-aware
// emitDecoratorMetadata implementation also became legacy. in TS 5.2
// support for the new, stable decorator metadata proposal was added -
// however this proposal does not include type information
//
//
// PHEW. So TL;DR what does all this mean?
// - if you use experimentalDecorators:true,
// emitDecoratorMetadata:true, and have a decorator in the file -
// the rule will do nothing in the file out of an abundance of
// caution.
// - else the rule will work as normal.
return;
}
for (const sourceImports of Object.values(sourceImportsMap)) {
if (sourceImports.reportValueImports.length === 0) {
// nothing to fix. value specifiers and type specifiers are correctly written
continue;
}
for (const report of sourceImports.reportValueImports) {
if (report.valueSpecifiers.length === 0 &&
report.unusedSpecifiers.length === 0 &&
report.node.importKind !== 'type') {
/**
* checks if import has type assertions
* @example
* ```ts
* import * as type from 'mod' assert \{ type: 'json' \};
* ```
* https://github.com/typescript-eslint/typescript-eslint/issues/7527
*/
if (report.node.attributes.length === 0) {
context.report({
node: report.node,
messageId: 'typeOverValue',
*fix(fixer) {
yield* fixToTypeImportDeclaration(fixer, report, sourceImports);
},
});
}
}
else {
// we have a mixed type/value import or just value imports, so we need to split them out into multiple imports if separate-type-imports is configured
const importNames = report.typeSpecifiers.map(specifier => `"${specifier.local.name}"`);
const message = (() => {
const typeImports = (0, util_1.formatWordList)(importNames);
if (importNames.length === 1) {
return {
messageId: 'someImportsAreOnlyTypes',
data: {
typeImports,
},
};
}
return {
messageId: 'someImportsAreOnlyTypes',
data: {
typeImports,
},
};
})();
context.report({
node: report.node,
...message,
*fix(fixer) {
// take all the typeSpecifiers and put them on a new line
yield* fixToTypeImportDeclaration(fixer, report, sourceImports);
},
});
}
}
}
},
};
function classifySpecifier(node) {
const defaultSpecifier = node.specifiers[0].type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier
? node.specifiers[0]
: null;
const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier) ?? null;
const namedSpecifiers = node.specifiers.filter((specifier) => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier);
return {
defaultSpecifier,
namedSpecifiers,
namespaceSpecifier,
};
}
/**
* Returns information for fixing named specifiers, type or value
*/
function getFixesNamedSpecifiers(fixer, node, subsetNamedSpecifiers, allNamedSpecifiers) {
if (allNamedSpecifiers.length === 0) {
return {
removeTypeNamedSpecifiers: [],
typeNamedSpecifiersText: '',
};
}
const typeNamedSpecifiersTexts = [];
const removeTypeNamedSpecifiers = [];
if (subsetNamedSpecifiers.length === allNamedSpecifiers.length) {
// import Foo, {Type1, Type2} from 'foo'
// import DefType, {Type1, Type2} from 'foo'
const openingBraceToken = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(subsetNamedSpecifiers[0], util_1.isOpeningBraceToken), util_1.NullThrowsReasons.MissingToken('{', node.type));
const commaToken = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(openingBraceToken, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type));
const closingBraceToken = (0, util_1.nullThrows)(context.sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', node.type));
// import DefType, {...} from 'foo'
// ^^^^^^^ remove
removeTypeNamedSpecifiers.push(fixer.removeRange([commaToken.range[0], closingBraceToken.range[1]]));
typeNamedSpecifiersTexts.push(context.sourceCode.text.slice(openingBraceToken.range[1], closingBraceToken.range[0]));
}
else {
const namedSpecifierGroups = [];
let group = [];
for (const namedSpecifier of allNamedSpecifiers) {
if (subsetNamedSpecifiers.includes(namedSpecifier)) {
group.push(namedSpecifier);
}
else if (group.length) {
namedSpecifierGroups.push(group);
group = [];
}
}
if (group.length) {
namedSpecifierGroups.push(group);
}
for (const namedSpecifiers of namedSpecifierGroups) {
const { removeRange, textRange } = getNamedSpecifierRanges(namedSpecifiers, allNamedSpecifiers);
removeTypeNamedSpecifiers.push(fixer.removeRange(removeRange));
typeNamedSpecifiersTexts.push(context.sourceCode.text.slice(...textRange));
}
}
return {
removeTypeNamedSpecifiers,
typeNamedSpecifiersText: typeNamedSpecifiersTexts.join(','),
};
}
/**
* Returns ranges for fixing named specifier.
*/
function getNamedSpecifierRanges(namedSpecifierGroup, allNamedSpecifiers) {
const first = namedSpecifierGroup[0];
const last = namedSpecifierGroup[namedSpecifierGroup.length - 1];
const removeRange = [first.range[0], last.range[1]];
const textRange = [...removeRange];
const before = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(first), util_1.NullThrowsReasons.MissingToken('token', 'first specifier'));
textRange[0] = before.range[1];
if ((0, util_1.isCommaToken)(before)) {
removeRange[0] = before.range[0];
}
else {
removeRange[0] = before.range[1];
}
const isFirst = allNamedSpecifiers[0] === first;
const isLast = allNamedSpecifiers[allNamedSpecifiers.length - 1] === last;
const after = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(last), util_1.NullThrowsReasons.MissingToken('token', 'last specifier'));
textRange[1] = after.range[0];
if ((isFirst || isLast) && (0, util_1.isCommaToken)(after)) {
removeRange[1] = after.range[1];
}
return {
removeRange,
textRange,
};
}
/**
* insert specifiers to named import node.
* e.g.
* import type { Already, Type1, Type2 } from 'foo'
* ^^^^^^^^^^^^^ insert
*/
function fixInsertNamedSpecifiersInNamedSpecifierList(fixer, target, insertText) {
const closingBraceToken = (0, util_1.nullThrows)(context.sourceCode.getFirstTokenBetween((0, util_1.nullThrows)(context.sourceCode.getFirstToken(target), util_1.NullThrowsReasons.MissingToken('token before', 'import')), target.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', target.type));
const before = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(closingBraceToken), util_1.NullThrowsReasons.MissingToken('token before', 'closing brace'));
if (!(0, util_1.isCommaToken)(before) && !(0, util_1.isOpeningBraceToken)(before)) {
insertText = `,${insertText}`;
}
return fixer.insertTextBefore(closingBraceToken, insertText);
}
/**
* insert type keyword to named import node.
* e.g.
* import ADefault, { Already, type Type1, type Type2 } from 'foo'
* ^^^^ insert
*/
function* fixInsertTypeKeywordInNamedSpecifierList(fixer, typeSpecifiers) {
for (const spec of typeSpecifiers) {
const insertText = context.sourceCode.text.slice(...spec.range);
yield fixer.replaceTextRange(spec.range, `type ${insertText}`);
}
}
function* fixInlineTypeImportDeclaration(fixer, report, sourceImports) {
const { node } = report;
// For a value import, will only add an inline type to named specifiers
const { namedSpecifiers } = classifySpecifier(node);
const typeNamedSpecifiers = namedSpecifiers.filter(specifier => report.typeSpecifiers.includes(specifier));
if (sourceImports.valueImport) {
// add import named type specifiers to its value import
// import ValueA, { type A }
// ^^^^ insert
const { namedSpecifiers: valueImportNamedSpecifiers } = classifySpecifier(sourceImports.valueImport);
if (sourceImports.valueOnlyNamedImport ||
valueImportNamedSpecifiers.length) {
yield* fixInsertTypeKeywordInNamedSpecifierList(fixer, typeNamedSpecifiers);
}
}
}
function* fixToTypeImportDeclaration(fixer, report, sourceImports) {
const { node } = report;
const { defaultSpecifier, namedSpecifiers, namespaceSpecifier } = classifySpecifier(node);
if (namespaceSpecifier && !defaultSpecifier) {
// import * as types from 'foo'
// checks for presence of import assertions
if (node.attributes.length === 0) {
yield* fixInsertTypeSpecifierForImportDeclaration(fixer, node, false);
}
return;
}
if (defaultSpecifier) {
if (report.typeSpecifiers.includes(defaultSpecifier) &&
namedSpecifiers.length === 0 &&
!namespaceSpecifier) {
// import Type from 'foo'
yield* fixInsertTypeSpecifierForImportDeclaration(fixer, node, true);
return;
}
if (fixStyle === 'inline-type-imports' &&
!report.typeSpecifiers.includes(defaultSpecifier) &&
namedSpecifiers.length > 0 &&
!namespaceSpecifier) {
// if there is a default specifier but it isn't a type specifier, then just add the inline type modifier to the named specifiers
// import AValue, {BValue, Type1, Type2} from 'foo'
yield* fixInlineTypeImportDeclaration(fixer, report, sourceImports);
return;
}
}
else if (!namespaceSpecifier) {
if (fixStyle === 'inline-type-imports' &&
namedSpecifiers.some(specifier => report.typeSpecifiers.includes(specifier))) {
// import {AValue, Type1, Type2} from 'foo'
yield* fixInlineTypeImportDeclaration(fixer, report, sourceImports);
return;
}
if (namedSpecifiers.every(specifier => report.typeSpecifiers.includes(specifier))) {
// import {Type1, Type2} from 'foo'
yield* fixInsertTypeSpecifierForImportDeclaration(fixer, node, false);
return;
}
}
const typeNamedSpecifiers = namedSpecifiers.filter(specifier => report.typeSpecifiers.includes(specifier));
const fixesNamedSpecifiers = getFixesNamedSpecifiers(fixer, node, typeNamedSpecifiers, namedSpecifiers);
const afterFixes = [];
if (typeNamedSpecifiers.length) {
if (sourceImports.typeOnlyNamedImport) {
const insertTypeNamedSpecifiers = fixInsertNamedSpecifiersInNamedSpecifierList(fixer, sourceImports.typeOnlyNamedImport, fixesNamedSpecifiers.typeNamedSpecifiersText);
if (sourceImports.typeOnlyNamedImport.range[1] <= node.range[0]) {
yield insertTypeNamedSpecifiers;
}
else {
afterFixes.push(insertTypeNamedSpecifiers);
}
}
else {
// The import is both default and named. Insert named on new line because can't mix default type import and named type imports
// eslint-disable-next-line no-lonely-if
if (fixStyle === 'inline-type-imports') {
yield fixer.insertTextBefore(node, `import {${typeNamedSpecifiers
.map(spec => {
const insertText = context.sourceCode.text.slice(...spec.range);
return `type ${insertText}`;
})
.join(', ')}} from ${context.sourceCode.getText(node.source)};\n`);
}
else {
yield fixer.insertTextBefore(node, `import type {${fixesNamedSpecifiers.typeNamedSpecifiersText}} from ${context.sourceCode.getText(node.source)};\n`);
}
}
}
const fixesRemoveTypeNamespaceSpecifier = [];
if (namespaceSpecifier &&
report.typeSpecifiers.includes(namespaceSpecifier)) {
// import Foo, * as Type from 'foo'
// import DefType, * as Type from 'foo'
// import DefType, * as Type from 'foo'
const commaToken = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(namespaceSpecifier, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type));
// import Def, * as Ns from 'foo'
// ^^^^^^^^^ remove
fixesRemoveTypeNamespaceSpecifier.push(fixer.removeRange([commaToken.range[0], namespaceSpecifier.range[1]]));
// import type * as Ns from 'foo'
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ insert
yield fixer.insertTextBefore(node, `import type ${context.sourceCode.getText(namespaceSpecifier)} from ${context.sourceCode.getText(node.source)};\n`);
}
if (defaultSpecifier &&
report.typeSpecifiers.includes(defaultSpecifier)) {
if (report.typeSpecifiers.length === node.specifiers.length) {
const importToken = (0, util_1.nullThrows)(context.sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type));
// import type Type from 'foo'
// ^^^^ insert
yield fixer.insertTextAfter(importToken, ' type');
}
else {
const commaToken = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(defaultSpecifier, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', defaultSpecifier.type));
// import Type , {...} from 'foo'
// ^^^^^ pick
const defaultText = context.sourceCode.text
.slice(defaultSpecifier.range[0], commaToken.range[0])
.trim();
yield fixer.insertTextBefore(node, `import type ${defaultText} from ${context.sourceCode.getText(node.source)};\n`);
const afterToken = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(commaToken, {
includeComments: true,
}), util_1.NullThrowsReasons.MissingToken('any token', node.type));
// import Type , {...} from 'foo'
// ^^^^^^^ remove
yield fixer.removeRange([
defaultSpecifier.range[0],
afterToken.range[0],
]);
}
}
yield* fixesNamedSpecifiers.removeTypeNamedSpecifiers;
yield* fixesRemoveTypeNamespaceSpecifier;
yield* afterFixes;
}
function* fixInsertTypeSpecifierForImportDeclaration(fixer, node, isDefaultImport) {
// import type Foo from 'foo'
// ^^^^^ insert
const importToken = (0, util_1.nullThrows)(context.sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type));
yield fixer.insertTextAfter(importToken, ' type');
if (isDefaultImport) {
// Has default import
const openingBraceToken = context.sourceCode.getFirstTokenBetween(importToken, node.source, util_1.isOpeningBraceToken);
if (openingBraceToken) {
// Only braces. e.g. import Foo, {} from 'foo'
const commaToken = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(openingBraceToken, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type));
const closingBraceToken = (0, util_1.nullThrows)(context.sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', node.type));
// import type Foo, {} from 'foo'
// ^^ remove
yield fixer.removeRange([
commaToken.range[0],
closingBraceToken.range[1],
]);
const specifiersText = context.sourceCode.text.slice(commaToken.range[1], closingBraceToken.range[1]);
if (node.specifiers.length > 1) {
yield fixer.insertTextAfter(node, `\nimport type${specifiersText} from ${context.sourceCode.getText(node.source)};`);
}
}
}
// make sure we don't do anything like `import type {type T} from 'foo';`
for (const specifier of node.specifiers) {
if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
specifier.importKind === 'type') {
yield* fixRemoveTypeSpecifierFromImportSpecifier(fixer, specifier);
}
}
}
function* fixRemoveTypeSpecifierFromImportDeclaration(fixer, node) {
// import type Foo from 'foo'
// ^^^^ remove
const importToken = (0, util_1.nullThrows)(context.sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type));
const typeToken = (0, util_1.nullThrows)(context.sourceCode.getFirstTokenBetween(importToken, node.specifiers[0]?.local ?? node.source, util_1.isTypeKeyword), util_1.NullThrowsReasons.MissingToken('type', node.type));
const afterToken = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(typeToken, { includeComments: true }), util_1.NullThrowsReasons.MissingToken('any token', node.type));
yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]);
}
function* fixRemoveTypeSpecifierFromImportSpecifier(fixer, node) {
// import { type Foo } from 'foo'
// ^^^^ remove
const typeToken = (0, util_1.nullThrows)(context.sourceCode.getFirstToken(node, util_1.isTypeKeyword), util_1.NullThrowsReasons.MissingToken('type', node.type));
const afterToken = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(typeToken, { includeComments: true }), util_1.NullThrowsReasons.MissingToken('any token', node.type));
yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]);
}
},
});

View File

@@ -0,0 +1,2 @@
declare const _default: "00000000-0000-0000-0000-000000000000";
export default _default;

View File

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

View File

@@ -0,0 +1,227 @@
/**
* @fileoverview Rule to flag updates of imported bindings.
* @author Toru Nagashima <https://github.com/mysticatea>
*/
"use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const { findVariable } = require("@eslint-community/eslint-utils");
const astUtils = require("./utils/ast-utils");
const WellKnownMutationFunctions = {
Object: /^(?:assign|definePropert(?:y|ies)|freeze|setPrototypeOf)$/u,
Reflect: /^(?:(?:define|delete)Property|set(?:PrototypeOf)?)$/u,
};
/**
* Check if a given node is LHS of an assignment node.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is LHS.
*/
function isAssignmentLeft(node) {
const { parent } = node;
return (
(parent.type === "AssignmentExpression" && parent.left === node) ||
// Destructuring assignments
parent.type === "ArrayPattern" ||
(parent.type === "Property" &&
parent.value === node &&
parent.parent.type === "ObjectPattern") ||
parent.type === "RestElement" ||
(parent.type === "AssignmentPattern" && parent.left === node)
);
}
/**
* Check if a given node is the operand of mutation unary operator.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is the operand of mutation unary operator.
*/
function isOperandOfMutationUnaryOperator(node) {
const argumentNode =
node.parent.type === "ChainExpression" ? node.parent : node;
const { parent } = argumentNode;
return (
(parent.type === "UpdateExpression" &&
parent.argument === argumentNode) ||
(parent.type === "UnaryExpression" &&
parent.operator === "delete" &&
parent.argument === argumentNode)
);
}
/**
* Check if a given node is the iteration variable of `for-in`/`for-of` syntax.
* @param {ASTNode} node The node to check.
* @returns {boolean} `true` if the node is the iteration variable.
*/
function isIterationVariable(node) {
const { parent } = node;
return (
(parent.type === "ForInStatement" && parent.left === node) ||
(parent.type === "ForOfStatement" && parent.left === node)
);
}
/**
* Check if a given node is at the first argument of a well-known mutation function.
* - `Object.assign`
* - `Object.defineProperty`
* - `Object.defineProperties`
* - `Object.freeze`
* - `Object.setPrototypeOf`
* - `Reflect.defineProperty`
* - `Reflect.deleteProperty`
* - `Reflect.set`
* - `Reflect.setPrototypeOf`
* @param {ASTNode} node The node to check.
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
* @returns {boolean} `true` if the node is at the first argument of a well-known mutation function.
*/
function isArgumentOfWellKnownMutationFunction(node, scope) {
const { parent } = node;
if (parent.type !== "CallExpression" || parent.arguments[0] !== node) {
return false;
}
const callee = astUtils.skipChainExpression(parent.callee);
if (
!astUtils.isSpecificMemberAccess(
callee,
"Object",
WellKnownMutationFunctions.Object,
) &&
!astUtils.isSpecificMemberAccess(
callee,
"Reflect",
WellKnownMutationFunctions.Reflect,
)
) {
return false;
}
const variable = findVariable(scope, callee.object);
return variable !== null && variable.scope.type === "global";
}
/**
* Check if the identifier node is placed at to update members.
* @param {ASTNode} id The Identifier node to check.
* @param {Scope} scope A `escope.Scope` object to find variable (whichever).
* @returns {boolean} `true` if the member of `id` was updated.
*/
function isMemberWrite(id, scope) {
const { parent } = id;
return (
(parent.type === "MemberExpression" &&
parent.object === id &&
(isAssignmentLeft(parent) ||
isOperandOfMutationUnaryOperator(parent) ||
isIterationVariable(parent))) ||
isArgumentOfWellKnownMutationFunction(id, scope)
);
}
/**
* Get the mutation node.
* @param {ASTNode} id The Identifier node to get.
* @returns {ASTNode} The mutation node.
*/
function getWriteNode(id) {
let node = id.parent;
while (
node &&
node.type !== "AssignmentExpression" &&
node.type !== "UpdateExpression" &&
node.type !== "UnaryExpression" &&
node.type !== "CallExpression" &&
node.type !== "ForInStatement" &&
node.type !== "ForOfStatement"
) {
node = node.parent;
}
return node || id;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
type: "problem",
docs: {
description: "Disallow assigning to imported bindings",
recommended: true,
url: "https://eslint.org/docs/latest/rules/no-import-assign",
},
schema: [],
messages: {
readonly: "'{{name}}' is read-only.",
readonlyMember: "The members of '{{name}}' are read-only.",
},
},
create(context) {
const sourceCode = context.sourceCode;
return {
ImportDeclaration(node) {
const scope = sourceCode.getScope(node);
for (const variable of sourceCode.getDeclaredVariables(node)) {
const shouldCheckMembers = variable.defs.some(
d => d.node.type === "ImportNamespaceSpecifier",
);
let prevIdNode = null;
for (const reference of variable.references) {
const idNode = reference.identifier;
/*
* AssignmentPattern (e.g. `[a = 0] = b`) makes two write
* references for the same identifier. This should skip
* the one of the two in order to prevent redundant reports.
*/
if (idNode === prevIdNode) {
continue;
}
prevIdNode = idNode;
if (reference.isWrite()) {
context.report({
node: getWriteNode(idNode),
messageId: "readonly",
data: { name: idNode.name },
});
} else if (
shouldCheckMembers &&
isMemberWrite(idNode, scope)
) {
context.report({
node: getWriteNode(idNode),
messageId: "readonlyMember",
data: { name: idNode.name },
});
}
}
}
},
};
},
};

View File

@@ -0,0 +1 @@
{"version":3,"file":"tokenFlags.js","sourceRoot":"","sources":["../../src/enums/tokenFlags.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,MAAM,CAAC,IAAI,UAAe,CAAC;AAC3B,CAAC,UAAU,UAAU;IACjB,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;IAC5C,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,GAAG,oBAAoB,CAAC;IACxE,UAAU,CAAC,UAAU,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,GAAG,uBAAuB,CAAC;IAC9E,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC;IAC5D,UAAU,CAAC,UAAU,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,GAAG,uBAAuB,CAAC;IAC9E,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,GAAG,YAAY,CAAC;IACzD,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IAC/C,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,GAAG,cAAc,CAAC;IAC7D,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,GAAG,GAAG,CAAC,GAAG,iBAAiB,CAAC;IACpE,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,GAAG,CAAC,GAAG,gBAAgB,CAAC;IAClE,UAAU,CAAC,UAAU,CAAC,mBAAmB,CAAC,GAAG,GAAG,CAAC,GAAG,mBAAmB,CAAC;IACxE,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,GAAG,eAAe,CAAC;IACjE,UAAU,CAAC,UAAU,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAC,GAAG,uBAAuB,CAAC;IACjF,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;IACzD,UAAU,CAAC,UAAU,CAAC,qBAAqB,CAAC,GAAG,IAAI,CAAC,GAAG,qBAAqB,CAAC;IAC7E,UAAU,CAAC,UAAU,CAAC,0BAA0B,CAAC,GAAG,KAAK,CAAC,GAAG,0BAA0B,CAAC;IACxF,UAAU,CAAC,UAAU,CAAC,gCAAgC,CAAC,GAAG,KAAK,CAAC,GAAG,gCAAgC,CAAC;IACpG,UAAU,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,GAAG,aAAa,CAAC;IAC9D,UAAU,CAAC,UAAU,CAAC,8BAA8B,CAAC,GAAG,MAAM,CAAC,GAAG,8BAA8B,CAAC;IACjG,UAAU,CAAC,UAAU,CAAC,6BAA6B,CAAC,GAAG,MAAM,CAAC,GAAG,6BAA6B,CAAC;IAC/F,UAAU,CAAC,UAAU,CAAC,wBAAwB,CAAC,GAAG,GAAG,CAAC,GAAG,wBAAwB,CAAC;IAClF,UAAU,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,GAAG,CAAC,GAAG,eAAe,CAAC;IAChE,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,GAAG,KAAK,CAAC,GAAG,oBAAoB,CAAC;IAC5E,UAAU,CAAC,UAAU,CAAC,qBAAqB,CAAC,GAAG,KAAK,CAAC,GAAG,qBAAqB,CAAC;IAC9E,UAAU,CAAC,UAAU,CAAC,0BAA0B,CAAC,GAAG,IAAI,CAAC,GAAG,0BAA0B,CAAC;IACvF,UAAU,CAAC,UAAU,CAAC,+BAA+B,CAAC,GAAG,CAAC,CAAC,GAAG,+BAA+B,CAAC;IAC9F,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC,GAAG,WAAW,CAAC;AAC9D,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,235 @@
/**
* @fileoverview Rule to disallow empty functions.
* @author Toru Nagashima
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const ALLOW_OPTIONS = Object.freeze([
"functions",
"arrowFunctions",
"generatorFunctions",
"methods",
"generatorMethods",
"getters",
"setters",
"constructors",
"asyncFunctions",
"asyncMethods",
"privateConstructors",
"protectedConstructors",
"decoratedFunctions",
"overrideMethods",
]);
/**
* Gets the kind of a given function node.
* @param {ASTNode} node A function node to get. This is one of
* an ArrowFunctionExpression, a FunctionDeclaration, or a
* FunctionExpression.
* @returns {string} The kind of the function. This is one of "functions",
* "arrowFunctions", "generatorFunctions", "asyncFunctions", "methods",
* "generatorMethods", "asyncMethods", "getters", "setters", and
* "constructors".
*/
function getKind(node) {
const parent = node.parent;
let kind;
if (node.type === "ArrowFunctionExpression") {
return "arrowFunctions";
}
// Detects main kind.
if (parent.type === "Property") {
if (parent.kind === "get") {
return "getters";
}
if (parent.kind === "set") {
return "setters";
}
kind = parent.method ? "methods" : "functions";
} else if (parent.type === "MethodDefinition") {
if (parent.kind === "get") {
return "getters";
}
if (parent.kind === "set") {
return "setters";
}
if (parent.kind === "constructor") {
return "constructors";
}
kind = "methods";
} else {
kind = "functions";
}
// Detects prefix.
let prefix;
if (node.generator) {
prefix = "generator";
} else if (node.async) {
prefix = "async";
} else {
return kind;
}
return prefix + kind[0].toUpperCase() + kind.slice(1);
}
/**
* Checks if a constructor function has parameter properties.
* @param {ASTNode} node The function node to examine.
* @returns {boolean} True if the constructor has parameter properties, false otherwise.
*/
function isParameterPropertiesConstructor(node) {
return node.params.some(param => param.type === "TSParameterProperty");
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
module.exports = {
meta: {
hasSuggestions: true,
type: "suggestion",
defaultOptions: [{ allow: [] }],
docs: {
description: "Disallow empty functions",
dialects: ["JavaScript", "TypeScript"],
recommended: false,
url: "https://eslint.org/docs/latest/rules/no-empty-function",
},
schema: [
{
type: "object",
properties: {
allow: {
type: "array",
items: { enum: ALLOW_OPTIONS },
uniqueItems: true,
},
},
additionalProperties: false,
},
],
messages: {
unexpected: "Unexpected empty {{name}}.",
suggestComment: "Add comment inside empty {{name}}.",
},
},
create(context) {
const [{ allow }] = context.options;
const sourceCode = context.sourceCode;
/**
* Checks if the given function node is allowed to be empty.
* @param {ASTNode} node The function node to check.
* @returns {boolean} True if the function is allowed to be empty, false otherwise.
*/
function isAllowedEmptyFunction(node) {
const kind = getKind(node);
if (allow.includes(kind)) {
return true;
}
if (kind === "constructors") {
if (
(node.parent.accessibility === "private" &&
allow.includes("privateConstructors")) ||
(node.parent.accessibility === "protected" &&
allow.includes("protectedConstructors")) ||
isParameterPropertiesConstructor(node)
) {
return true;
}
}
if (/(?:g|s)etters|methods$/iu.test(kind)) {
if (
(node.parent.decorators?.length &&
allow.includes("decoratedFunctions")) ||
(node.parent.override && allow.includes("overrideMethods"))
) {
return true;
}
}
return false;
}
/**
* Reports a given function node if the node matches the following patterns.
*
* - Not allowed by options.
* - The body is empty.
* - The body doesn't have any comments.
* @param {ASTNode} node A function node to report. This is one of
* an ArrowFunctionExpression, a FunctionDeclaration, or a
* FunctionExpression.
* @returns {void}
*/
function reportIfEmpty(node) {
const name = astUtils.getFunctionNameWithKind(node);
const innerComments = sourceCode.getTokens(node.body, {
includeComments: true,
filter: astUtils.isCommentToken,
});
if (
!isAllowedEmptyFunction(node) &&
node.body.type === "BlockStatement" &&
node.body.body.length === 0 &&
innerComments.length === 0
) {
context.report({
node,
loc: node.body.loc,
messageId: "unexpected",
data: { name },
suggest: [
{
messageId: "suggestComment",
data: { name },
fix(fixer) {
const range = [
node.body.range[0] + 1,
node.body.range[1] - 1,
];
return fixer.replaceTextRange(
range,
" /* empty */ ",
);
},
},
],
});
}
}
return {
ArrowFunctionExpression: reportIfEmpty,
FunctionDeclaration: reportIfEmpty,
FunctionExpression: reportIfEmpty,
};
},
};

View File

@@ -0,0 +1,8 @@
export { g as getBenchFn, a as getBenchOptions } from './chunks/benchmark.CX_oY03V.js';
export { createTaskCollector, getCurrentSuite, getCurrentTest, getFn, getHooks, setFn, setHooks } from '@vitest/runner';
export { createChainable } from '@vitest/runner/utils';
import '@vitest/utils/helpers';
import './chunks/utils.BX5Fg8C4.js';
import '@vitest/utils/timers';
console.warn("Importing from \"vitest/suite\" is deprecated since Vitest 4.1. Please use static methods of \"TestRunner\" from the \"vitest\" entry point instead: e.g., `TestRunner.getCurrentTest()`.");

View File

@@ -0,0 +1,716 @@
// Generated by LiveScript 1.6.0
var each, map, compact, filter, reject, remove, partition, find, head, first, tail, last, initial, empty, reverse, unique, uniqueBy, fold, foldl, fold1, foldl1, foldr, foldr1, unfoldr, concat, concatMap, flatten, difference, intersection, union, countBy, groupBy, andList, orList, any, all, sort, sortWith, sortBy, sum, product, mean, average, maximum, minimum, maximumBy, minimumBy, scan, scanl, scan1, scanl1, scanr, scanr1, slice, take, drop, splitAt, takeWhile, dropWhile, span, breakList, zip, zipWith, zipAll, zipAllWith, at, elemIndex, elemIndices, findIndex, findIndices, toString$ = {}.toString;
each = curry$(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
f(x);
}
return xs;
});
map = curry$(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
results$.push(f(x));
}
return results$;
});
compact = function(xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (x) {
results$.push(x);
}
}
return results$;
};
filter = curry$(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
results$.push(x);
}
}
return results$;
});
reject = curry$(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!f(x)) {
results$.push(x);
}
}
return results$;
});
remove = curry$(function(el, xs){
var i, x$;
i = elemIndex(el, xs);
x$ = xs.slice();
if (i != null) {
x$.splice(i, 1);
}
return x$;
});
partition = curry$(function(f, xs){
var passed, failed, i$, len$, x;
passed = [];
failed = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
(f(x) ? passed : failed).push(x);
}
return [passed, failed];
});
find = curry$(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
return x;
}
}
});
head = first = function(xs){
return xs[0];
};
tail = function(xs){
if (!xs.length) {
return;
}
return xs.slice(1);
};
last = function(xs){
return xs[xs.length - 1];
};
initial = function(xs){
if (!xs.length) {
return;
}
return xs.slice(0, -1);
};
empty = function(xs){
return !xs.length;
};
reverse = function(xs){
return xs.concat().reverse();
};
unique = function(xs){
var result, i$, len$, x;
result = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!in$(x, result)) {
result.push(x);
}
}
return result;
};
uniqueBy = curry$(function(f, xs){
var seen, i$, len$, x, val, results$ = [];
seen = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
val = f(x);
if (in$(val, seen)) {
continue;
}
seen.push(val);
results$.push(x);
}
return results$;
});
fold = foldl = curry$(function(f, memo, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
memo = f(memo, x);
}
return memo;
});
fold1 = foldl1 = curry$(function(f, xs){
return fold(f, xs[0], xs.slice(1));
});
foldr = curry$(function(f, memo, xs){
var i$, x;
for (i$ = xs.length - 1; i$ >= 0; --i$) {
x = xs[i$];
memo = f(x, memo);
}
return memo;
});
foldr1 = curry$(function(f, xs){
return foldr(f, xs[xs.length - 1], xs.slice(0, -1));
});
unfoldr = curry$(function(f, b){
var result, x, that;
result = [];
x = b;
while ((that = f(x)) != null) {
result.push(that[0]);
x = that[1];
}
return result;
});
concat = function(xss){
return [].concat.apply([], xss);
};
concatMap = curry$(function(f, xs){
var x;
return [].concat.apply([], (function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
results$.push(f(x));
}
return results$;
}()));
});
flatten = function(xs){
var x;
return [].concat.apply([], (function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
if (toString$.call(x).slice(8, -1) === 'Array') {
results$.push(flatten(x));
} else {
results$.push(x);
}
}
return results$;
}()));
};
difference = function(xs){
var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
yss = res$;
results = [];
outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
ys = yss[j$];
if (in$(x, ys)) {
continue outer;
}
}
results.push(x);
}
return results;
};
intersection = function(xs){
var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
yss = res$;
results = [];
outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
ys = yss[j$];
if (!in$(x, ys)) {
continue outer;
}
}
results.push(x);
}
return results;
};
union = function(){
var xss, res$, i$, to$, results, len$, xs, j$, len1$, x;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
results = [];
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
for (j$ = 0, len1$ = xs.length; j$ < len1$; ++j$) {
x = xs[j$];
if (!in$(x, results)) {
results.push(x);
}
}
}
return results;
};
countBy = curry$(function(f, xs){
var results, i$, len$, x, key;
results = {};
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
key = f(x);
if (key in results) {
results[key] += 1;
} else {
results[key] = 1;
}
}
return results;
});
groupBy = curry$(function(f, xs){
var results, i$, len$, x, key;
results = {};
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
key = f(x);
if (key in results) {
results[key].push(x);
} else {
results[key] = [x];
}
}
return results;
});
andList = function(xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!x) {
return false;
}
}
return true;
};
orList = function(xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (x) {
return true;
}
}
return false;
};
any = curry$(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
return true;
}
}
return false;
});
all = curry$(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!f(x)) {
return false;
}
}
return true;
});
sort = function(xs){
return xs.concat().sort(function(x, y){
if (x > y) {
return 1;
} else if (x < y) {
return -1;
} else {
return 0;
}
});
};
sortWith = curry$(function(f, xs){
return xs.concat().sort(f);
});
sortBy = curry$(function(f, xs){
return xs.concat().sort(function(x, y){
if (f(x) > f(y)) {
return 1;
} else if (f(x) < f(y)) {
return -1;
} else {
return 0;
}
});
});
sum = function(xs){
var result, i$, len$, x;
result = 0;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
result += x;
}
return result;
};
product = function(xs){
var result, i$, len$, x;
result = 1;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
result *= x;
}
return result;
};
mean = average = function(xs){
var sum, i$, len$, x;
sum = 0;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
sum += x;
}
return sum / xs.length;
};
maximum = function(xs){
var max, i$, ref$, len$, x;
max = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (x > max) {
max = x;
}
}
return max;
};
minimum = function(xs){
var min, i$, ref$, len$, x;
min = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (x < min) {
min = x;
}
}
return min;
};
maximumBy = curry$(function(f, xs){
var max, i$, ref$, len$, x;
max = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (f(x) > f(max)) {
max = x;
}
}
return max;
});
minimumBy = curry$(function(f, xs){
var min, i$, ref$, len$, x;
min = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (f(x) < f(min)) {
min = x;
}
}
return min;
});
scan = scanl = curry$(function(f, memo, xs){
var last, x;
last = memo;
return [memo].concat((function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
results$.push(last = f(last, x));
}
return results$;
}()));
});
scan1 = scanl1 = curry$(function(f, xs){
if (!xs.length) {
return;
}
return scan(f, xs[0], xs.slice(1));
});
scanr = curry$(function(f, memo, xs){
xs = xs.concat().reverse();
return scan(f, memo, xs).reverse();
});
scanr1 = curry$(function(f, xs){
if (!xs.length) {
return;
}
xs = xs.concat().reverse();
return scan(f, xs[0], xs.slice(1)).reverse();
});
slice = curry$(function(x, y, xs){
return xs.slice(x, y);
});
take = curry$(function(n, xs){
if (n <= 0) {
return xs.slice(0, 0);
} else {
return xs.slice(0, n);
}
});
drop = curry$(function(n, xs){
if (n <= 0) {
return xs;
} else {
return xs.slice(n);
}
});
splitAt = curry$(function(n, xs){
return [take(n, xs), drop(n, xs)];
});
takeWhile = curry$(function(p, xs){
var len, i;
len = xs.length;
if (!len) {
return xs;
}
i = 0;
while (i < len && p(xs[i])) {
i += 1;
}
return xs.slice(0, i);
});
dropWhile = curry$(function(p, xs){
var len, i;
len = xs.length;
if (!len) {
return xs;
}
i = 0;
while (i < len && p(xs[i])) {
i += 1;
}
return xs.slice(i);
});
span = curry$(function(p, xs){
return [takeWhile(p, xs), dropWhile(p, xs)];
});
breakList = curry$(function(p, xs){
return span(compose$(p, not$), xs);
});
zip = curry$(function(xs, ys){
var result, len, i$, len$, i, x;
result = [];
len = ys.length;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (i === len) {
break;
}
result.push([x, ys[i]]);
}
return result;
});
zipWith = curry$(function(f, xs, ys){
var result, len, i$, len$, i, x;
result = [];
len = ys.length;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (i === len) {
break;
}
result.push(f(x, ys[i]));
}
return result;
});
zipAll = function(){
var xss, res$, i$, to$, minLength, len$, xs, ref$, i, lresult$, j$, results$ = [];
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
minLength = undefined;
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
minLength <= (ref$ = xs.length) || (minLength = ref$);
}
for (i$ = 0; i$ < minLength; ++i$) {
i = i$;
lresult$ = [];
for (j$ = 0, len$ = xss.length; j$ < len$; ++j$) {
xs = xss[j$];
lresult$.push(xs[i]);
}
results$.push(lresult$);
}
return results$;
};
zipAllWith = function(f){
var xss, res$, i$, to$, minLength, len$, xs, ref$, i, results$ = [];
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
minLength = undefined;
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
minLength <= (ref$ = xs.length) || (minLength = ref$);
}
for (i$ = 0; i$ < minLength; ++i$) {
i = i$;
results$.push(f.apply(null, (fn$())));
}
return results$;
function fn$(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xss).length; i$ < len$; ++i$) {
xs = ref$[i$];
results$.push(xs[i]);
}
return results$;
}
};
at = curry$(function(n, xs){
if (n < 0) {
return xs[xs.length + n];
} else {
return xs[n];
}
});
elemIndex = curry$(function(el, xs){
var i$, len$, i, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (x === el) {
return i;
}
}
});
elemIndices = curry$(function(el, xs){
var i$, len$, i, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (x === el) {
results$.push(i);
}
}
return results$;
});
findIndex = curry$(function(f, xs){
var i$, len$, i, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (f(x)) {
return i;
}
}
});
findIndices = curry$(function(f, xs){
var i$, len$, i, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (f(x)) {
results$.push(i);
}
}
return results$;
});
module.exports = {
each: each,
map: map,
filter: filter,
compact: compact,
reject: reject,
remove: remove,
partition: partition,
find: find,
head: head,
first: first,
tail: tail,
last: last,
initial: initial,
empty: empty,
reverse: reverse,
difference: difference,
intersection: intersection,
union: union,
countBy: countBy,
groupBy: groupBy,
fold: fold,
fold1: fold1,
foldl: foldl,
foldl1: foldl1,
foldr: foldr,
foldr1: foldr1,
unfoldr: unfoldr,
andList: andList,
orList: orList,
any: any,
all: all,
unique: unique,
uniqueBy: uniqueBy,
sort: sort,
sortWith: sortWith,
sortBy: sortBy,
sum: sum,
product: product,
mean: mean,
average: average,
concat: concat,
concatMap: concatMap,
flatten: flatten,
maximum: maximum,
minimum: minimum,
maximumBy: maximumBy,
minimumBy: minimumBy,
scan: scan,
scan1: scan1,
scanl: scanl,
scanl1: scanl1,
scanr: scanr,
scanr1: scanr1,
slice: slice,
take: take,
drop: drop,
splitAt: splitAt,
takeWhile: takeWhile,
dropWhile: dropWhile,
span: span,
breakList: breakList,
zip: zip,
zipWith: zipWith,
zipAll: zipAll,
zipAllWith: zipAllWith,
at: at,
elemIndex: elemIndex,
elemIndices: elemIndices,
findIndex: findIndex,
findIndices: findIndices
};
function curry$(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
function in$(x, xs){
var i = -1, l = xs.length >>> 0;
while (++i < l) if (x === xs[i]) return true;
return false;
}
function compose$() {
var functions = arguments;
return function() {
var i, result;
result = functions[0].apply(this, arguments);
for (i = 1; i < functions.length; ++i) {
result = functions[i](result);
}
return result;
};
}
function not$(x){ return !x; }

View File

@@ -0,0 +1,38 @@
{
"name": "@types/pg",
"version": "8.21.0",
"description": "TypeScript definitions for pg",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/pg",
"license": "MIT",
"contributors": [
{
"name": "Phips Peter",
"githubUsername": "pspeter3",
"url": "https://github.com/pspeter3"
}
],
"main": "",
"types": "index.d.ts",
"exports": {
".": {
"import": "./index.d.mts",
"require": "./index.d.ts"
},
"./lib/*": "./lib/*.d.ts",
"./package.json": "./package.json"
},
"repository": {
"type": "git",
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/pg"
},
"scripts": {},
"dependencies": {
"@types/node": "*",
"pg-protocol": "*",
"pg-types": "^2.2.0"
},
"peerDependencies": {},
"typesPublisherContentHash": "339a3113d2fba11606b673acadf3f47d6be100bc03adff52b16ee80e5c989444",
"typeScriptVersion": "5.6"
}

View File

@@ -0,0 +1,6 @@
export { Modifiers } from './enums';
export type { PredefinedFormatsString } from './enums';
export { parseOptions } from './parse-options';
export { SCHEMA } from './schema';
export { selectorTypeToMessageString } from './shared';
export type { Context, Selector, ValidatorFunction } from './types';

View File

@@ -0,0 +1,16 @@
import commander from './index.js';
// wrapper to provide named exports for ESM.
export const {
program,
createCommand,
createArgument,
createOption,
CommanderError,
InvalidArgumentError,
InvalidOptionArgumentError, // deprecated old name
Command,
Argument,
Option,
Help,
} = commander;