@govtechsg/oobee 0.10.90 → 0.10.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -755,13 +755,36 @@ generateJsonFiles = false) => {
755
755
  const browserChannel = getBrowserToRun(randomToken, BrowserTypes.CHROME, false).browserToRun;
756
756
  // Should consider refactor constants.userDataDirectory to be a parameter in future
757
757
  await retryFunction(() => writeSummaryPdf(storagePath, pagesScanned.length, 'summary', browserChannel, constants.userDataDirectory), 1);
758
+ // Suppress uncaught EPERM errors from lingering Crawlee async lock-file operations
759
+ // (Windows holds mandatory file locks; Crawlee may still attempt mkdir on .json.lock
760
+ // files after the crawl has finished). Without this, Node crashes with uncaughtException.
761
+ const crawleeEpermHandler = (err) => {
762
+ if (err.code === 'EPERM' && err.message?.includes('crawlee')) {
763
+ consoleLogger.info(`Suppressed lingering Crawlee storage error: ${err.message}`);
764
+ return;
765
+ }
766
+ // Re-throw non-crawlee EPERM errors so they aren't silently swallowed
767
+ throw err;
768
+ };
769
+ process.on('uncaughtException', crawleeEpermHandler);
770
+ process.on('unhandledRejection', crawleeEpermHandler);
758
771
  // Brief delay to allow lingering async crawlee storage operations to flush
759
- await new Promise(resolve => setTimeout(resolve, 3000));
772
+ await new Promise(resolve => setTimeout(resolve, process.platform === 'win32' ? 5000 : 3000));
773
+ const crawleePath = path.join(storagePath, 'crawlee');
760
774
  try {
761
- await fs.promises.rm(path.join(storagePath, 'crawlee'), { recursive: true, force: true });
775
+ await fs.promises.rm(crawleePath, { recursive: true, force: true });
762
776
  }
763
777
  catch (error) {
764
- // Silently ignore folder may already be gone or still locked
778
+ // On Windows, retry once after a delay if the folder is still locked
779
+ if (process.platform === 'win32') {
780
+ await new Promise(resolve => setTimeout(resolve, 3000));
781
+ try {
782
+ await fs.promises.rm(crawleePath, { recursive: true, force: true });
783
+ }
784
+ catch {
785
+ // Best-effort cleanup — leave the folder; report generation continues
786
+ }
787
+ }
765
788
  }
766
789
  try {
767
790
  await fs.promises.rm(path.join(storagePath, 'pdfs'), { recursive: true, force: true });
@@ -825,6 +848,8 @@ generateJsonFiles = false) => {
825
848
  }
826
849
  if (process.env.RUNNING_FROM_PH_GUI || process.env.OOBEE_VERBOSE)
827
850
  console.log('Report generated successfully');
851
+ process.removeListener('uncaughtException', crawleeEpermHandler);
852
+ process.removeListener('unhandledRejection', crawleeEpermHandler);
828
853
  return ruleIdJson;
829
854
  };
830
855
  export { writeHTML, compressJsonFileStreaming, convertItemsToReferences, flattenAndSortResults, populateScanPagesDetail, sendWcagBreakdownToSentry, getWcagPassPercentage, getProgressPercentage, getIssuesPercentage, itemTypeDescription, oobeeAiHtmlETL, oobeeAiRules, formatAboutStartTime, };
@@ -3,7 +3,7 @@
3
3
  * DO NOT EDIT MANUALLY. Re-generate with: node dist/generateOobeeClientScanner.js
4
4
  *
5
5
  * Embedded at generation time:
6
- * App version : 0.10.90
6
+ * App version : 0.10.91
7
7
  * Sentry DSN : (from OOBEE_SENTRY_DSN env var or constants.ts default)
8
8
  * Sentry SDK : @sentry/browser 9.47.1 (loaded from CDN at runtime)
9
9
  *
@@ -34883,7 +34883,7 @@
34883
34883
  // ── Sentry browser telemetry (Sentry JS SDK, loaded from CDN) ────────────
34884
34884
 
34885
34885
  var _oobeeSentryDsn = "https://3b8c7ee46b06f33815a1301b6713ebc3@o4509047624761344.ingest.us.sentry.io/4509327783559168";
34886
- var _oobeeAppVersion = "0.10.90";
34886
+ var _oobeeAppVersion = "0.10.91";
34887
34887
  var _oobeeSentryVersion = "9.47.1";
34888
34888
  var _oobeeSentryInitialized = false;
34889
34889
  var _oobeeSentryLoadPromise = null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@govtechsg/oobee",
3
3
  "main": "dist/npmIndex.js",
4
- "version": "0.10.90",
4
+ "version": "0.10.91",
5
5
  "type": "module",
6
6
  "author": "Government Technology Agency <info@tech.gov.sg>",
7
7
  "bin": {
@@ -1020,13 +1020,36 @@ const generateArtifacts = async (
1020
1020
  1,
1021
1021
  );
1022
1022
 
1023
+ // Suppress uncaught EPERM errors from lingering Crawlee async lock-file operations
1024
+ // (Windows holds mandatory file locks; Crawlee may still attempt mkdir on .json.lock
1025
+ // files after the crawl has finished). Without this, Node crashes with uncaughtException.
1026
+ const crawleeEpermHandler = (err: Error & { code?: string }) => {
1027
+ if (err.code === 'EPERM' && err.message?.includes('crawlee')) {
1028
+ consoleLogger.info(`Suppressed lingering Crawlee storage error: ${err.message}`);
1029
+ return;
1030
+ }
1031
+ // Re-throw non-crawlee EPERM errors so they aren't silently swallowed
1032
+ throw err;
1033
+ };
1034
+ process.on('uncaughtException', crawleeEpermHandler);
1035
+ process.on('unhandledRejection', crawleeEpermHandler);
1036
+
1023
1037
  // Brief delay to allow lingering async crawlee storage operations to flush
1024
- await new Promise(resolve => setTimeout(resolve, 3000));
1038
+ await new Promise(resolve => setTimeout(resolve, process.platform === 'win32' ? 5000 : 3000));
1025
1039
 
1040
+ const crawleePath = path.join(storagePath, 'crawlee');
1026
1041
  try {
1027
- await fs.promises.rm(path.join(storagePath, 'crawlee'), { recursive: true, force: true });
1042
+ await fs.promises.rm(crawleePath, { recursive: true, force: true });
1028
1043
  } catch (error) {
1029
- // Silently ignore folder may already be gone or still locked
1044
+ // On Windows, retry once after a delay if the folder is still locked
1045
+ if (process.platform === 'win32') {
1046
+ await new Promise(resolve => setTimeout(resolve, 3000));
1047
+ try {
1048
+ await fs.promises.rm(crawleePath, { recursive: true, force: true });
1049
+ } catch {
1050
+ // Best-effort cleanup — leave the folder; report generation continues
1051
+ }
1052
+ }
1030
1053
  }
1031
1054
 
1032
1055
  try {
@@ -1112,6 +1135,9 @@ const generateArtifacts = async (
1112
1135
  if (process.env.RUNNING_FROM_PH_GUI || process.env.OOBEE_VERBOSE)
1113
1136
  console.log('Report generated successfully');
1114
1137
 
1138
+ process.removeListener('uncaughtException', crawleeEpermHandler);
1139
+ process.removeListener('unhandledRejection', crawleeEpermHandler);
1140
+
1115
1141
  return ruleIdJson;
1116
1142
  };
1117
1143