Socket
Socket
Sign inDemoInstall

soql-parser-js

Package Overview
Dependencies
Maintainers
1
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

soql-parser-js - npm Package Versions

1
9

4.0.0

Diff

Changelog

Source

4.0.0

April 13, 20201

💥 Breaking Changes 💥

Release 4.x has changed the way the groupBy and having clauses are parsed. (#149) Previously, the groupBy clause only allowed multiple entries for fields, but not functions.

The groupBy and orderBy are now always returned as arrays from parsed queries to normalize the returned data structure.

For backwards compatibility, a single groupBy or orderBy object is allowed to be passed in to composeQuery(), but a parsed query will always return an array.

The Query object now has

  • A list of group by clauses (a single groupBy clause is allowed if you build the data structure yourself)
  • A Having clause (this was previously nested in the groupBy clause)
  • A list of orderBy clauses (a single orderBy clause is allowed if you build the data structure yourself)
-groupBy?: GroupByClause;
+groupBy?: GroupByClause | GroupByClause[]; // a parsed query will always be undefined or an array
+having?: HavingClause;
orderBy?: OrderByClause | OrderByClause[]; // a parsed query will always be undefined or an array

Each groupBy clause

  • No longer has a nested having clause
  • Is an object with a single field or fn property
type GroupByClause = GroupByFieldClause | GroupByFnClause;

-interface GroupByOptionalFieldsClause {
-  having?: HavingClause;
-}

-interface GroupByFieldClause extends GroupByOptionalFieldsClause {
+interface GroupByFieldClause {
-  field: string | string[];
+  field: string;
}

-interface GroupByFnClause extends GroupByOptionalFieldsClause {
+interface GroupByFnClause {
  fn: FunctionExp;
}

Here are a few examples of how the groupBy is parsed or expected when composing a query:

SELECT UserId, CALENDAR_MONTH(LoginTime) month FROM LoginHistory WHERE NetworkId != NULL GROUP BY UserId, CALENDAR_MONTH(LoginTime)

{
  fields: [
    {
      type: 'Field',
      field: 'UserId',
    },
    {
      type: 'FieldFunctionExpression',
      functionName: 'CALENDAR_MONTH',
      rawValue: 'CALENDAR_MONTH(LoginTime)',
      parameters: ['LoginTime'],
      alias: 'month',
    },
  ],
  sObject: 'LoginHistory',
  where: {
    left: {
      field: 'NetworkId',
      operator: '!=',
      literalType: 'NULL',
      value: 'NULL',
    },
  },
  groupBy: [
    { field: 'UserId' },
    {
      fn: {
        functionName: 'CALENDAR_MONTH',
        rawValue: 'CALENDAR_MONTH(LoginTime)',
        parameters: ['LoginTime'],
      },
    },
  ],
}

SELECT ProductCode FROM Product2 GROUP BY ProductCode HAVING COUNT(Id) > 1 ORDER BY COUNT(Id) DESC

{
  fields: [{ type: 'Field', field: 'ProductCode' }],
  sObject: 'Product2',
  groupBy: [{
    field: 'ProductCode',
  }],
  having: {
    left: {
      operator: '>',
      value: '1',
      literalType: 'INTEGER',
      fn: { rawValue: 'COUNT(Id)', functionName: 'COUNT', parameters: ['Id'] },
    },
  },
  orderBy: [{
    fn: { rawValue: 'COUNT(Id)', functionName: 'COUNT', parameters: ['Id'] },
    order: 'DESC',
  }],
}

SELECT SBQQ__Product__r.Name foo, SBQQ__Quote__c foo1 FROM SBQQ__Quoteline__c GROUP BY SBQQ__Quote__c, SBQQ__Product__r.Name

{
  fields: [
    {
      type: 'FieldRelationship',
      field: 'Name',
      relationships: ['SBQQ__Product__r'],
      rawValue: 'SBQQ__Product__r.Name',
      alias: 'foo',
    },
    {
      type: 'Field',
      field: 'SBQQ__Quote__c',
      alias: 'foo1',
    },
  ],
  sObject: 'SBQQ__Quoteline__c',
  groupBy: [{ field: 'SBQQ__Quote__c' }, { field: 'SBQQ__Product__r.Name' }],
}
paustint
published 3.2.0 •

Changelog

Source

3.2.0

March 27, 2021

A number of improvements to the formatter have been made with this release.

  • The formatter option whereClauseOperatorsIndented has been deprecated and will always be applied.
  • A new boolean formatter option named newLineAfterKeywords has been added and will ensure that there is always a new line after any keyword. (#137)
  • TYPEOF fields will now always be included on their own line be default, or will span multiple lines, split by keywords if newLineAfterKeywords is set to true. (#135)

Example

SELECT Id, TYPEOF What WHEN Account THEN Phone, NumberOfEmployees WHEN Opportunity THEN Amount, CloseDate ELSE Name, Email END, Name FROM Event

formatOptions: { newLineAfterKeywords: true, fieldMaxLineLength: 1 },

SELECT
  Id,
  TYPEOF What
    WHEN
      Account
    THEN
      Phone, NumberOfEmployees
    WHEN
      Opportunity
    THEN
      Amount, CloseDate
    ELSE
      Name, Email
  END,
  Name
FROM
  Event
paustint
published 3.1.0 •

Changelog

Source

3.1.0

March 27, 2021

  1. Added support for the FIELDS() function
paustint
published 3.0.2 •

Changelog

Source

3.0.2

March 6, 2021

  1. Date functions were not properly parsed when used in order by clauses. (#139)
  2. Modified names of functions / types (internal)
  3. Removed improper import of isString from node utils

Changes also released to 2.5.6

paustint
published 2.5.6 •

paustint
published 3.0.1 •

Changelog

Source

3.0.1

January 7, 20201

  1. getFlattenedFields did not properly handle the alias for an aggregate function within an aggregate query. (#131)
paustint
published 3.0.0 •

Changelog

Source

3.0.0

October 14, 2020

🔥 Breaking Changes 🔥

This version changes the WHERE clause structure when using the NOT operator t0 fix issue #122, and has implemented stricter type definitions.

The NOT operator is now treated as a LogicalOperator and will be set in the operator field between left and right. In cases where this is populated, the preceding left condition will either be set to null or will at most have the openParens field populated.

The logicalPrefix property has been removed from Condition.

Example of the change in structure for queries using NOT - SELECT Id FROM Account WHERE NOT Id = '2'

{
  "fields": [
    {
      "type": "Field",
      "field": "Id"
    }
  ],
  "sObject": "Account",
  "where": {
-    "left": {
-      "logicalPrefix": "NOT",
-      "field": "Id",
-      "operator": "=",
-      "value": "'2'",
-      "literalType": "STRING"
-    }
+    "left": null
+    "operator": "NOT",
+    "right": {
+      "left": {
+        "field": "Id",
+        "operator": "=",
+        "value": "'2'",
+        "literalType": "STRING"
+      }
  }
}

If you are using Typescript in strict mode, you may encounter some breaking changes to your types depending on how you pre-checked for the presence of fields.

Field and FieldRelationship are now made up of two types, one with and one without alias. Condition is now made up of multiple individual interfaces that represent different data types based on what data is populated. OrderByClause is now made up of multiple individual interfaces that represent different data types based on what data is populated. GroupByClause is now made up of multiple individual interfaces that represent different data types based on what data is populated. HavingClause is now made up of multiple individual interfaces that represent different data types based on what data is populated.

Previously you could have just done null/undefined checks in Typescript strict mode. Now, to avoid using the any type, you can use the newly introduced utility methods that provide type detection and type narrowing.

  • hasAlias()
  • isFieldSubquery()
  • isGroupByField()
  • isGroupByFn()
  • isHavingClauseWithRightCondition()b
  • isNegationCondition()
  • isOrderByField()
  • isOrderByFn()
  • isString()
  • isSubquery()
  • isValueCondition()
  • isValueFunctionCondition()
  • isValueQueryCondition()
  • isValueWithDateLiteralCondition()
  • isValueWithDateNLiteralCondition()
  • isWhereClauseWithRightCondition()
  • isWhereOrHavingClauseWithRightCondition()

Here is a summary of the core changes, view the Readme for the comprehensive types.

export type FieldType =
   | Field
+  | FieldWithAlias
   | FieldFunctionExpression
   | FieldRelationship
+  | FieldRelationshipWithAlias
   | FieldSubquery
   | FieldTypeOf;
-export interface WhereClause {
-  left: Condition & ValueQuery;
-  right?: WhereClause;
-  operator?: LogicalOperator;
-}

+export type WhereClause = WhereClauseWithoutOperator | WhereClauseWithRightCondition;

-export interface Condition {
-  openParen?: number;
-  closeParen?: number;
-  logicalPrefix?: LogicalPrefix;
-  field?: string;
-  fn?: FunctionExp;
-  operator: Operator;
-  value?: string | string[];
-  literalType?: LiteralType | LiteralType[]; // If populated with STRING on compose, the value(s) will be wrapped in "'" if they are not already. - All other values ignored
-  dateLiteralVariable?: number | number[]; // not required for compose, will be populated if SOQL is parsed
-}

+export type Condition =
+  | ValueCondition
+  | ValueWithDateLiteralCondition
+  | ValueWithDateNLiteralCondition
+  | ValueFunctionCondition
+  | NegationCondition;
-export interface OrderByClause {
-  field?: string;
-  fn?: FunctionExp;
-  order?: OrderByCriterion;
-  nulls?: NullsOrder;
-}

+export type OrderByClause = OrderByFieldClause | OrderByFnClause;
-export interface GroupByClause {
-  field?: string | string[];
-  fn?: FunctionExp;
-  having?: HavingClause;
-}

+export type GroupByClause = GroupByFieldClause | GroupByFnClause;

-export interface HavingClause {
-  left: Condition;
-  right?: HavingClause;
-  operator?: LogicalOperator;
-}

+export type HavingClause = HavingClauseWithoutOperator | HavingClauseWithRightCondition;
paustint
published 2.5.5 •

Changelog

Source

2.5.5

Aug 23, 2020

  1. getFlattenedFields ignores typeof clauses in query. (#115)
paustint
published 2.5.4 •

Changelog

Source

2.5.4

April 12, 2020

  1. getFlattenedFields returns incorrect results if relationship field is grouped and you are grouping for only one field (#113)
paustint
published 2.5.3 •

Changelog

Source

2.5.3

April 24, 2020

  1. Fixed nanoseconds on date (#102)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc