Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ storybook-static
# rollup.js default build output
dist/
dist_esm/
dist_cli/

# Gatsby files
.cache/
Expand Down
38 changes: 23 additions & 15 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
lib/
src/
test/
docs/
.vscode/
.sfdx/
debug/
coverage/
tsconfig.json
.prettierrc
.travis.yml
.rpt2_cache
.env
.git
.prettierrc
.release-it.json
ISSUE_TEMPLATE
CONTRIBUTING.md
.rpt2_cache
.sfdx/
.travis.yml
.vscode/
cli/
coverage/
debug/
docs/
lib/
src/
tasks/
test/
AUTHORS.md
CHANGELOG.md
webpack.config.js
CONTRIBUTING.md
CONTRIBUTORS.md
ISSUE_TEMPLATE
tsconfig-cli.json
tsconfig-esm.json
tsconfig.json
webpack-cli.config.js
webpack-min.config.js
webpack-regular.config.js
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 4.3

September 19, 2021

- Added cli support, check out the readme for usage details

## 4.2.2

August 1, 2021
Expand Down
151 changes: 151 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Want to try it out? [Check out the demo](https://paustint.github.io/soql-parser-
**Node**: version 11 or higher, or a polyfill for [Array.flat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)
**Browser**: Tested in all modern browsers, may not work with older browsers.

The **commander** dependency is only required for the cli, the other two dependencies **chevrotain** and **lodash.get** are bundled with the non-cli code.

## Quick Start

```javascript
Expand Down Expand Up @@ -402,6 +404,155 @@ WHERE Name LIKE 'a%'
OR Name LIKE 'c%'
```

## CLI

If you install globally, you can use the cli

### Available Commands

- `soql-parser-js --help`
- `soql-parser-js parse --help`
- `soql-parser-js compose --help`
- `soql-parser-js format --help`

### Examples

#### Parse

`soql-parser-js parse "SELECT Id FROM Account"`

```bash
{"fields":[{"type":"Field","field":"Id"}],"sObject":"Account"}
```

#### Compose

`soql-parser-js compose "{\"fields\":[{\"type\":\"Field\",\"field\":\"Id\"}],\"sObject\":\"Account\"}"`

```bash
SELECT Id FROM Account
```

`soql-parser-js compose "{\"fields\":[{\"type\":\"Field\",\"field\":\"Id\"}],\"sObject\":\"Account\"}" --json` or -j

```json
{ "query": "SELECT Id FROM Account" }
```

#### Format

`soql-parser-js format "SELECT Name, COUNT(Id) FROM Account GROUP BY Name HAVING COUNT(Id) > 1"`

```bash
SELECT Name, COUNT(Id)
FROM Account
GROUP BY Name
HAVING COUNT(Id) > 1
```

`soql-parser-js format "SELECT Name, COUNT(Id) FROM Account GROUP BY Name HAVING COUNT(Id) > 1 -j`

```json
{ "query": "SELECT Name, COUNT(Id)\nFROM Account\nGROUP BY Name\nHAVING COUNT(Id) > 1" }
```

#### Is Valid

`soql-parser-js valid "SELECT Id FROM Account"`

```bash
true
```

`soql-parser-js valid "SELECT Id invalid FROM Account"`

ℹ️ this returns an exit code of 1

```bash
false
```

`soql-parser-js valid "SELECT Id FROM Account -j`

```json
{ "isValid": true }
```

`soql-parser-js valid "SELECT Id invalid invalid FROM Account -j`

ℹ️ this returns an exit code of 0

```json
{ "isValid": false }
```

### List of options

`soql-parser-js --help`

```bash
Usage: soql-parser-js [options] [command]

Options:
-h, --help output usage information

Commands:
parse [options] <query>
compose [options] <query>
format [options] <query>
valid <query>
```

`soql-parser-js parse --help`

```bash
Usage: parse [options] <query>

Options:
-a, --allow-apex allow apex bind variables
-i, --ignore-errors ignore parse errors, return as much of query as possible
-h, --help output usage information
```

`soql-parser-js compose --help`

```bash
Usage: compose [options] <query>

Options:
-f, --format format output
-i --indent <chars> number of tab characters to indent (default: 1)
-m --line-length <chars> max number of characters per lins (default: 60)
-s --subquery-parens-new-line subquery parens on own line
-k --keywords-new-line new line after keywords
-j, --json output as JSON
-h, --help output usage information
```

`soql-parser-js format --help`

```bash
Usage: format [options] <query>

Options:
-i --indent <chars> number of tab characters to indent (default: 1)
-m --line-length <chars> max number of characters per lins (default: 60)
-s --subquery-parens-new-line subquery parens on own line
-k --keywords-new-line new line after keywords
-j, --json output as JSON
-h, --help output usage information
```

`soql-parser-js valid --help`

```bash
Usage: valid [options] <query>

Options:
-j, --json output as JSON
-h, --help output usage information
```

## Data Models

### Query
Expand Down
3 changes: 3 additions & 0 deletions bin/soql-parser-js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node

require('../dist_cli/cli');
122 changes: 122 additions & 0 deletions cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { parseQuery, composeQuery, isQueryValid, formatQuery, FormatOptions } from '../src';
import { Command } from 'commander';

interface ParseCommandActions {
allowApex: boolean;
ignoreErrors: boolean;
}

interface ComposeCommandOptions {
format: boolean;
indent: number;
lineLength: number;
subqueryParensNewLine: boolean;
keywordsNewLine: boolean;
json: boolean;
}

type FormatCommandOptions = Omit<ComposeCommandOptions, 'format'>;
type IsValidCommandOptions = Pick<ComposeCommandOptions, 'json'>;

const program = new Command();

program
.command('parse <query>')
.option('-a, --allow-apex', 'allow apex bind variables')
.option('-i, --ignore-errors', 'ignore parse errors, return as much of query as possible')
.action((query: string, options: ParseCommandActions) => {
console.log(
JSON.stringify(
parseQuery(query, {
allowApexBindVariables: options.allowApex,
ignoreParseErrors: options.ignoreErrors,
}),
),
);
});

program
.command('compose <query>')
.option('-f, --format', 'format output')
.option('-i --indent <chars>', 'number of tab characters to indent', 1)
.option('-m --line-length <chars>', 'max number of characters per lins', 60)
.option('-s --subquery-parens-new-line', 'subquery parens on own line')
.option('-k --keywords-new-line', 'new line after keywords')
.option('-j, --json', 'output as JSON')
.action((query: string, options: ComposeCommandOptions) => {
const formatOptions: FormatOptions = {};
if (options.indent) {
formatOptions.numIndent = options.indent;
}

if (options.lineLength) {
formatOptions.fieldMaxLineLength = options.lineLength;
}

if (options.subqueryParensNewLine) {
formatOptions.fieldSubqueryParensOnOwnLine = options.subqueryParensNewLine;
}

if (options.keywordsNewLine) {
formatOptions.newLineAfterKeywords = options.keywordsNewLine;
}

let output = composeQuery(JSON.parse(query), { format: options.format, formatOptions });
if (options.json) {
console.log(JSON.stringify({ query: output }));
} else {
console.log(output);
}
});

program
.command('format <query>')
.option('-i --indent <chars>', 'number of tab characters to indent', 1)
.option('-m --line-length <chars>', 'max number of characters per lins', 60)
.option('-s --subquery-parens-new-line', 'subquery parens on own line')
.option('-k --keywords-new-line', 'new line after keywords')
.option('-j, --json', 'output as JSON')
.action((query: string, options: FormatCommandOptions) => {
const formatOptions: FormatOptions = {};
if (options.indent) {
formatOptions.numIndent = options.indent;
}

if (options.lineLength) {
formatOptions.fieldMaxLineLength = options.lineLength;
}

if (options.subqueryParensNewLine) {
formatOptions.fieldSubqueryParensOnOwnLine = options.subqueryParensNewLine;
}

if (options.keywordsNewLine) {
formatOptions.newLineAfterKeywords = options.keywordsNewLine;
}

const output = formatQuery(query, formatOptions);
if (options.json) {
console.log(JSON.stringify({ query: output }));
} else {
console.log(output);
}
});

program
.command('valid <query>')
.option('-j, --json', 'output as JSON')
.action((query: string, options: IsValidCommandOptions) => {
const isValid = isQueryValid(query);
if (options.json) {
console.log(JSON.stringify({ isValid }));
} else {
if (isValid) {
console.log('true');
} else {
console.error('false');
process.exit(1);
}
}
});

program.parse(process.argv);
14 changes: 8 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading