From eb62f2baba3938002755176d2413a8b94a7aed5e Mon Sep 17 00:00:00 2001 From: Jonny Hork Date: Thu, 13 Jun 2024 12:13:44 -0600 Subject: [PATCH] Jh/bug filter by null (#285) * chore: use openssl legacy provider for node build * fix: allow users to filter string field types by null * chore: address new lint errors * chore: update release please version * chore: release 1.0.0 Release-As: 1.0.0 --- .github/workflows/release-soql-builder-ui.yml | 2 +- .github/workflows/release-soql-common.yml | 2 +- .github/workflows/release-soql-data-view.yml | 2 +- .github/workflows/release-soql-model.yml | 2 +- packages/soql-builder-ui/.eslintrc.json | 8 +++++++- packages/soql-builder-ui/package.json | 2 +- .../src/modules/querybuilder/app/app.ts | 19 ++++++++++--------- .../src/modules/querybuilder/fields/fields.ts | 4 ++-- .../src/modules/querybuilder/from/from.ts | 2 +- .../src/modules/querybuilder/limit/limit.ts | 2 +- .../modules/querybuilder/orderBy/orderBy.ts | 4 ++-- .../src/modules/querybuilder/where/where.ts | 2 +- .../whereModifierGroup.test.ts | 1 + packages/soql-builder-ui/tsconfig.json | 1 + .../src/validators/stringValidator.test.ts | 8 ++++++++ .../src/validators/stringValidator.ts | 9 +++++---- 16 files changed, 44 insertions(+), 26 deletions(-) diff --git a/.github/workflows/release-soql-builder-ui.yml b/.github/workflows/release-soql-builder-ui.yml index f5374ce0..f3b97426 100644 --- a/.github/workflows/release-soql-builder-ui.yml +++ b/.github/workflows/release-soql-builder-ui.yml @@ -12,7 +12,7 @@ jobs: release-soql-builder-ui: runs-on: ubuntu-latest steps: - - uses: GoogleCloudPlatform/release-please-action@v2 + - uses: GoogleCloudPlatform/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-soql-common.yml b/.github/workflows/release-soql-common.yml index 9b186f1c..746970e5 100644 --- a/.github/workflows/release-soql-common.yml +++ b/.github/workflows/release-soql-common.yml @@ -12,7 +12,7 @@ jobs: release-soql-common: runs-on: ubuntu-latest steps: - - uses: GoogleCloudPlatform/release-please-action@v2 + - uses: GoogleCloudPlatform/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-soql-data-view.yml b/.github/workflows/release-soql-data-view.yml index 00afde57..82e4f064 100644 --- a/.github/workflows/release-soql-data-view.yml +++ b/.github/workflows/release-soql-data-view.yml @@ -12,7 +12,7 @@ jobs: release-soql-data-view: runs-on: ubuntu-latest steps: - - uses: GoogleCloudPlatform/release-please-action@v2 + - uses: GoogleCloudPlatform/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-soql-model.yml b/.github/workflows/release-soql-model.yml index 78f6bdaf..51d89611 100644 --- a/.github/workflows/release-soql-model.yml +++ b/.github/workflows/release-soql-model.yml @@ -12,7 +12,7 @@ jobs: release-soql-model: runs-on: ubuntu-latest steps: - - uses: GoogleCloudPlatform/release-please-action@v2 + - uses: GoogleCloudPlatform/release-please-action@v4 id: release with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/packages/soql-builder-ui/.eslintrc.json b/packages/soql-builder-ui/.eslintrc.json index 4006118f..539c2471 100644 --- a/packages/soql-builder-ui/.eslintrc.json +++ b/packages/soql-builder-ui/.eslintrc.json @@ -9,6 +9,12 @@ "@lwc/lwc/no-async-operation": "off", "@lwc/lwc/no-inner-html": "warn", "@lwc/lwc/no-document-query": "warn", - "no-underscore-dangle": "off" + "no-underscore-dangle": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "varsIgnorePattern": "[api|track]" + } + ] } } diff --git a/packages/soql-builder-ui/package.json b/packages/soql-builder-ui/package.json index 970eec06..8084aa28 100644 --- a/packages/soql-builder-ui/package.json +++ b/packages/soql-builder-ui/package.json @@ -44,7 +44,7 @@ "license": "BSD-3-Clause", "main": "dist/", "scripts": { - "build": "lwc-services build -w webpack.config.js -m production", + "build": "export NODE_OPTIONS=--openssl-legacy-provider && lwc-services build -w webpack.config.js -m production", "clean": "shx rm -rf package-lock.json && shx rm -rf dist && shx rm -rf node_modules", "publish:lwc": "npm publish .", "lint": "eslint ./src", diff --git a/packages/soql-builder-ui/src/modules/querybuilder/app/app.ts b/packages/soql-builder-ui/src/modules/querybuilder/app/app.ts index c31cb46e..a4384f03 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/app/app.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/app/app.ts @@ -7,6 +7,7 @@ */ import { LightningElement, track } from 'lwc'; +import { JsonMap } from '@salesforce/ts-types'; import { ToolingSDK } from '../services/toolingSDK'; import { MessageServiceFactory } from '../services/message/messageServiceFactory'; @@ -176,7 +177,7 @@ export default class App extends LightningElement { } /* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-return*/ - public inspectUnsupported(unsupported): any { + public inspectUnsupported(unsupported: JsonMap[]): any { const filteredUnsupported = unsupported // this reason is often associated with a parse error, so snuffing it out instead of double notifications .filter( @@ -189,7 +190,7 @@ export default class App extends LightningElement { return filteredUnsupported; } /* ---- SOBJECT HANDLERS ---- */ - public handleObjectChange(e): void { + public handleObjectChange(e: CustomEvent): void { const selectedSObjectName = e.detail.selectedSobject; this.onSObjectChanged(selectedSObjectName); // when triggered by the ui, send message @@ -204,7 +205,7 @@ export default class App extends LightningElement { } } /* ---- FIELD HANDLERS ---- */ - public handleFieldSelected(e): void { + public handleFieldSelected(e: CustomEvent): void { this.modelService.setFields(e.detail.fields); } public handleFieldSelectAll(): void { @@ -215,24 +216,24 @@ export default class App extends LightningElement { } /* ---- ORDER BY HANDLERS ---- */ - public handleOrderBySelected(e): void { + public handleOrderBySelected(e: CustomEvent): void { this.modelService.addUpdateOrderByField(e.detail); } - public handleOrderByRemoved(e): void { + public handleOrderByRemoved(e: CustomEvent): void { this.modelService.removeOrderByField(e.detail.field); } /* ---- LIMIT HANDLERS ---- */ - public handleLimitChanged(e): void { + public handleLimitChanged(e: CustomEvent): void { this.modelService.changeLimit(e.detail.limit); } /* ---- WHERE HANDLERS ---- */ - public handleWhereSelection(e): void { + public handleWhereSelection(e: CustomEvent): void { this.modelService.upsertWhereFieldExpr(e.detail); } - public handleAndOrSelection(e): void { + public handleAndOrSelection(e: CustomEvent): void { this.modelService.setAndOr(e.detail); } - public handleRemoveWhereCondition(e): void { + public handleRemoveWhereCondition(e: CustomEvent): void { this.modelService.removeWhereFieldCondition(e.detail); } diff --git a/packages/soql-builder-ui/src/modules/querybuilder/fields/fields.ts b/packages/soql-builder-ui/src/modules/querybuilder/fields/fields.ts index ffde57fe..e1b7611d 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/fields/fields.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/fields/fields.ts @@ -32,7 +32,7 @@ export default class Fields extends LightningElement { public selectPlaceHolderText = 'Search fields...'; // TODO: i18n public _displayFields: string[]; - public handleFieldSelection(e): void { + public handleFieldSelection(e: CustomEvent): void { e.preventDefault(); if (e.detail && e.detail.value) { let selection = []; @@ -62,7 +62,7 @@ export default class Fields extends LightningElement { } } - public handleFieldRemoved(e): void { + public handleFieldRemoved(e: Event): void { e.preventDefault(); const fieldRemovedEvent = new CustomEvent('fields__selected', { detail: { diff --git a/packages/soql-builder-ui/src/modules/querybuilder/from/from.ts b/packages/soql-builder-ui/src/modules/querybuilder/from/from.ts index 3a5ae18a..8cfa8d6f 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/from/from.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/from/from.ts @@ -25,7 +25,7 @@ export default class From extends LightningElement { } /* eslint-disable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment */ - public handleSobjectSelection(e): void { + public handleSobjectSelection(e: CustomEvent): void { e.preventDefault(); const selectedSobject = e.detail.value; if (selectedSobject && selectedSobject.length) { diff --git a/packages/soql-builder-ui/src/modules/querybuilder/limit/limit.ts b/packages/soql-builder-ui/src/modules/querybuilder/limit/limit.ts index 237dbea4..03c5984f 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/limit/limit.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/limit/limit.ts @@ -13,7 +13,7 @@ export default class Limit extends LightningElement { @api public limit; /* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access */ - public handleLimitChange(e): void { + public handleLimitChange(e: Event): void { e.preventDefault(); const limit = e.target.value; const sObjectSelected = new CustomEvent('limit__changed', { diff --git a/packages/soql-builder-ui/src/modules/querybuilder/orderBy/orderBy.ts b/packages/soql-builder-ui/src/modules/querybuilder/orderBy/orderBy.ts index 0729f6eb..dbe719a4 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/orderBy/orderBy.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/orderBy/orderBy.ts @@ -21,7 +21,7 @@ export default class OrderBy extends LightningElement { } /* eslint-disable @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-assignment */ - public handleOrderBySelected(e): void { + public handleOrderBySelected(e: Event): void { e.preventDefault(); const orderbyFieldEl = this.template.querySelector( 'querybuilder-custom-select' @@ -44,7 +44,7 @@ export default class OrderBy extends LightningElement { } } - public handleOrderByRemoved(e): void { + public handleOrderByRemoved(e: Event): void { e.preventDefault(); const orderByRemovedEvent = new CustomEvent('orderby__removed', { detail: { field: e.target.dataset.field } diff --git a/packages/soql-builder-ui/src/modules/querybuilder/where/where.ts b/packages/soql-builder-ui/src/modules/querybuilder/where/where.ts index 23aca9fc..7e7d85ce 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/where/where.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/where/where.ts @@ -129,7 +129,7 @@ export default class Where extends LightningElement { } } - public handleModifierGroupSelection(e): void { + public handleModifierGroupSelection(e: Event): void { e.preventDefault(); // eslint-disable-next-line camelcase const where__group_selectionEvent = new CustomEvent( diff --git a/packages/soql-builder-ui/src/modules/querybuilder/whereModifierGroup/whereModifierGroup.test.ts b/packages/soql-builder-ui/src/modules/querybuilder/whereModifierGroup/whereModifierGroup.test.ts index a3326708..dc4c2fb0 100644 --- a/packages/soql-builder-ui/src/modules/querybuilder/whereModifierGroup/whereModifierGroup.test.ts +++ b/packages/soql-builder-ui/src/modules/querybuilder/whereModifierGroup/whereModifierGroup.test.ts @@ -1,4 +1,5 @@ /* eslint-disable @lwc/lwc/prefer-custom-event */ +/* eslint-disable @lwc/lwc/no-inner-html */ /* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ diff --git a/packages/soql-builder-ui/tsconfig.json b/packages/soql-builder-ui/tsconfig.json index e69de29b..0967ef42 100644 --- a/packages/soql-builder-ui/tsconfig.json +++ b/packages/soql-builder-ui/tsconfig.json @@ -0,0 +1 @@ +{} diff --git a/packages/soql-model/src/validators/stringValidator.test.ts b/packages/soql-model/src/validators/stringValidator.test.ts index ef787fae..670194da 100644 --- a/packages/soql-model/src/validators/stringValidator.test.ts +++ b/packages/soql-model/src/validators/stringValidator.test.ts @@ -13,12 +13,20 @@ describe('StringValidator should', () => { const validator = new StringValidator({ type: SObjectFieldType.String }); const validResult = { isValid: true }; const notValidResult = { isValid: false, message: Messages.error_fieldInput_string }; + it('return valid result for string in single quotes', () => { expect(validator.validate("'foo'")).toEqual(validResult); }); + + it('return valid result when user input is NULL or null', () => { + expect(validator.validate("'null'")).toEqual(validResult); + expect(validator.validate("'NULL'")).toEqual(validResult); + }); + it('return not valid result for non-string value', () => { expect(validator.validate('foo')).toEqual(notValidResult); }); + it('return not valid result for string ending in escaped quote', () => { expect(validator.validate("'foo\\'")).toEqual(notValidResult); }); diff --git a/packages/soql-model/src/validators/stringValidator.ts b/packages/soql-model/src/validators/stringValidator.ts index 966072ae..6d0f356c 100644 --- a/packages/soql-model/src/validators/stringValidator.ts +++ b/packages/soql-model/src/validators/stringValidator.ts @@ -10,10 +10,11 @@ import { ValidateResult, Validator } from './validator'; export class StringValidator extends Validator { public validate(input: string): ValidateResult { const isValid = - input.length >= 2 && - input.startsWith("'") && - input.endsWith("'") && - !this.isEscaped(input.substring(1, input.length - 1)); + (input.length >= 2 && + input.startsWith("'") && + input.endsWith("'") && + !this.isEscaped(input.substring(1, input.length - 1))) || + input.toLowerCase() === 'null'; const message = isValid ? undefined : Messages.error_fieldInput_string; return { isValid, message }; }