Repository: opencomponents/oc (js)

Issue:
A high severity vulnerability introduced in oc
Hi, a vulnerability https://snyk.io/vuln/SNYK-JS-MERGE-1040469 is introduced in oc via:
●  oc@0.48.19 ➔ watch@1.0.2 ➔ exec-sh@0.2.2 ➔ merge@1.2.1

However, **_watch_** is a legacy package, which has not been maintained for about 4 years.
Is it possible to migrate **_watch_** to other package or remove it to remediate this vulnerability?

I noticed a migration record in other js repo for **_watch_**:

● in @google/clasp, version 2.3.2 ➔ 2.4.0, Migrate from watch to chokidar via [commit](https://github.com/google/clasp/commit/003d422b5b5fdae4ece6eb6c24db2591b53fc956)
● in forever-monitor, version 1.5.2 ➔ 1.6.0, Migrate from watch to chokidar via [commit](https://github.com/foreversd/forever-monitor/commit/12e35fcd17f0e7beace9a62dfd949300fe4fb371)

Are there any efforts planned that would remediate this vulnerability or migrate **_watch_**?

Thanks
; )

Pull request:
Use chokidar
Closes #1197 

Use chokidar in favor of watch, since the latter is unmantained. I disabled `polling` (although it's disabled by default) since for our use case I don't think it's needed and should be faster ([check here](https://github.com/paulmillr/chokidar#performance)). This setup worked the same in local with a couple of components, so should be fine.

I also took the opportunity to upgrade devDependencies

Patch:
diff --git a/package.json b/package.json
index 8352312d..6b4c2690 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "oc",
-  "version": "0.48.22",
+  "version": "0.48.23",
   "description": "A framework for developing and distributing html components",
   "main": "./src/index.js",
   "bin": {
@@ -44,17 +44,17 @@
     "oc"
   ],
   "devDependencies": {
-    "chai": "4.2.0",
-    "chalk": "^2.1.0",
-    "glob": "^7.1.2",
-    "husky": "^7.0.0",
+    "chai": "4.3.4",
+    "chalk": "4.1.2",
+    "glob": "7.1.7",
+    "husky": "7.0.2",
     "injectr": "0.5.1",
-    "lint-staged": "^11.1.2",
-    "minimist": "^1.2.0",
+    "lint-staged": "11.1.2",
+    "minimist": "1.2.5",
     "mocha": "7.0.1",
-    "node-emoji": "^1.8.1",
+    "node-emoji": "1.11.0",
     "oc-template-es6-compiler": "1.1.8",
-    "prettier-eslint-cli": "5.0.0",
+    "prettier-eslint-cli": "5.0.1",
     "semver-sort": "0.0.4",
     "simple-git": "^1.77.0",
     "sinon": "7.5.0"
@@ -65,6 +65,7 @@
     "basic-auth-connect": "^1.0.0",
     "body-parser": "1.19.0",
     "builtin-modules": "^3.0.0",
+    "chokidar": "^3.5.2",
     "colors": "1.3.3",
     "cross-spawn": "7.0.1",
     "dependency-graph": "0.8.0",
@@ -101,7 +102,6 @@
     "stringformat": "0.0.5",
     "targz": "1.0.1",
     "try-require": "^1.2.1",
-    "watch": "1.0.2",
     "yargs": "13.3.0"
   }
 }
diff --git a/src/cli/domain/watch.js b/src/cli/domain/watch.js
index 31ca4fe4..8d497ec2 100644
--- a/src/cli/domain/watch.js
+++ b/src/cli/domain/watch.js
@@ -1,33 +1,29 @@
 'use strict';
 
 const path = require('path');
-const watch = require('watch');
+const chokidar = require('chokidar');
 
 const settings = require('../../resources/settings');
 
 module.exports = function(dirs, baseDir, changed) {
-  try {
-    watch.watchTree(
-      path.resolve(baseDir),
-      {
-        interval: 0.5,
-        ignoreUnreadableDir: true,
-        ignoreDotFiles: false,
-        filter: fileOrDir =>
-          settings.filesToIgnoreOnDevWatch.test(fileOrDir) === false
-      },
-      (fileName, currentStat, previousStat) => {
-        if (!!currentStat || !!previousStat) {
-          const componentDir = dirs.find(dir =>
-            Boolean(fileName.match(escapeRegularExpression(dir + path.sep)))
-          );
-          changed(null, fileName, componentDir);
-        }
-      }
+  const watcher = chokidar.watch(path.resolve(baseDir), {
+    ignored: settings.filesToIgnoreOnDevWatch,
+    persistent: true,
+    ignoreInitial: true,
+    usePolling: false
+  });
+  const onChange = fileName => {
+    const componentDir = dirs.find(dir =>
+      Boolean(fileName.match(escapeRegularExpression(dir + path.sep)))
     );
-  } catch (err) {
-    changed(err);
-  }
+    changed(null, fileName, componentDir);
+  };
+
+  watcher
+    .on('add', onChange)
+    .on('change', onChange)
+    .on('unlink', onChange)
+    .on('error', changed);
 };
 
 function escapeRegularExpression(text) {
diff --git a/src/components/oc-client/package.json b/src/components/oc-client/package.json
index e4e6a139..b9ee2720 100644
--- a/src/components/oc-client/package.json
+++ b/src/components/oc-client/package.json
@@ -1,7 +1,7 @@
 {
   "name": "oc-client",
   "description": "The OpenComponents client-side javascript client",
-  "version": "0.48.22",
+  "version": "0.48.23",
   "repository": "https://github.com/opencomponents/oc/tree/master/components/oc-client",
   "author": "Matteo Figus <matteofigus@gmail.com>",
   "oc": {


Test patch:
diff --git a/test/unit/cli-domain-watch.js b/test/unit/cli-domain-watch.js
index 9534f7de..583772f3 100644
--- a/test/unit/cli-domain-watch.js
+++ b/test/unit/cli-domain-watch.js
@@ -6,25 +6,15 @@ const sinon = require('sinon');
 
 describe('cli : domain : watch', () => {
   const execute = (fileChanged, separator, cb) => {
-    class Stats {
-      constructor(settings) {
-        this.stuff = settings.stuff;
-      }
-    }
-
     const watch = injectr('../../src/cli/domain/watch.js', {
       path: {
         resolve: x => x,
         sep: separator
       },
-      watch: {
-        watchTree: sinon
-          .stub()
-          .yields(
-            fileChanged,
-            new Stats('some stuff about current state'),
-            new Stats('previous stuff about the previous state')
-          )
+      chokidar: {
+        watch: sinon.stub().returns({
+          on: sinon.stub().yields(fileChanged)
+        })
       }
     });