Skip to content

Commit 56e28ea

Browse files
authored
Merge pull request #282 from jetstreamapp/feat/lwc-build-improvements
Enhance LWC build process and add test cases for USING SCOPE
2 parents c02364f + 120dd2b commit 56e28ea

8 files changed

Lines changed: 285 additions & 35 deletions

File tree

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- patch
1414

1515
permissions:
16+
id-token: write
1617
contents: write
1718

1819
jobs:
@@ -28,6 +29,8 @@ jobs:
2829
with:
2930
node-version: '24'
3031
cache: 'npm'
32+
registry-url: 'https://registry.npmjs.org'
33+
package-manager-cache: false
3134
- name: install dependencies
3235
run: npm ci
3336
- name: git config

.release-it.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
"commitMessage": "chore: release v${version}"
44
},
55
"github": {
6-
"release": true
6+
"release": true,
7+
"assets": [
8+
"jetstreamapp-soql-parser-js-${version}.tgz",
9+
"dist/soql-parser-js-lwc-v${version}.zip",
10+
"dist/lwc/soqlParserJs.js"
11+
]
712
},
813
"hooks": {
914
"before:init": ["npm run build", "npm test"],
10-
"after:bump": "npm run build",
15+
"after:bump": ["npm run build", "npm pack"],
1116
"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"
1217
}
1318
}

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
## 7.2.0
4+
5+
May 11, 2026
6+
7+
### LWC Distribution
8+
9+
The LWC build now produces two artifacts to support different deployment workflows:
10+
11+
- **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.
12+
- **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 <alias>`, no SFDX project required.
13+
- **Pre-zipped metadata package on GitHub Releases** — every release attaches `soql-parser-js-lwc-v<version>.zip` (the metadata package, pre-zipped) so users can grab a single archive, and deploy without cloning or running `npm install`.
14+
- **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.
15+
- **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.
16+
17+
### Release Pipeline
18+
19+
- **npm tarball attached to GitHub Releases** — every release now attaches `jetstreamapp-soql-parser-js-<version>.tgz`.
20+
- **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.
21+
322
## 7.1.1
423

524
Apr 25, 2026

README.md

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -510,52 +510,74 @@ WHERE Name LIKE 'a%'
510510
511511
## Using in LWC
512512
513-
The easiest way to utilize this library in LWC is to deploy the compiled code as a web component in your org.
513+
The library can be used as a Lightning Web Component in your Salesforce org. The build produces two artifacts to support different workflows:
514514
515-
: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.
515+
| Artifact | What it is | Best for |
516+
| ------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------- |
517+
| `dist/lwc/soqlParserJs.js` | Standalone bundled JS file (no metadata) | SFDX projects — drop into your existing `lwc/soqlParserJs/` folder |
518+
| `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 |
516519
517-
### Obtaining the build artifacts
520+
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.
518521
519-
We don't store the built artifacts on github, so you will need to obtain from NPM or run the build command yourself.
522+
### Option 1: SFDX project — drop in the standalone JS file
520523
521-
#### Download from NPM
524+
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.
522525

