soql-parser-js
Advanced tools
Comparing version 1.1.1 to 1.2.0
# Changelog | ||
## 1.2.0 | ||
- Changed compose methods to public to allow external access (#65) | ||
- Fixed lodash security vulnerability | ||
- Updated README to reflect new changes and other minor changes | ||
## 1.1.1 | ||
@@ -4,0 +10,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { Query } from './models/SoqlQuery.model'; | ||
import { FieldType, GroupByClause, HavingClause, OrderByClause, Query, WhereClause, WithDataCategoryClause, FieldTypeOf, Subquery } from './models/SoqlQuery.model'; | ||
import { Formatter, FormatOptions } from './SoqlFormatter'; | ||
@@ -7,2 +7,3 @@ export interface SoqlComposeConfig { | ||
formatOptions?: FormatOptions; | ||
autoCompose: boolean; | ||
} | ||
@@ -19,2 +20,4 @@ /** | ||
* Composes a parsed query back to a SOQL query | ||
* The parsing methods are public in case there is a need to parse just a part of a query, | ||
* but the common case is to call the "start()" method | ||
* @param soql | ||
@@ -41,2 +44,6 @@ * @param [config] | ||
start(): void; | ||
/** | ||
* If logging is enabled, print the query to the console | ||
* @param soql | ||
*/ | ||
private log(soql); | ||
@@ -50,3 +57,3 @@ /** | ||
*/ | ||
private parseQuery(query); | ||
parseQuery(query: Query | Subquery): string; | ||
/** | ||
@@ -58,3 +65,3 @@ * Parses fields | ||
*/ | ||
private parseFields(fields); | ||
parseFields(fields: FieldType[]): string[]; | ||
/** | ||
@@ -66,3 +73,3 @@ * Parses type of Field | ||
*/ | ||
private parseTypeOfField(typeOfField); | ||
parseTypeOfField(typeOfField: FieldTypeOf): string; | ||
/** | ||
@@ -81,3 +88,3 @@ * Parses fn from a WHERE clause | ||
*/ | ||
private parseWhereClause(where); | ||
parseWhereClause(where: WhereClause): string; | ||
/** | ||
@@ -89,3 +96,3 @@ * Parses group by clause | ||
*/ | ||
private parseGroupByClause(groupBy); | ||
parseGroupByClause(groupBy: GroupByClause): string; | ||
/** | ||
@@ -97,3 +104,3 @@ * Parses having clause | ||
*/ | ||
private parseHavingClause(having); | ||
parseHavingClause(having: HavingClause): string; | ||
/** | ||
@@ -105,3 +112,3 @@ * Parses order by | ||
*/ | ||
private parseOrderBy(orderBy); | ||
parseOrderBy(orderBy: OrderByClause | OrderByClause[]): string; | ||
/** | ||
@@ -113,3 +120,3 @@ * Parses with data category | ||
*/ | ||
private parseWithDataCategory(withDataCategory); | ||
parseWithDataCategory(withDataCategory: WithDataCategoryClause): string; | ||
} |
{ | ||
"name": "soql-parser-js", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "Salesforce.com SOQL parser.", | ||
@@ -27,3 +27,5 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"@types/lodash": "^4.14.136", | ||
"antlr4ts": "0.4.1-alpha.0", | ||
"lodash": "^4.17.14", | ||
"minimist": "^1.2.0" | ||
@@ -30,0 +32,0 @@ }, |
191
README.md
@@ -9,17 +9,19 @@ # SOQL Parser JS | ||
:sunny: This library allows parsing Salesforce SOQL queries using JavaScript or Typescript. Works in the browser and node. :sunny: | ||
SOQL Parser JS provides the following capabilities: | ||
1. Parse a SOQL query into a usable data structure. | ||
2. Turn a parsed query data structure back into well a SOQL query with various format options. | ||
3. Check if a SOQL query is syntactically valid (**note**: some cases may be structurally sound but not allowed by SFDC). | ||
2. Turn a parsed data structure back into a well formed SOQL query with various format options. | ||
3. Check if a SOQL query is syntactically valid (**note**: some cases may be structurally valid but not allowed by Salesforce, e.x. invalid field name). | ||
This library is written in Typescript and all type definitions are included with the library for your benefit if you choose to use Typescript or use VSCode's automatic type checking. | ||
_Warning_: antlr4 is dependency for this library and is a rather large library (~600 KB) and is required for the parser to function, use in the browser with care. | ||
:warning: antlr4 is dependency for this library and is a rather large library (~600 KB) and is required for the parser to function. Consider using dynamic imports to achieve lazy loading. | ||
## Examples | ||
For an example of the parser, check out the [example application](https://paustint.github.io/soql-parser-js/). | ||
Want to try it out? [Check out the demo](https://paustint.github.io/soql-parser-js/). | ||
Have a look through the unit tests for many more examples. | ||
Look through the [unit tests](./test/TestCases.ts) for additional examples. | ||
@@ -30,3 +32,3 @@ # Usage | ||
Parsing a SOQL query can be completed by calling `parseQuery(soqlQueryString, options)` and a `Query` data structure will be returned; | ||
Parsing a SOQL query can be completed by calling `parseQuery(soqlQueryString, options)`. A `Query` data structure will be returned; | ||
@@ -36,10 +38,14 @@ #### Typescript / ES6 | ||
```typescript | ||
import { parseQuery } from 'soql-parser-js'; // TS / ES6 imports | ||
import { parseQuery } from 'soql-parser-js'; | ||
// var soqlParserJs = require('soql-parser-js'); // node's require format - usage: soqlParserJs.parseQuery() | ||
const soql = | ||
'SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId'; | ||
const soql = ` | ||
SELECT UserId, COUNT(Id) | ||
FROM LoginHistory | ||
WHERE LoginTime > 2010-09-20T22:16:30.000Z | ||
AND LoginTime < 2010-09-21T22:16:30.000Z | ||
GROUP BY UserId'; | ||
`; | ||
const soqlQuery = parseQuery(soql); | ||
// const soqlQuery = soqlParserJs.parseQuery(soql); // using require() | ||
@@ -49,2 +55,43 @@ console.log(JSON.stringify(soqlQuery, null, 2)); | ||
**Results** | ||
```json | ||
{ | ||
"fields": [ | ||
{ | ||
"type": "Field", | ||
"field": "UserId" | ||
}, | ||
{ | ||
"type": "FieldFunctionExpression", | ||
"rawValue": "COUNT(Id)", | ||
"fn": "COUNT", | ||
"isAggregateFn": true, | ||
"parameters": ["Id"] | ||
} | ||
], | ||
"sObject": "LoginHistory", | ||
"where": { | ||
"left": { | ||
"field": "LoginTime", | ||
"operator": ">", | ||
"value": "2010-09-20T22:16:30.000Z", | ||
"literalType": "DATETIME" | ||
}, | ||
"operator": "AND", | ||
"right": { | ||
"left": { | ||
"field": "LoginTime", | ||
"operator": "<", | ||
"value": "2010-09-21T22:16:30.000Z", | ||
"literalType": "DATETIME" | ||
} | ||
} | ||
}, | ||
"groupBy": { | ||
"field": "UserId" | ||
} | ||
} | ||
``` | ||
#### Options | ||
@@ -61,9 +108,9 @@ | ||
Composing a query will turn a Query object back to a SOQL query. The exact same data structure returned from `parseQuery()` can be used, | ||
but there are many use-cases where you may need to build your own data structure to compose a query. | ||
Composing a query will turn a Query object back to a SOQL query string. The exact same data structure returned from `parseQuery()` can be used, | ||
but depending on your use-case, you may need to build your own data structure to compose a query. | ||
These examples show building your own Query object with the minimum required fields. | ||
**Note:** For some operators, they may be converted to upper case (e.x. NOT, AND) | ||
:page_facing_up: **Note:** Some operators may be converted to upper case (e.x. NOT, AND) | ||
**Note:** There are a number of fields populated on the Query object when `parseQuery()` is called that are not required to compose a query. Look at the examples below and the comments in the data model for more information. | ||
:page_facing_up: **Note:** There are a number of fields populated on the Query object when `parseQuery()` is called that are not required to compose a query. Look at the examples below and the comments in the data model for more information. | ||
@@ -92,3 +139,3 @@ **The base query object is shaped like this:** | ||
This is the query that will be composed | ||
This is the query that will be composed programmatically | ||
@@ -148,3 +195,3 @@ ```sql | ||
// literalType is optional, but if set to STRING and our value is not already wrapped in "'", they will be added | ||
// All other literalType values are ignored in composing a query | ||
// All other literalType values are ignored when composing a query | ||
literalType: 'STRING', | ||
@@ -162,5 +209,6 @@ }, | ||
In the above examples, we made use of `getComposedField(input: string | ComposeFieldInput)` to help easily compose the fields. The input expects a string or one of the following shapes of data below. An error will be thrown if the data passed in is not one of the following shapes: | ||
and will return a `FieldType` object. | ||
In the example above, we made use of `getComposedField(input: string | ComposeFieldInput)` to compose the fields. The input expects a string or one of the following data structures listed below. An error will be thrown if the data passed in is not one of the following shapes. | ||
This returns a `FieldType` object. | ||
```typescript | ||
@@ -194,5 +242,49 @@ export interface ComposeField { | ||
### Composing a partial query | ||
If you need to compose just a part of a query instead of the entire query, you can create an instance of the Compose class directly. | ||
For example, if you just need the "WHERE" clause from a query as a string, you can do the following: | ||
```typescript | ||
import { Compose, getComposedField, parseQuery } from 'soql-parser-js'; | ||
const soql = `SELECT Id FROM Account WHERE Name = 'Foo'`; | ||
const parsedQuery = parseQuery(soql); | ||
// Results of Parsed Query: | ||
// const parsedQuery = { | ||
// fields: [ | ||
// { | ||
// type: 'Field', | ||
// field: 'Id', | ||
// }, | ||
// ], | ||
// sObject: 'Account', | ||
// where: { | ||
// left: { | ||
// field: 'Name', | ||
// operator: '=', | ||
// value: "'Foo'", | ||
// literalType: 'STRING', | ||
// }, | ||
// }, | ||
// }; | ||
// Create a new instance of the compose class and set the autoCompose to false to avoid composing the entire query | ||
const composer = new Compose(parsedQuery, { autoCompose: false }); | ||
const whereClause = composer.parseWhereClause(parsedQuery.where); | ||
console.log(whereClause); | ||
// Name = 'Foo' | ||
} | ||
``` | ||
## Checking if a Query is Valid | ||
This will parse the AST tree to confirm the syntax is valid, but will not parse the tree into a data structure. | ||
This will parse a Query to confirm valid syntax, but will not parse into the Query data structure, which will have a small performance gain. | ||
This method is faster than parsing the full query. | ||
@@ -216,21 +308,9 @@ | ||
console.log('isValid', isValid); | ||
console.log(isValid); | ||
``` | ||
#### Node | ||
```javascript | ||
var soqlParserJs = require('soql-parser-js'); | ||
const soql = | ||
'SELECT UserId, COUNT(Id) from LoginHistory WHERE LoginTime > 2010-09-20T22:16:30.000Z AND LoginTime < 2010-09-21T22:16:30.000Z GROUP BY UserId'; | ||
const isValid = isQueryValid(soql); | ||
console.log('isValid', isValid); | ||
``` | ||
## Format Query | ||
This function is provided as a convenience and just calls parse and compose under the hood. | ||
This function is provided as a convenience and just calls parse and compose. | ||
[Check out the demo](https://paustint.github.io/soql-parser-js/) to see the outcome of the various format options. | ||
@@ -330,2 +410,3 @@ ```typescript | ||
formatOptions?: FormatOptions; | ||
autoCompose: boolean; // default=true | ||
} | ||
@@ -347,14 +428,15 @@ | ||
1. `getComposedField(input: string | ComposeFieldInput)` | ||
1. Convenience method to construct fields in the correct data format. See example usage in the Compose example. | ||
1. `isSubquery(query: Query | Subquery)` | ||
1. Returns true if the data passed in is a subquery | ||
1. `getFlattenedFields(query: Query)` | ||
1. This provides a list of fields that are stringified and flattened in order to access data from a returned API call from Salesforce. Refer to `tests/publicUtils.spec.ts` for usage examples. | ||
1. Convenience method to construct fields in the correct data format. See example usage in the Compose example. | ||
2. `isSubquery(query: Query | Subquery)` | ||
1. Returns true if the data passed in is a subquery | ||
3. `getFlattenedFields(query: Query)` | ||
1. Flatten a Salesforce record based on the parsed SOQL Query. this is useful if you have relationships in your query and want to show the results in a table, using `.` dot notation for the relationship fields. | ||
2. Refer to `tests/publicUtils.spec.ts` for usage examples. | ||
## Data Models | ||
These are all available for import in your typescript projects | ||
### Query | ||
These are all available for import in your typescript projects | ||
```typescript | ||
@@ -513,2 +595,29 @@ export type LogicalOperator = 'AND' | 'OR'; | ||
### Compose Class | ||
You only need to interact with the compose class if you want to compose part of a SOQL query | ||
```typescript | ||
// Instance Properties | ||
logging: boolean; // default to false | ||
format: boolean; // default to false | ||
query: string; | ||
formatter: Formatter; | ||
// Instance Methods: | ||
constructor(private soql: Query, config?: Partial<SoqlComposeConfig>) | ||
start(): void | ||
// Pass in part of the parsed query to get the string representation for a given segment of a query | ||
parseQuery(query: Query | Subquery): string | ||
parseFields(fields: FieldType[]): string[] | ||
parseTypeOfField(typeOfField: FieldTypeOf): string | ||
parseFn(fn: FunctionExp): string | ||
parseWhereClause(where: WhereClause): string | ||
parseGroupByClause(groupBy: GroupByClause): string | ||
parseHavingClause(having: HavingClause): string | ||
parseOrderBy(orderBy: OrderByClause | OrderByClause[]): string | ||
parseWithDataCategory(withDataCategory: WithDataCategoryClause): string | ||
``` | ||
### Utils | ||
@@ -515,0 +624,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4210403
43051
685
4
+ Added@types/lodash@^4.14.136
+ Addedlodash@^4.17.14
+ Added@types/lodash@4.17.13(transitive)
+ Addedlodash@4.17.21(transitive)