Add 'eslint-plugin-header' to check license

Add eslint rule to verify that source files have the required license
header.
Convert `.eslintrc.json` to `.eslintrc.cjs` to add header plugin
configuration.

Gitlab: #45
Change-Id: I7a2331d68a418be35e6bea425eede92087451980
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..537f3e4
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program.  If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+const header = [
+  'error',
+  'block',
+  [
+    '',
+    {
+      pattern: ' \\* Copyright \\(C\\) (\\d{4}|(\\d{4}-\\d{4})) Savoir-faire Linux Inc\\.',
+      template: ` * Copyright (C) ${new Date().getFullYear()} Savoir-faire Linux Inc.`,
+    },
+    ' *',
+    ' * This program is free software; you can redistribute it and/or modify',
+    ' * it under the terms of the GNU Affero General Public License as',
+    ' * published by the Free Software Foundation; either version 3 of the',
+    ' * License, or (at your option) any later version.',
+    ' *',
+    ' * This program is distributed in the hope that it will be useful,',
+    ' * but WITHOUT ANY WARRANTY; without even the implied warranty of',
+    ' * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the',
+    ' * GNU Affero General Public License for more details.',
+    ' *',
+    ' * You should have received a copy of the GNU Affero General Public',
+    ' * License along with this program.  If not, see',
+    ' * <https://www.gnu.org/licenses/>.',
+    ' ',
+  ],
+];
+
+module.exports = {
+  env: {
+    browser: true,
+    es2021: true,
+    node: true,
+  },
+  extends: [
+    'eslint:recommended',
+    'plugin:@typescript-eslint/recommended',
+    /* TODO: Enable these configs once the project is fully converted to typescript */
+    // "plugin:@typescript-eslint/recommended-requiring-type-checking",
+    // "plugin:@typescript-eslint/strict",
+    'prettier',
+  ],
+  ignorePatterns: ['node_modules/', 'dist/', 'daemon/', 'test/'],
+  overrides: [
+    {
+      files: ['**/*.test.{js,jsx,ts,tsx}'],
+      env: {
+        jest: true,
+      },
+    },
+  ],
+  parser: '@typescript-eslint/parser',
+  parserOptions: {
+    ecmaVersion: 'latest',
+    sourceType: 'module',
+  },
+  plugins: ['@typescript-eslint', 'header', 'simple-import-sort', 'unused-imports'],
+  rules: {
+    '@typescript-eslint/ban-ts-comment': 'off',
+    '@typescript-eslint/no-empty-function': 'off',
+    '@typescript-eslint/no-explicit-any': 'off',
+    '@typescript-eslint/no-unused-vars': 'off',
+    eqeqeq: ['warn', 'smart'],
+    'header/header': header,
+    'no-constant-condition': ['error', { checkLoops: false }],
+    'simple-import-sort/exports': 'warn',
+    'simple-import-sort/imports': 'warn',
+    'unused-imports/no-unused-imports': 'error',
+    'unused-imports/no-unused-vars': [
+      'warn',
+      { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
+    ],
+  },
+};
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 323d257..0000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
-  "env": {
-    "browser": true,
-    "es2021": true,
-    "node": true
-  },
-  "extends": [
-    "eslint:recommended",
-    "plugin:@typescript-eslint/recommended",
-    /* TODO: Enable these configs once the project is fully converted to typescript */
-    // "plugin:@typescript-eslint/recommended-requiring-type-checking",
-    // "plugin:@typescript-eslint/strict",
-    "prettier"
-  ],
-  "ignorePatterns": ["node_modules/", "dist/", "daemon/", "test/"],
-  "overrides": [
-    {
-      "files": ["**/*.test.{js,jsx,ts,tsx}"],
-      "env": {
-        "jest": true
-      }
-    }
-  ],
-  "parser": "@typescript-eslint/parser",
-  "parserOptions": {
-    "ecmaVersion": "latest",
-    "sourceType": "module"
-  },
-  "plugins": ["@typescript-eslint", "simple-import-sort", "unused-imports"],
-  "rules": {
-    "@typescript-eslint/ban-ts-comment": "off",
-    "@typescript-eslint/no-empty-function": "off",
-    "@typescript-eslint/no-explicit-any": "off",
-    "@typescript-eslint/no-unused-vars": "off",
-    "eqeqeq": ["warn", "smart"],
-    "no-constant-condition": ["error", { "checkLoops": false }],
-    "simple-import-sort/exports": "warn",
-    "simple-import-sort/imports": "warn",
-    "unused-imports/no-unused-imports": "error",
-    "unused-imports/no-unused-vars": [
-      "warn",
-      { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
-    ]
-  }
-}
diff --git a/client/.eslintrc.json b/client/.eslintrc.json
index 4188353..e94691b 100644
--- a/client/.eslintrc.json
+++ b/client/.eslintrc.json
@@ -4,7 +4,11 @@
       "version": "detect"
     }
   },
-  "extends": ["plugin:react/recommended", "plugin:react-hooks/recommended", "../.eslintrc.json"],
+  "extends": [
+    "plugin:react/recommended",
+    "plugin:react-hooks/recommended",
+    "../.eslintrc.cjs"
+  ],
   "rules": {
     "react-hooks/exhaustive-deps": "error",
     "react/display-name": "off",
diff --git a/package-lock.json b/package-lock.json
index dbbfc9a..f3457a3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -44,6 +44,7 @@
         "cypress": "^10.8.0",
         "eslint": "^8.23.1",
         "eslint-config-prettier": "^8.5.0",
+        "eslint-plugin-header": "^3.1.1",
         "eslint-plugin-simple-import-sort": "^8.0.0",
         "eslint-plugin-unused-imports": "^2.0.0",
         "husky": "^8.0.0",
@@ -7001,6 +7002,15 @@
         "eslint": ">=7.0.0"
       }
     },
+    "node_modules/eslint-plugin-header": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
+      "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
+      "dev": true,
+      "peerDependencies": {
+        "eslint": ">=7.7.0"
+      }
+    },
     "node_modules/eslint-plugin-react": {
       "version": "7.31.8",
       "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz",
@@ -20344,6 +20354,13 @@
       "dev": true,
       "requires": {}
     },
+    "eslint-plugin-header": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
+      "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
+      "dev": true,
+      "requires": {}
+    },
     "eslint-plugin-react": {
       "version": "7.31.8",
       "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz",
diff --git a/package.json b/package.json
index e67c2cf..eafa447 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
     "start:prod": "NODE_ENV=production node dist/bundle.js"
   },
   "lint-staged": {
-    "**/*.{ts,tsx,js,jsx,json}": [
+    "**/*.{ts,tsx,js,jsx,cjs}": [
       "eslint --fix",
       "prettier --write"
     ]
@@ -60,6 +60,7 @@
     "cypress": "^10.8.0",
     "eslint": "^8.23.1",
     "eslint-config-prettier": "^8.5.0",
+    "eslint-plugin-header": "^3.1.1",
     "eslint-plugin-simple-import-sort": "^8.0.0",
     "eslint-plugin-unused-imports": "^2.0.0",
     "husky": "^8.0.0",