Product
Socket Now Supports uv.lock Files
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
@fullstackio/cq
Advanced tools
A tool to extract code snippets using selectors (instead of line numbers)
Supports JavaScript ES5, ES6, JSX, and TypeScript
$ npm install --global @fullstackio/cq
$ cq <query> <file>
# or
$ cat file | cq <query>
Say we have a file examples/basics.js
with the following code:
// examples/basics.js
const bye = function() {
return 'bye';
}
bye(); // -> 'bye'
let Farm = () => 'cow';
class Barn {
constructor(height, width) {
this.height = height;
this.width = width;
}
calcArea() {
return this.height * this.width;
}
}
Get the bye()
function:
$ cq '.bye' examples/basics.js
const bye = function() {
return 'bye';
}
Get the calcArea()
function on the Barn
class:
$ cq '.Barn .calcArea' examples/basics.js
calcArea() {
return this.height * this.width;
}
Get the bye()
function plus the line after:
// `context(identifier, linesBefore, linesAfter)`
$ cq 'context(.bye,0,1)' examples/basics.js
const bye = function() {
return 'bye';
}
bye(); // -> 'bye'
Get the range of constructor
through calcArea
, inclusive, of the Barn
class
$ cq '.Barn .constructor-.calcArea' examples/basics.js
constructor(height, width) {
this.height = height;
this.width = width;
}
calcArea() {
return this.height * this.width;
}
If you pass --json
you'll get the results in JSON, which can be useful for further processing:
$ cq --json 'context(.bye,0,1)' examples/basics.js
{
"code": "const bye = function() {\n return 'bye';\n}\nbye(); // -> 'bye'",
"start": 598,
"end": 659,
"start_line": 25,
"end_line": 28
}
cq
works with TypeScript as well. Say we had the following TypeScript File:
// AuthService.ts
import {Injectable, provide} from '@angular/core';
@Injectable()
export class AuthService {
getUser(): any {
return localStorage.getItem('username');
}
isLoggedIn(): boolean {
return this.getUser() !== null;
}
}
export var AUTH_PROVIDERS: Array<any> = [
provide(AuthService, {useClass: AuthService})
];
Get the AUTH_PROVIDERS
export:
$ cq '.AUTH_PROVIDERS' examples/AuthService.ts
export var AUTH_PROVIDERS: Array<any> = [
provide(AuthService, {useClass: AuthService})
];
Get the isLoggedIn()
function through AUTH_PROVIDERS
$ cq '(.AuthService .isLoggedIn)-.AUTH_PROVIDERS' examples/AuthService.ts
isLoggedIn(): boolean {
return this.getUser() !== null;
}
}
export var AUTH_PROVIDERS: Array<any> = [
provide(AuthService, {useClass: AuthService})
];
cq
can search for strings as well as identifiers. Say we have the following test:
import chai from 'chai';
const assert = chai.assert;
describe('My First Test', () => {
it('basic assert', () => {
assert.equal(1, 1);
});
});
describe('My Second Test', () => {
it('basic assert', () => {
// this is the second one
assert.equal(2, 2);
});
});
We can get the first test:
$ cq "'My First Test'" examples/mocha.test.js
describe('My First Test', () => {
it('basic assert', () => {
assert.equal(1, 1);
});
});
Or get the it
block in the second test:
$ cq "'My Second Test' 'basic assert'" examples/mocha.test.js
it('basic assert', () => {
// this is the second one
assert.equal(2, 2);
});
Sometimes we want to pull the comments before a selection. cq
supports this using the comments()
operator:
// comments.js
function hello() {
return 'hi';
}
/*
* @function bye
*/
function bye() {
return 'see ya';
}
Get the bye()
function with comments:
$ cq 'comments(.bye)' comments.js
/*
* @function bye
*/
const bye = function() {
return 'bye';
}
See many more examples in the
/examples
directory
When writing blog posts, tutorials, and books about programming there's a tension between code that gets copied and pasted into the text and runnable code on disk.
If you copy and paste your code into the copy, then you're prone to typos, missing steps. When things change, you have to update all of the copypasta and eyeball it to make sure you didn't miss anything. Mistakes are really easy to make because you can't really test code that's in your manuscript without it's context.
A better solution is to keep your code (or steps of your code) as runnable examples on disk. You can then load the code into your manuscript with some pre-processing.
The problem with the code-on-disk approach is how to designate the ranges of code you wish to import. Line numbers are the most obvious approach, but if you add or remove a line of code, then you have to adjust all line numbers accordingly.
cq
is a tool that lets you specify selectors to extract portions of code. Rather than using brittle line numbers, instead cq
lets you query your code. It uses babylon
to understand the semantics of your code and will extract the appropriate lines.
Examples:
.Simple
.render
A dot .
preceding JavaScript identifier characters represents an identifier.
In this code:
const Simple = React.createClass({
render() {
return (
<div>
{this.renderName()}
</div>
)
}
});
The query .Simple
would find the whole const Simple = ...
variable declaration.
Searches for identifiers traverse the whole tree, relative to the parent, and return the first match. This means that you do not have to start at the root. In this case you could query for .render
and would receive the render()
function. That said, creating more specific queries can help in the case where you want to disambiguate.
Examples:
.Simple .render
.foo .bar .baz
The space in a query selection expression designates a parent for the next identifier. For instance, the query .Simple .render
will first look for the identifier Simple
and then find the render
function that is a child of Simple
.
The space indicates to search for the next identifier anywhere within the parent. That is, it does not require that the child identifier be a direct child the parent.
In this way the space is analogous to the space in a CSS selector. E.g. search for any child that matches.
cq
does not yet support the>
notation (which would require the identifier to be a direct child), but we may in the future.
You can write child selection in parenthesis ()
if there is ambiguity. E.g.: (.foo .bar)
.
Examples:
.constructor-.calcArea
.Barn .constructor-.calcArea
1-(.AuthService .login)
.foo-EOF
Given:
class Barn {
constructor(height, width) {
this.height = height;
this.width = width;
}
calcArea() {
return this.height * this.width;
}
}
A pair of selections (e.g. identifiers) joined by a dash -
form a range. A range will emit the code from the beginning of the match of the first identifier to the end of the match of the last.
You can use a parent identifier to limit the scope of the search of the range as in the query: .Barn .constructor-.calcArea
If you'd like to specify a line number, you can use a number (instead of an identifier) in a range. For example the query: 30-35
will give lines 30 through 35, inclusive.
If you want to specify a child selector at the end of a range, use parenthesis as in this query: 1-(.AuthService .login)
. The previous query will return the lines from line 1 to the end of the login()
function on AuthService
.
You can use the special line number EOF
to select until the end-of-file.
Examples:
context(.bye,1,1)
upto(.bye)
comments(.bye)
Given:
// here is the bye function
const bye = function() {
return 'bye';
}
bye(); // -> 'bye'
Operators allow you to change the result of the inner selection.
context()
The context()
operation allows you to take line numbers before and after the selection. The signature is context(selection, numLinesBefore, numLinesAfter)
.
upto()
The upto()
operation will return the code up-to, but not including, the selection. A convenient (but potentially confusing) default is that the upto()
operation trims whitespace. This is normally what you want, but you have to be careful when using upto()
and context()
together (because upto()
may trim lines).
comments()
The comments()
operation will return the selection plus the leading comments before the selection.
Examples:
'My Test'
'My Test' 'my should'
2-'My Test'
You can use a single-quoted string as a selection and cq
will search for that string. When a string is found, cq
will emit the statement / block associated with that string.
For instance, given:
describe('My First Test', () => {
it('basic assert', () => {
assert.equal(1, 1);
});
});
You could search for the strings 'My First Test'
or 'basic assert'
and receive the appropriate selection.
var cq = require('@fullstackio/cq').default;
var results = cq(codeString, query);
console.log(results.code);
import
s, and require
sThe query API may change (see Future). Any breaking API changes (query or otherwise) will result in a major version bump.
Please feel free to submit pull requests!
Originally written by Nate Murray.
This repo was written and is maintained by the Fullstack React team. If you're looking to learn React, there's no faster way than by spending a few hours with the Fullstack React book.
FAQs
query code with selectors
The npm package @fullstackio/cq receives a total of 35 weekly downloads. As such, @fullstackio/cq popularity was classified as not popular.
We found that @fullstackio/cq demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers 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.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.
Research
Security News
Socket researchers have discovered multiple malicious npm packages targeting Solana private keys, abusing Gmail to exfiltrate the data and drain Solana wallets.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.