Skip to content

Commit

Permalink
chore: add more checks for bundling
Browse files Browse the repository at this point in the history
  • Loading branch information
mingxuanzhangsfdx committed Oct 3, 2024
1 parent 0b8aede commit f0ed499
Show file tree
Hide file tree
Showing 8 changed files with 710 additions and 9 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/testCommitExceptMain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ on:
jobs:
unit-tests:
uses: salesforcecli/github-workflows/.github/workflows/unitTest.yml@main
test-bundle:
runs-on: ubuntu-latest
needs: unit-tests
name: test bundling
steps:
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: yarn
- uses: salesforcecli/github-workflows/.github/actions/yarnInstallWithRetries@main
- name: Build the project
run: yarn build
- name: check if bundling runs into failures
run: node scripts/testEsbuild.js
xNuts:
needs: unit-tests
name: external NUTs
Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"

yarn lint-staged
node ./scripts/scanTs.js
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
"chai": "^4.5.0",
"commitlint": "^18.6.1",
"cz-conventional-changelog": "^3.3.0",
"esbuild": "^0.24.0",
"esbuild-plugin-pino": "^2.2.0",
"esbuild-plugin-tsc": "^0.4.0",
"npm-dts": "^1.3.13",
"ts-morph": "^23.0.0",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-header": "^3.0.0",
Expand Down
32 changes: 32 additions & 0 deletions scripts/esbuild.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* NOTE: This file does NOT really generate a bundle version of apex-node
* apex-node is bundled directly in salesforcedx-vscode
* The file is only used to detect any potential risks to esbuild.
**/
const { build } = require('esbuild');

const sharedConfig = {
bundle: true,
format: 'cjs',
platform: 'node',
external: [
'jsonpath'
], // The whitelist of dependencies that are not bundle-able
keepNames: true,
plugins: [
],
supported: {
'dynamic-import': false
},
logOverride: {
'unsupported-dynamic-import': 'error',
},
};

(async () => {
await build({
...sharedConfig,
entryPoints: ['./lib/src/index.js'],
outdir: 'dist'
});
})();
51 changes: 51 additions & 0 deletions scripts/scanTs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const fs = require('fs');
const path = require('path');
const { Project, CallExpression } = require('ts-morph');

const SRC_DIR = path.join(__dirname, '..', 'src');
const project = new Project({
tsConfigFilePath: path.join(__dirname, '..', 'tsconfig.json'),
});

let detected = false;

const scanDirectory = (dir) => {
const files = fs.readdirSync(dir);
files.forEach((file) => {
const fullPath = path.join(dir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
scanDirectory(fullPath);
} else if (fullPath.endsWith('.ts')) {
analyzeFile(fullPath);
}
});
};

// This function will detect all the usages of fs.read* and send warnings with the location of the usage
const analyzeFile = (filePath) => {
const srcFile = project.addSourceFileAtPath(filePath);
const funcCalls = srcFile.getDescendantsOfKind(CallExpression);

funcCalls.forEach((callExpression) => {
const exp = callExpression.getExpression();
if (exp.getText().startsWith('fs.read')) {
detected = true;
console.warn(
`Warning: Usage of "${exp.getText()}" in file "${filePath}" at line ${callExpression.getStartLineNumber()}.\n`
);
}
});
};

scanDirectory(SRC_DIR);

if (detected) {
console.log('The warnings above do not mean the usages are wrong.');
console.log(`Avoid reading local artifacts with "fs.read*" since esbuild cannot bundle the artifacts together.`);
console.log('Consider using import instead or reach out to IDEx Foundations team');
} else {
console.log('No fs.read* usages detected.');
}

console.log('Scan complete');
20 changes: 20 additions & 0 deletions scripts/testEsbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const { exec } = require('child_process');

const commandToRun = 'node ./scripts/esbuild.config.js';

// Run the command
exec(commandToRun, (error, stdout, stderr) => {
// Combine stdout and stderr to check the entire output
const output = `${stdout}\n${stderr}`;
if(error) {
console.error(stderr);
process.exit(1); // Exit with an error code
}
// Check if the output contains the error string
if (output.includes('[require-resolve-not-external]')) {
console.error('Error: A dependency that has to be externalized in esbuild process is found. Please resolve it!');
process.exit(1); // Exit with an error code
} else {
process.exit(0); // Exit with success code
}
});
4 changes: 4 additions & 0 deletions src/tests/testService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ import { Transform } from 'stream';
import { pipeline } from 'node:stream/promises';
import { createWriteStream } from 'node:fs';

/**
* The library jsonpath that bfj depends on cannot be bundled through esbuild.
* Please pay attention whenever you deal with bfj
*/
// eslint-disable-next-line @typescript-eslint/no-var-requires
const bfj = require('bfj');

Expand Down
Loading

0 comments on commit f0ed499

Please sign in to comment.