523-
Download from [npm](https://www.npmjs.com/package/@jetstreamapp/soql-parser-js)
526+
Sources for the standalone JS:
524527

525-
**Either:**
528+
- **GitHub Releases** — every release attaches `soqlParserJs.js` directly to the [Releases page](https://github.com/jetstreamapp/soql-parser-js/releases).
529+
- **npm**`npm install @jetstreamapp/soql-parser-js`, then copy from `node_modules/@jetstreamapp/soql-parser-js/dist/lwc/soqlParserJs.js`.
530+
- **Local build** — clone the repo, run `npm install && npm run build:lwc`, and find the file at `dist/lwc/soqlParserJs.js`.
526531

527-
1. Go to the "Code Tab" on the [npm](https://www.npmjs.com/package/@jetstreamapp/soql-parser-js) listing
528-
1. Navigate to `/dist/lwc.index.mjs`
529-
2. Install this project in an existing node library by running `npm install @jetstreamapp/soql-parser-js`
530-
1. then navigating to the downloaded code in this folder: `node_modules/@jetstreamapp/soql-parser-js/dist/lwc`
532+
Your SFDX folder should look like:
531533

532-
#### Build the files yourself
534+
```
535+
force-app/main/default/lwc/soqlParserJs/
536+
├── soqlParserJs.js <-- copied from this project
537+
└── soqlParserJs.js-meta.xml <-- your own (example below)
538+
```
533539
534-
1. Clone/download the repository from GitHub
535-
2. Ensure you have node installed (version 22 or higher)
536-
3. Install dependencies with `npm install`
537-
4. Run `npm build:lwc`
538-
5. The output will be placed in `/dist/lwc.index.mjs`
540+
A minimal `soqlParserJs.js-meta.xml`:
539541
540-
### Deploying and Using in Salesforce
542+
```xml
543+
<?xml version="1.0" encoding="UTF-8"?>
544+
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
545+
<apiVersion>65.0</apiVersion>
546+
<isExposed>false</isExposed>
547+
</LightningComponentBundle>
548+
```
541549

542-
Copy `index.mjs` into an LWC component.
550+
### Option 2: Direct deployment — use the pre-built metadata package
543551

544-
For example:
552+
If you don't have an SFDX project, download the pre-zipped metadata package, extract, and deploy:
545553

554+
```bash
555+
# Download soql-parser-js-lwc-v<version>.zip from the GitHub Releases page, then:
556+
unzip soql-parser-js-lwc-v<version>.zip -d soql-parser-js-lwc
557+
sf project deploy start --metadata-dir soql-parser-js-lwc --target-org <your-org-alias>
546558
```
547-
soqlParserJsLib
548-
- soqlParserJsLib.js <--- copy the code here
549-
- soqlParserJsLib.js-meta.xml
559+
560+
Or, if you've built locally, the equivalent directory is `dist/lwc-packaged/`:
561+
562+
```bash
563+
sf project deploy start --metadata-dir dist/lwc-packaged --target-org <your-org-alias>
550564
```
551565

552-
After you have deployed the LWC, you can import it just like any other LWC import.
566+
Legacy `sfdx` CLI alternative:
567+
568+
```bash
569+
sfdx force:mdapi:deploy -d <path-to-package> -w 10
570+
```
571+
572+
### Using in Salesforce
573+
574+
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:
553575

554576
```js
555577
import { LightningElement } from 'lwc';
556-
import { parseQuery } from 'c/soqlParserJsLib';
578+
import { parseQuery } from 'c/soqlParserJs';
557579

558-
export default class SoqlParserJs extends LightningElement {
580+
export default class MyComponent extends LightningElement {
559581
parsedQuery;
560582

561583
get parsedQueryString() {
@@ -570,12 +592,14 @@ export default class SoqlParserJs extends LightningElement {
570592

571593
```html
572594
<template>
573-
<button class="slds-button slds-button_neutral" onclick="{handleClick}">Click Me</button>
595+
<button class="slds-button slds-button_neutral" onclick={handleClick}>Click Me</button>
574596

575597
<p>Parsed Query: {parsedQueryString}</p>
576598
</template>
577599
```
578600

601+
All public exports of the library (`parseQuery`, `composeQuery`, `formatQuery`, `isQueryValid`, the various utility functions, etc.) are available as named imports from `c/soqlParserJs`.
602+
579603
## CLI
580604

581605
Install globally or use `npx` to interact with the cli.

package.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"name": "@jetstreamapp/soql-parser-js",
33
"version": "7.1.1",
4+
"salesforceApiVersion": "66.0",
45
"description": "Salesforce.com SOQL parser and composer",
56
"main": "dist/cjs/index.js",
67
"module": "dist/esm/index.mjs",
@@ -15,11 +16,12 @@
1516
"scripts": {
1617
"clean": "rm -rf ./dist/*",
1718
"prebuild": "npm run clean",
18-
"build": "npm-run-all build:esm build:lwc build:cjs build:cli build:declarations",
19-
"build:esm": "esbuild src/index.ts --bundle --outfile=dist/esm/index.mjs --minify --format=esm --target=es2022",
20-
"build:lwc": "esbuild src/index.ts --bundle --outfile=dist/lwc/index.js --format=esm --target=es2022",
21-
"build:cjs": "esbuild src/index.ts --bundle --outfile=dist/cjs/index.js --minify --format=cjs --target=es2022",
22-
"build:cli": "esbuild cli/index.ts --bundle --outfile=dist/cli/index.js --minify --format=cjs --target=es2022 --platform=node",
19+
"build": "npm-run-all build:bundles build:declarations",
20+
"build:bundles": "node tasks/build.mjs",
21+
"build:esm": "node tasks/build.mjs esm",
22+
"build:lwc": "node tasks/build.mjs lwc",
23+
"build:cjs": "node tasks/build.mjs cjs",
24+
"build:cli": "node tasks/build.mjs cli",
2325
"build:declarations": "tsc --project tsconfig.json",
2426
"tsc": "tsc",
2527
"release": "release-it",
@@ -37,7 +39,11 @@
3739
"access": "public"
3840
},
3941
"files": [
40-
"dist/**",
42+
"dist/esm/**",
43+
"dist/cjs/**",
44+
"dist/cli/**",
45+
"dist/lwc/**",
46+
"dist/types/**",
4147
"bin/**",
4248
"AUTHORS.md",
4349
"CHANGELOG.md",

tasks/build.mjs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { build } from 'esbuild';
2+
import { readFileSync, writeFileSync, rmSync, mkdirSync, copyFileSync } from 'node:fs';
3+
import { execFileSync } from 'node:child_process';
4+
5+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
6+
const repoUrl = (pkg.repository?.url ?? '').replace(/^git\+/, '').replace(/\.git$/, '');
7+
8+
const banner = `/*!
9+
* ${pkg.name} v${pkg.version}
10+
* ${repoUrl}
11+
* @license ${pkg.license}
12+
*/`;
13+
14+
const LWC_COMPONENT_NAME = 'soqlParserJs';
15+
const LWC_STANDALONE_DIR = 'dist/lwc';
16+
const LWC_STANDALONE_FILE = `${LWC_STANDALONE_DIR}/${LWC_COMPONENT_NAME}.js`;
17+
const LWC_PACKAGE_DIR = 'dist/lwc-packaged';
18+
const LWC_PACKAGE_BUNDLE_DIR = `${LWC_PACKAGE_DIR}/lwc/${LWC_COMPONENT_NAME}`;
19+
20+
const targets = {
21+
esm: {
22+
entryPoints: ['src/index.ts'],
23+
outfile: 'dist/esm/index.mjs',
24+
format: 'esm',
25+
},
26+
lwc: {
27+
entryPoints: ['src/index.ts'],
28+
outfile: LWC_STANDALONE_FILE,
29+
format: 'esm',
30+
// LWC's compiler doesn't support certain ES2022 syntax
31+
target: 'es2020',
32+
},
33+
cjs: {
34+
entryPoints: ['src/index.ts'],
35+
outfile: 'dist/cjs/index.js',
36+
format: 'cjs',
37+
},
38+
cli: {
39+
entryPoints: ['cli/index.ts'],
40+
outfile: 'dist/cli/index.js',
41+
format: 'cjs',
42+
platform: 'node',
43+
},
44+
};
45+
46+
const requested = process.argv[2];
47+
const names = requested ? [requested] : Object.keys(targets);
48+
49+
for (const name of names) {
50+
if (!targets[name]) {
51+
console.error(`Unknown build target: ${name}. Valid targets: ${Object.keys(targets).join(', ')}`);
52+
process.exit(1);
53+
}
54+
}
55+
56+
await Promise.all(
57+
names.map(async name => {
58+
await build({
59+
bundle: true,
60+
target: 'es2022',
61+
banner: { js: banner },
62+
minify: true,
63+
...targets[name],
64+
});
65+
if (name === 'lwc') {
66+
writeLwcPackage();
67+
}
68+
}),
69+
);
70+
71+
function writeLwcPackage() {
72+
const apiVersion = pkg.salesforceApiVersion;
73+
if (!apiVersion) {
74+
throw new Error('Missing "salesforceApiVersion" in package.json — required for LWC package metadata.');
75+
}
76+
mkdirSync(LWC_PACKAGE_BUNDLE_DIR, { recursive: true });
77+
copyFileSync(LWC_STANDALONE_FILE, `${LWC_PACKAGE_BUNDLE_DIR}/${LWC_COMPONENT_NAME}.js`);
78+
79+
const packageXml = `<?xml version="1.0" encoding="UTF-8"?>
80+
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
81+
<types>
82+
<members>${LWC_COMPONENT_NAME}</members>
83+
<name>LightningComponentBundle</name>
84+
</types>
85+
<version>${apiVersion}</version>
86+
</Package>
87+
`;
88+
const metaXml = `<?xml version="1.0" encoding="UTF-8"?>
89+
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
90+
<apiVersion>${apiVersion}</apiVersion>
91+
<isExposed>false</isExposed>
92+
</LightningComponentBundle>
93+
`;
94+
writeFileSync(`${LWC_PACKAGE_DIR}/package.xml`, packageXml);
95+
writeFileSync(`${LWC_PACKAGE_BUNDLE_DIR}/${LWC_COMPONENT_NAME}.js-meta.xml`, metaXml);
96+
writeLwcZip();
97+
}
98+
99+
function writeLwcZip() {
100+
const zipName = `soql-parser-js-lwc-v${pkg.version}.zip`;
101+
const zipPath = `dist/${zipName}`;
102+
rmSync(zipPath, { force: true });
103+
execFileSync('zip', ['-r', `../${zipName}`, '.'], { cwd: LWC_PACKAGE_DIR, stdio: 'inherit' });
104+
}

test/test-cases-for-is-valid.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,5 +494,10 @@ WHERE
494494
isValid: true,
495495
},
496496
{ testCase: 161, soql: `SELECT Name, Id FROM Contact USING SCOPE mru ORDER BY Name ASC`, isValid: true },
497+
{ testCase: 162, soql: `SELECT Id FROM Account USING SCOPE scopingRule`, isValid: true },
498+
{ testCase: 163, soql: `SELECT Id FROM Account USING SCOPE mine_and_my_groups`, isValid: true },
499+
{ testCase: 164, soql: `SELECT Id FROM Account USING SCOPE my_territory`, isValid: true },
500+
{ testCase: 165, soql: `SELECT Id FROM Account USING SCOPE my_team_territory`, isValid: true },
501+
{ testCase: 166, soql: `SELECT Id, Name FROM Account USING SCOPE myRule`, isValid: true },
497502
];
498503
export default testCases;

0 commit comments

Comments
 (0)