From 3797a31e90996cdef7fd406f42d76f629801d6c1 Mon Sep 17 00:00:00 2001 From: Austin Turner Date: Mon, 11 May 2026 08:32:43 -0700 Subject: [PATCH 1/3] feat: add additional test-cases for USING SCOPE to ensure compatibility --- test/test-cases-for-is-valid.ts | 5 ++ test/test-cases.ts | 84 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/test/test-cases-for-is-valid.ts b/test/test-cases-for-is-valid.ts index 7de5972..b34d745 100644 --- a/test/test-cases-for-is-valid.ts +++ b/test/test-cases-for-is-valid.ts @@ -494,5 +494,10 @@ WHERE isValid: true, }, { testCase: 161, soql: `SELECT Name, Id FROM Contact USING SCOPE mru ORDER BY Name ASC`, isValid: true }, + { testCase: 162, soql: `SELECT Id FROM Account USING SCOPE scopingRule`, isValid: true }, + { testCase: 163, soql: `SELECT Id FROM Account USING SCOPE mine_and_my_groups`, isValid: true }, + { testCase: 164, soql: `SELECT Id FROM Account USING SCOPE my_territory`, isValid: true }, + { testCase: 165, soql: `SELECT Id FROM Account USING SCOPE my_team_territory`, isValid: true }, + { testCase: 166, soql: `SELECT Id, Name FROM Account USING SCOPE myRule`, isValid: true }, ]; export default testCases; diff --git a/test/test-cases.ts b/test/test-cases.ts index 7867489..ed1170c 100644 --- a/test/test-cases.ts +++ b/test/test-cases.ts @@ -2699,6 +2699,90 @@ export const testCases: TestCase[] = [ orderBy: [{ field: 'Name', order: 'ASC' }], }, }, + { + testCase: 130, + soql: 'SELECT Id FROM Task USING SCOPE delegated', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Task', + usingScope: 'delegated', + }, + }, + { + testCase: 131, + soql: 'SELECT Id FROM Account USING SCOPE everything', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'everything', + }, + }, + { + testCase: 132, + soql: 'SELECT Id FROM Account USING SCOPE mine', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'mine', + }, + }, + { + testCase: 133, + soql: 'SELECT Id FROM ProcessInstanceWorkitem USING SCOPE mine_and_my_groups', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'ProcessInstanceWorkitem', + usingScope: 'mine_and_my_groups', + }, + }, + { + testCase: 134, + soql: 'SELECT Id FROM Account USING SCOPE my_territory', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'my_territory', + }, + }, + { + testCase: 135, + soql: 'SELECT Id FROM Account USING SCOPE my_team_territory', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'my_team_territory', + }, + }, + { + testCase: 136, + soql: 'SELECT Id FROM Account USING SCOPE team', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'team', + }, + }, + { + testCase: 137, + soql: 'SELECT Id FROM Account USING SCOPE scopingRule', + output: { + fields: [{ type: 'Field', field: 'Id' }], + sObject: 'Account', + usingScope: 'scopingRule', + }, + }, + { + testCase: 138, + soql: 'SELECT Id, Name FROM Account USING SCOPE myRule', + output: { + fields: [ + { type: 'Field', field: 'Id' }, + { type: 'Field', field: 'Name' }, + ], + sObject: 'Account', + usingScope: 'myRule', + }, + }, ]; export default testCases; From 618ef34ce9481b89ace6d74e06212b7d685f643c Mon Sep 17 00:00:00 2001 From: Austin Turner Date: Mon, 11 May 2026 08:33:30 -0700 Subject: [PATCH 2/3] feat: enhance LWC build process with new artifacts and improved metadata packaging --- .release-it.json | 9 +++- CHANGELOG.md | 19 +++++++++ README.md | 78 +++++++++++++++++++++++------------ package.json | 18 +++++--- tasks/build.mjs | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 35 deletions(-) create mode 100644 tasks/build.mjs diff --git a/.release-it.json b/.release-it.json index 5a4b89f..1becec0 100644 --- a/.release-it.json +++ b/.release-it.json @@ -3,11 +3,16 @@ "commitMessage": "chore: release v${version}" }, "github": { - "release": true + "release": true, + "assets": [ + "jetstreamapp-soql-parser-js-${version}.tgz", + "dist/soql-parser-js-lwc-v${version}.zip", + "dist/lwc/soqlParserJs.js" + ] }, "hooks": { "before:init": ["npm run build", "npm test"], - "after:bump": "npm run build", + "after:bump": ["npm run build", "npm pack"], "after:release": "npm run copy-tc-to-docs && cd docs && npm install @jetstreamapp/soql-parser-js@${version} && git add package*.json && git add static/sample-queries-json.json && git commit -m \"Updated docs version\" && git push && npm run deploy" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index edd1859..f7ae9d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 7.2.0 + +May 11, 2026 + +### LWC Distribution + +The LWC build now produces two artifacts to support different deployment workflows: + +- **Standalone JS file** at `dist/lwc/soqlParserJs.js` — a single bundled file that SFDX users can drop directly into their project's `lwc/soqlParserJs/` folder alongside their own `.js-meta.xml`. Also published to npm and attached to each GitHub Release. +- **Ready-to-deploy metadata package** at `dist/lwc-packaged/` — contains `package.xml`, `lwc/soqlParserJs/soqlParserJs.js`, and `soqlParserJs.js-meta.xml`. Deploy directly with `sf project deploy start --metadata-dir dist/lwc-packaged --target-org `, no SFDX project required. +- **Pre-zipped metadata package on GitHub Releases** — every release attaches `soql-parser-js-lwc-v.zip` (the metadata package, pre-zipped) so users can grab a single archive, and deploy without cloning or running `npm install`. +- **Fixed LWC compiler compatibility** — lowered the LWC bundle's esbuild target to `es2020`, which down-levels ES2022 syntax (e.g. static class initialization blocks) that the Salesforce LWC compiler does not yet support. +- **Configurable Salesforce API version** — added the `salesforceApiVersion` field to `package.json` (currently `66.0`); the value is stamped into both `package.xml` and `.js-meta.xml` at build time, so bumping the API version is a one-line change. + +### Release Pipeline + +- **npm tarball attached to GitHub Releases** — every release now attaches `jetstreamapp-soql-parser-js-.tgz`. +- **Version banner on all bundles** — `esm`, `cjs`, `cli`, and `lwc` bundles all start with a `/*! ... */` header listing the package name, version, repository URL, and license. Banner values are sourced from `package.json`, so they stay in sync automatically with each release. + ## 7.1.1 Apr 25, 2026 diff --git a/README.md b/README.md index 54ebfd9..12ba238 100644 --- a/README.md +++ b/README.md @@ -510,52 +510,74 @@ WHERE Name LIKE 'a%' ## Using in LWC -The easiest way to utilize this library in LWC is to deploy the compiled code as a web component in your org. +The library can be used as a Lightning Web Component in your Salesforce org. The build produces two artifacts to support different workflows: -:warning: The minified version ends up with `$A` characters in the output, which causes the deployment to SFD to fail, so we have created an unminified version of the library just for Salesforce. +| Artifact | What it is | Best for | +| ------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `dist/lwc/soqlParserJs.js` | Standalone bundled JS file (no metadata) | SFDX projects — drop into your existing `lwc/soqlParserJs/` folder | +| `dist/lwc-packaged/` (and the release zip) | Full Salesforce metadata package: `package.xml` + `lwc/soqlParserJs/{js,js-meta.xml}` | Direct deployment to an org via `sf project deploy start` — no SFDX project required | -### Obtaining the build artifacts +The Salesforce API version used for the metadata package is configured via the `salesforceApiVersion` field in [package.json](package.json) and is applied to both `package.xml` and `soqlParserJs.js-meta.xml` at build time. -We don't store the built artifacts on github, so you will need to obtain from NPM or run the build command yourself. +### Option 1: SFDX project — drop in the standalone JS file -#### Download from NPM +If you already have an SFDX project, the easiest path is to grab the standalone `soqlParserJs.js` and place it in your project's `lwc/soqlParserJs/` folder alongside a `soqlParserJs.js-meta.xml` file you provide yourself. -Download from [npm](https://www.npmjs.com/package/@jetstreamapp/soql-parser-js) +Sources for the standalone JS: -**Either:** +- **GitHub Releases** — every release attaches `soqlParserJs.js` directly to the [Releases page](https://github.com/jetstreamapp/soql-parser-js/releases). +- **npm** — `npm install @jetstreamapp/soql-parser-js`, then copy from `node_modules/@jetstreamapp/soql-parser-js/dist/lwc/soqlParserJs.js`. +- **Local build** — clone the repo, run `npm install && npm run build:lwc`, and find the file at `dist/lwc/soqlParserJs.js`. -1. Go to the "Code Tab" on the [npm](https://www.npmjs.com/package/@jetstreamapp/soql-parser-js) listing - 1. Navigate to `/dist/lwc.index.mjs` -2. Install this project in an existing node library by running `npm install @jetstreamapp/soql-parser-js` - 1. then navigating to the downloaded code in this folder: `node_modules/@jetstreamapp/soql-parser-js/dist/lwc` +Your SFDX folder should look like: -#### Build the files yourself +``` +force-app/main/default/lwc/soqlParserJs/ +├── soqlParserJs.js <-- copied from this project +└── soqlParserJs.js-meta.xml <-- your own (example below) +``` -1. Clone/download the repository from GitHub -2. Ensure you have node installed (version 22 or higher) -3. Install dependencies with `npm install` -4. Run `npm build:lwc` -5. The output will be placed in `/dist/lwc.index.mjs` +A minimal `soqlParserJs.js-meta.xml`: -### Deploying and Using in Salesforce +```xml + + + 65.0 + false + +``` -Copy `index.mjs` into an LWC component. +### Option 2: Direct deployment — use the pre-built metadata package -For example: +If you don't have an SFDX project, download the pre-zipped metadata package, extract, and deploy: +```bash +# Download soql-parser-js-lwc-v.zip from the GitHub Releases page, then: +unzip soql-parser-js-lwc-v.zip -d soql-parser-js-lwc +sf project deploy start --metadata-dir soql-parser-js-lwc --target-org ``` -soqlParserJsLib -- soqlParserJsLib.js <--- copy the code here -- soqlParserJsLib.js-meta.xml + +Or, if you've built locally, the equivalent directory is `dist/lwc-packaged/`: + +```bash +sf project deploy start --metadata-dir dist/lwc-packaged --target-org ``` -After you have deployed the LWC, you can import it just like any other LWC import. +Legacy `sfdx` CLI alternative: + +```bash +sfdx force:mdapi:deploy -d -w 10 +``` + +### Using in Salesforce + +The deployed component is `c/soqlParserJs`. It is intentionally a library component (`isExposed=false`), so you don't drop it on a Lightning page directly — instead, import its exports from your own LWC: ```js import { LightningElement } from 'lwc'; -import { parseQuery } from 'c/soqlParserJsLib'; +import { parseQuery } from 'c/soqlParserJs'; -export default class SoqlParserJs extends LightningElement { +export default class MyComponent extends LightningElement { parsedQuery; get parsedQueryString() { @@ -570,12 +592,14 @@ export default class SoqlParserJs extends LightningElement { ```html ``` +All public exports of the library (`parseQuery`, `composeQuery`, `formatQuery`, `isQueryValid`, the various utility functions, etc.) are available as named imports from `c/soqlParserJs`. + ## CLI Install globally or use `npx` to interact with the cli. diff --git a/package.json b/package.json index 17f7236..f1fd573 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@jetstreamapp/soql-parser-js", "version": "7.1.1", + "salesforceApiVersion": "66.0", "description": "Salesforce.com SOQL parser and composer", "main": "dist/cjs/index.js", "module": "dist/esm/index.mjs", @@ -15,11 +16,12 @@ "scripts": { "clean": "rm -rf ./dist/*", "prebuild": "npm run clean", - "build": "npm-run-all build:esm build:lwc build:cjs build:cli build:declarations", - "build:esm": "esbuild src/index.ts --bundle --outfile=dist/esm/index.mjs --minify --format=esm --target=es2022", - "build:lwc": "esbuild src/index.ts --bundle --outfile=dist/lwc/index.js --format=esm --target=es2022", - "build:cjs": "esbuild src/index.ts --bundle --outfile=dist/cjs/index.js --minify --format=cjs --target=es2022", - "build:cli": "esbuild cli/index.ts --bundle --outfile=dist/cli/index.js --minify --format=cjs --target=es2022 --platform=node", + "build": "npm-run-all build:bundles build:declarations", + "build:bundles": "node tasks/build.mjs", + "build:esm": "node tasks/build.mjs esm", + "build:lwc": "node tasks/build.mjs lwc", + "build:cjs": "node tasks/build.mjs cjs", + "build:cli": "node tasks/build.mjs cli", "build:declarations": "tsc --project tsconfig.json", "tsc": "tsc", "release": "release-it", @@ -37,7 +39,11 @@ "access": "public" }, "files": [ - "dist/**", + "dist/esm/**", + "dist/cjs/**", + "dist/cli/**", + "dist/lwc/**", + "dist/types/**", "bin/**", "AUTHORS.md", "CHANGELOG.md", diff --git a/tasks/build.mjs b/tasks/build.mjs new file mode 100644 index 0000000..58e2667 --- /dev/null +++ b/tasks/build.mjs @@ -0,0 +1,104 @@ +import { build } from 'esbuild'; +import { readFileSync, writeFileSync, rmSync, mkdirSync, copyFileSync } from 'node:fs'; +import { execFileSync } from 'node:child_process'; + +const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')); +const repoUrl = (pkg.repository?.url ?? '').replace(/^git\+/, '').replace(/\.git$/, ''); + +const banner = `/*! + * ${pkg.name} v${pkg.version} + * ${repoUrl} + * @license ${pkg.license} + */`; + +const LWC_COMPONENT_NAME = 'soqlParserJs'; +const LWC_STANDALONE_DIR = 'dist/lwc'; +const LWC_STANDALONE_FILE = `${LWC_STANDALONE_DIR}/${LWC_COMPONENT_NAME}.js`; +const LWC_PACKAGE_DIR = 'dist/lwc-packaged'; +const LWC_PACKAGE_BUNDLE_DIR = `${LWC_PACKAGE_DIR}/lwc/${LWC_COMPONENT_NAME}`; + +const targets = { + esm: { + entryPoints: ['src/index.ts'], + outfile: 'dist/esm/index.mjs', + format: 'esm', + }, + lwc: { + entryPoints: ['src/index.ts'], + outfile: LWC_STANDALONE_FILE, + format: 'esm', + // LWC's compiler doesn't support certain ES2022 syntax + target: 'es2020', + }, + cjs: { + entryPoints: ['src/index.ts'], + outfile: 'dist/cjs/index.js', + format: 'cjs', + }, + cli: { + entryPoints: ['cli/index.ts'], + outfile: 'dist/cli/index.js', + format: 'cjs', + platform: 'node', + }, +}; + +const requested = process.argv[2]; +const names = requested ? [requested] : Object.keys(targets); + +for (const name of names) { + if (!targets[name]) { + console.error(`Unknown build target: ${name}. Valid targets: ${Object.keys(targets).join(', ')}`); + process.exit(1); + } +} + +await Promise.all( + names.map(async name => { + await build({ + bundle: true, + target: 'es2022', + banner: { js: banner }, + minify: true, + ...targets[name], + }); + if (name === 'lwc') { + writeLwcPackage(); + } + }), +); + +function writeLwcPackage() { + const apiVersion = pkg.salesforceApiVersion; + if (!apiVersion) { + throw new Error('Missing "salesforceApiVersion" in package.json — required for LWC package metadata.'); + } + mkdirSync(LWC_PACKAGE_BUNDLE_DIR, { recursive: true }); + copyFileSync(LWC_STANDALONE_FILE, `${LWC_PACKAGE_BUNDLE_DIR}/${LWC_COMPONENT_NAME}.js`); + + const packageXml = ` + + + ${LWC_COMPONENT_NAME} + LightningComponentBundle + + ${apiVersion} + +`; + const metaXml = ` + + ${apiVersion} + false + +`; + writeFileSync(`${LWC_PACKAGE_DIR}/package.xml`, packageXml); + writeFileSync(`${LWC_PACKAGE_BUNDLE_DIR}/${LWC_COMPONENT_NAME}.js-meta.xml`, metaXml); + writeLwcZip(); +} + +function writeLwcZip() { + const zipName = `soql-parser-js-lwc-v${pkg.version}.zip`; + const zipPath = `dist/${zipName}`; + rmSync(zipPath, { force: true }); + execFileSync('zip', ['-r', `../${zipName}`, '.'], { cwd: LWC_PACKAGE_DIR, stdio: 'inherit' }); +} From 120dd2b94eb5d60c6c011d4235e24d4e3780957b Mon Sep 17 00:00:00 2001 From: Austin Turner Date: Mon, 11 May 2026 08:38:50 -0700 Subject: [PATCH 3/3] chore: update release workflow permissions and npm setup for improved reliability --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9f10ce..7a65fda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ on: - patch permissions: + id-token: write contents: write jobs: @@ -28,6 +29,8 @@ jobs: with: node-version: '24' cache: 'npm' + registry-url: 'https://registry.npmjs.org' + package-manager-cache: false - name: install dependencies run: npm ci - name: git config