Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
@phenomnomnominal/tsquery
Advanced tools
The @phenomnomnominal/tsquery package is a powerful tool for querying TypeScript AST (Abstract Syntax Tree) using a CSS-like selector system. It allows developers to easily find nodes within TypeScript source code, making it useful for tasks such as code analysis, refactoring, and more.
Querying TypeScript AST
This feature allows you to query TypeScript AST nodes by using CSS-like selectors. In the provided code, `tsquery.ast` generates an AST from the source code, and `tsquery` function is used to find all identifiers named 'foo'.
import { tsquery } from '@phenomnomnominal/tsquery';
const ast = tsquery.ast(sourceCode);
const nodes = tsquery(ast, 'Identifier[name="foo"]');
Counting specific nodes
This feature is useful for analyzing the code to count specific types of statements or nodes. Here, the code counts how many 'IfStatement' nodes are in the provided source code.
import { tsquery } from '@phenomnomnominal/tsquery';
const ast = tsquery.ast(sourceCode);
const count = tsquery(ast, 'IfStatement').length;
typescript-eslint is a plugin that allows for linting TypeScript code with ESLint. It uses an AST to analyze the code, similar to tsquery, but is more focused on linting and enforcing coding standards rather than general querying.
ts-morph provides an easier API to work with the TypeScript compiler's AST. It offers functionalities similar to tsquery but with additional features like code manipulation and emitting, making it more versatile for tasks that involve modifying the codebase.
TSQuery is a port of the ESQuery API for TypeScript! TSQuery allows you to query a TypeScript AST for patterns of syntax using a CSS style selector system.
ESQuery demo - note that the demo requires JavaScript code, not TypeScript TSQuery demo by Uri Shaked
npm install @phenomnomnominal/tsquery --save-dev
Say we want to select all instances of an identifier with name "Animal", e.g. the identifier in the class
declaration, and the identifier in the extends
declaration.
We would do something like the following:
import { ast, query } from '@phenomnomnominal/tsquery';
const typescript = `
class Animal {
constructor(public name: string) { }
move(distanceInMeters: number = 0) {
console.log(\`\${this.name} moved \${distanceInMeters}m.\`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
`;
const ast = ast(typescript);
const nodes = query(ast, 'Identifier[name="Animal"]');
console.log(nodes.length); // 2
The following selectors are supported:
ForStatement
(see common node types)*
[attr]
[attr="foo"]
or [attr=123]
[attr=/foo.*/]
[attr!="foo"]
, [attr>2]
, [attr<3]
, [attr>=2]
, or [attr<=3]
[attr.level2="foo"]
FunctionDeclaration > Identifier.id
:first-child
or :last-child
:nth-child(2)
:nth-last-child(1)
ancestor descendant
parent > child
node ~ sibling
node + adjacent
:not(ForStatement)
:matches([attr] > :first-child, :last-child)
IfStatement:has([name="foo"])
:statement
, :expression
, :declaration
, :function
, or :pattern
Identifier
- any identifier (name of a function, class, variable, etc)IfStatement
, ForStatement
, WhileStatement
, DoStatement
- control flowFunctionDeclaration
, ClassDeclaration
, ArrowFunction
- declarationsVariableStatement
- var, const, let.ImportDeclaration
- any import
statementStringLiteral
- any stringTrueKeyword
, FalseKeyword
, NullKeyword
, AnyKeyword
- various keywordsCallExpression
- function callNumericLiteral
- any numeric constantNoSubstitutionTemplateLiteral
, TemplateExpression
- template strings and expressionsast
:Parse a string of code into an Abstract Syntax Tree which can then be queried with TSQuery Selectors.
import { ast } from '@phenomnomnominal/tsquery';
const sourceFile = ast('const x = 1;');
includes
:Check for Nodes
within a given string
of code or AST Node
matching a Selector
.
import { includes } from '@phenomnomnominal/tsquery';
const hasIdentifier = includes('const x = 1;', 'Identifier');
map
:Transform AST Nodes
within a given Node
matching a Selector
. Can be used to do Node
-based replacement or removal of parts of the input AST.
import { factory } from 'typescript';
import { map } from '@phenomnomnominal/tsquery';
const tree = ast('const x = 1;')
const updatedTree = map(tree, 'Identifier', () => factory.createIdentifier('y'));
match
:Find AST Nodes
within a given AST Node
matching a Selector
.
import { ast, match } from '@phenomnomnominal/tsquery';
const tree = ast('const x = 1;')
const [xNode] = match(tree, 'Identifier');
parse
:Parse a string
into an ESQuery Selector
.
import { parse } from '@phenomnomnominal/tsquery';
const selector = parse(':matches([attr] > :first-child, :last-child)');
print
:Print a given Node
or SourceFile
to a string, using the default TypeScript printer.
import { print } from '@phenomnomnominal/tsquery';
import { factory } from 'typescript';
// create synthetic node:
const node = factory.createArrowFunction(
// ...
);
const code = print(node);
project
:Get all the SourceFiles
included in a the TypeScript project described by a given config file.
import { project } from '@phenomnomnominal/tsquery';
const files = project('./tsconfig.json');
files
:Get all the file paths included ina the TypeScript project described by a given config file.
import { files } from '@phenomnomnominal/tsquery';
const filePaths = files('./tsconfig.json');
match
:Find AST Nodes
within a given string
of code or AST Node
matching a Selector
.
import {query } from '@phenomnomnominal/tsquery';
const [xNode] = query('const x = 1;', 'Identifier');
replace
:Transform AST Nodes
within a given Node
matching a Selector
. Can be used to do string-based replacement or removal of parts of the input AST. The updated code will be printed with the TypeScript Printer
, so you may need to run your own formatter on any output code.
import { replace } from '@phenomnomnominal/tsquery';
const updatedCode = replace('const x = 1;', 'Identifier', () => 'y'));
FAQs
Query TypeScript ASTs with the esquery API!
The npm package @phenomnomnominal/tsquery receives a total of 1,572,225 weekly downloads. As such, @phenomnomnominal/tsquery popularity was classified as popular.
We found that @phenomnomnominal/tsquery demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.