Browse Source

Organise code, add formatting rules

Craig Fletcher 1 year ago
parent
commit
1152b6ff63
7 changed files with 1072 additions and 153 deletions
  1. 37 0
      eslint.config.js
  2. 826 0
      package-lock.json
  3. 2 0
      package.json
  4. 68 0
      src/lib/dependencies.js
  5. 84 0
      src/lib/options.js
  6. 28 0
      src/lib/package-files.js
  7. 27 153
      src/sync-package-json-deps.js

+ 37 - 0
eslint.config.js

@@ -0,0 +1,37 @@
+import js from '@eslint/js'
+
+export default [
+  js.configs.recommended,
+  {
+    rules: {
+      /**
+       * Custom rules.
+       * docs: https://eslint.org/docs/rules
+       */
+      'quotes': ['error', 'double'],
+      'indent': [
+        'error', 2, { 'SwitchCase': 1 },
+      ],
+      'no-multi-spaces': 'error',
+      'prefer-const': 'error',
+      'array-bracket-newline': [
+        'error', {
+          minItems: 3,
+          multiline: true,
+        },
+      ],
+      'array-element-newline': ['error', 'consistent'],
+      'comma-dangle': ['error', 'always-multiline'],
+      'no-process-env': 'off',
+      'no-undef': 'error',
+      'no-multiple-empty-lines': [
+        'error', {
+          'max': 1,
+        },
+      ],
+      'no-var': 'error',
+      'object-curly-spacing': ['error', 'always'],
+      'semi': ['error', 'never'],
+    },
+  },
+]

File diff suppressed because it is too large
+ 826 - 0
package-lock.json


+ 2 - 0
package.json

@@ -18,6 +18,8 @@
     "semver": "^7.6.3"
   },
   "devDependencies": {
+    "@eslint/js": "^9.15.0",
+    "eslint": "^9.15.0",
     "nexe": "^4.0.0-rc.6"
   }
 }

+ 68 - 0
src/lib/dependencies.js

@@ -0,0 +1,68 @@
+const semver = require("semver");
+const {
+  getPackageFiles,
+  readPackageFile,
+  writePackageFile
+} = require("./package-files.js");
+
+function collectDependencies(packageFiles) {
+  const allDependencies = {};
+
+  packageFiles.forEach(file => {
+    const pkg = readPackageFile(file);
+    ["dependencies", "devDependencies", "peerDependencies"].forEach(key => {
+      if (pkg[key]) {
+        for (const [dep, version] of Object.entries(pkg[key])) {
+          if (!allDependencies[dep]) {
+            allDependencies[dep] = [];
+          }
+          if (!allDependencies[dep].includes(version)) {
+            allDependencies[dep].push(version);
+          }
+        }
+      }
+    });
+  });
+
+  return allDependencies;
+}
+
+function findHighestVersion(versions) {
+  return versions.sort(semver.rcompare)[0];
+}
+
+function updateDependencies(
+  packageFiles,
+  allDependencies,
+  { write, tabWidth }
+) {
+  let updated = false;
+  packageFiles.forEach(file => {
+    const pkg = readPackageFile(file);
+
+    ["dependencies", "devDependencies", "peerDependencies"].forEach(key => {
+      if (pkg[key]) {
+        for (const dep of Object.keys(pkg[key])) {
+          const highestVersion = findHighestVersion(allDependencies[dep]);
+          if (pkg[key][dep] !== highestVersion) {
+            pkg[key][dep] = highestVersion;
+            updated = true;
+          }
+        }
+      }
+    });
+
+    if (updated && write) {
+      writePackageFile(file, pkg, tabWidth);
+      console.log(`Updated ${file}`);
+    }
+  });
+  if (updated && write) {
+    console.log("Dependency versions synchronized.");
+  }
+}
+module.exports = {
+  collectDependencies,
+  findHighestVersion,
+  updateDependencies
+};

+ 84 - 0
src/lib/options.js

@@ -0,0 +1,84 @@
+const allowedOptions = {
+  tabWidth: {
+    description: "Tab width in spaces, passed to JSON.stringify for output.",
+    flags: ["-tw", "--tab-width"],
+    numArgs: 1,
+    default: 2
+  },
+  write: {
+    description: "Write changes to files.",
+    flags: ["-w", "--write"],
+    numArgs: 0,
+    default: false
+  },
+  help: {
+    description: "Prints the help message, options and usage info then exits.",
+    flags: ["-h", "--help"],
+    numArgs: 0,
+    default: false
+  }
+};
+
+const optionNames = Object.keys(allowedOptions);
+
+function getOptName(flag) {
+  return optionNames.find(optName =>
+    allowedOptions[optName].flags.includes(flag)
+  );
+}
+
+function printHelpMessage() {
+  console.log(
+    "sync-package-json-deps: a script to find and fix out-of-sync dependencies in package.json files.\n"
+  );
+  console.log("Usage: script.js [options] [glob patterns]");
+  console.log(
+    "Example: sync-package-json-deps.js -w --tab-width 4 './packages/*/package.json' 'package.json'\n"
+  );
+  console.log("Allowed options:");
+  optionNames.forEach(optionName => {
+    const option = allowedOptions[optionName];
+    console.log(`${optionName}: ${option.description}`);
+    console.log(`flags: ${option.flags}`);
+    console.log(`number of arguments: ${option.numArgs}`);
+    console.log(`default: ${option.default}\n`);
+  });
+}
+
+function mergeOptionsAndDefaults(options) {
+  return optionNames.reduce((merged, optionName) => {
+    const option = allowedOptions[optionName];
+    const userValue =
+      option.numArgs > 1 ? options[optionName] : options[optionName]?.[0];
+    const optionValue = userValue || option.default;
+    return { ...merged, [optionName]: optionValue };
+  }, {});
+}
+
+function parseArgs(rest, opts = {}, globs = []) {
+  if (!rest || rest.length === 0) return { opts, globs };
+  const current = rest[0];
+
+  if (current.startsWith("-")) {
+    const optName = getOptName(current);
+    if (!optName) {
+      printHelpMessage();
+      throw new Error(`Unrecognised option: ${current}`);
+    }
+    const opt = allowedOptions[optName];
+    const value = opt.numArgs > 0 ? rest.slice(1, opt.numArgs + 1) : [true];
+    const nextRest = rest.slice((opt.numArgs || 0) + 1);
+    return parseArgs(nextRest, { ...opts, [optName]: value }, globs);
+  }
+
+  return parseArgs(rest.slice(1), opts, [...globs, current]);
+}
+
+module.exports = {
+  optionNames,
+  allowedOptions,
+  getOptName,
+  printHelpMessage,
+  mergeOptionsAndDefaults,
+  parseArgs
+};

+ 28 - 0
src/lib/package-files.js

@@ -0,0 +1,28 @@
+const fs = require("fs");
+const path = require("path");
+const glob = require("glob");
+const semver = require("semver");
+
+function getPackageFiles(globs) {
+  const files = new Set();
+  globs.forEach(pattern => {
+    glob.sync(pattern).forEach(file => files.add(file));
+  });
+  return [...files];
+}
+
+function readPackageFile(filePath) {
+  const content = fs.readFileSync(filePath, "utf8");
+  return JSON.parse(content);
+}
+
+function writePackageFile(filePath, content, tabWidth) {
+  const json = JSON.stringify(content, null, Number(tabWidth));
+  fs.writeFileSync(filePath, json, "utf8");
+}
+
+module.exports = {
+  getPackageFiles,
+  readPackageFile,
+  writePackageFile
+};

+ 27 - 153
src/sync-package-json-deps.js

@@ -1,127 +1,36 @@
 #!/usr/bin/env node
 
-const fs = require('fs');
-const path = require('path');
-const glob = require('glob');
-const semver = require('semver');
-
-const allowedOptions = {
-  tabWidth: {
-    description: "Tab width in spaces, passed to JSON.stringify for output.",
-    flags: ["-tw", "--tab-width"],
-    numArgs: 1,
-    default: 2
-  },
-  write: {
-    description: "Write changes to files.",
-    flags: ["-w", "--write"],
-    numArgs: 0,
-    default: false
-  },
-  help: {
-    description: "Prints the help message, options and usage info then exits.",
-    flags: ["-h", "--help"],
-    numArgs: 0,
-    default: false
-  },
-}
-
-const optionNames = Object.keys(allowedOptions)
-
-function printHelpMessage() {
-  console.log("sync-package-json-deps: a script to find and fix out-of-sync dependencies in package.json files.\n")
-  console.log("Usage: script.js [options] [glob patterns]")
-  console.log("Example: sync-package-json-deps.js -w --tab-width 4 './packages/*/package.json' 'package.json'\n")
-  console.log("Allowed options:")
-  optionNames.forEach(optionName => {
-    const option = allowedOptions[optionName]
-    console.log(`${optionName}: ${option.description}`)
-    console.log(`flags: ${option.flags}`)
-    console.log(`number of arguments: ${option.numArgs}`)
-    console.log(`default: ${option.default}\n`)
-  })
-}
-
-function getPackageFiles(globs) {
-  const files = new Set();
-  globs.forEach((pattern) => {
-    glob.sync(pattern).forEach((file) => files.add(file));
-  });
-  return [...files];
-}
-
-function readPackageFile(filePath) {
-  const content = fs.readFileSync(filePath, 'utf8');
-  return JSON.parse(content);
-}
-
-function writePackageFile(filePath, content, tabWidth) {
-  const json = JSON.stringify(content, null, Number(tabWidth));
-  fs.writeFileSync(filePath, json, 'utf8');
-}
-
-function collectDependencies(packageFiles) {
-  const allDependencies = {};
-
-  packageFiles.forEach((file) => {
-    const pkg = readPackageFile(file);
-    ['dependencies', 'devDependencies', 'peerDependencies'].forEach((key) => {
-      if (pkg[key]) {
-        for (const [dep, version] of Object.entries(pkg[key])) {
-          if (!allDependencies[dep]) {
-            allDependencies[dep] = [];
-          }
-          if (!allDependencies[dep].includes(version)) {
-            allDependencies[dep].push(version);
-          }
-        }
-      }
-    });
-  });
-
-  return allDependencies;
-}
-
-function findHighestVersion(versions) {
-  return versions.sort(semver.rcompare)[0];
-}
-
-function updateDependencies(packageFiles, allDependencies, {write, tabWidth}) {
-  let updated = false;
-  packageFiles.forEach((file) => {
-    const pkg = readPackageFile(file);
-
-    ['dependencies', 'devDependencies', 'peerDependencies'].forEach((key) => {
-      if (pkg[key]) {
-        for (const dep of Object.keys(pkg[key])) {
-          const highestVersion = findHighestVersion(allDependencies[dep]);
-          if (pkg[key][dep] !== highestVersion) {
-            pkg[key][dep] = highestVersion;
-            updated = true;
-          }
-        }
-      }
-    });
-
-    if (updated && write) {
-      writePackageFile(file, pkg, tabWidth);
-      console.log(`Updated ${file}`);
-    }
-  });
-  if (updated && write) {
-    console.log('Dependency versions synchronized.');
-  }
-}
+const fs = require("fs");
+const path = require("path");
+const glob = require("glob");
+const semver = require("semver");
+const {
+  allowedOptions,
+  getOptName,
+  printHelpMessage,
+  mergeOptionsAndDefaults,
+  parseArgs
+} = require("./lib/options.js");
+const {
+  getPackageFiles,
+  readPackageFile,
+  writePackageFile
+} = require("./lib/package-files.js");
+const {
+  collectDependencies,
+  findHighestVersion,
+  updateDependencies
+} = require("./lib/dependencies.js");
 
 function main(globPatterns, options) {
   const packageFiles = getPackageFiles(globPatterns);
   if (packageFiles.length === 0) {
-    console.log('No package.json files found.');
-    printHelpMessage()
+    console.log("No package.json files found.");
+    printHelpMessage();
     return;
   }
 
-  console.log('Found package.json files:', packageFiles);
+  console.log("Found package.json files:", packageFiles);
   const allDependencies = collectDependencies(packageFiles);
 
   for (const [dep, versions] of Object.entries(allDependencies)) {
@@ -133,46 +42,11 @@ function main(globPatterns, options) {
   updateDependencies(packageFiles, allDependencies, options);
 }
 
-function getOptName(flag) {
-  return optionNames.find(optName => allowedOptions[optName].flags.includes(flag))
-}
-
-function parseArgs (rest, opts = {}, globs = []) {
-  if (!rest || rest.length === 0) return {opts, globs};
-  const current = rest[0]
-
-  if (current.startsWith("-")) {
-    const optName = getOptName(current)
-    if (!optName) {
-      printHelpMessage()
-      throw new Error(`Unrecognised option: ${current}`)
-    }
-    const opt = allowedOptions[optName]
-    const value = opt.numArgs > 0 ?
-      rest.slice(1, opt.numArgs + 1) :
-      [true];
-    const nextRest = rest.slice((opt.numArgs || 0) + 1)
-    return parseArgs(nextRest, {...opts, [optName]: value}, globs)
-  }
-
-  return parseArgs(rest.slice(1), opts, [...globs, current])
-
-}
-
-function mergeOptionsAndDefaults(options) {
-  return optionNames.reduce((merged, optionName) => {
-    const option = allowedOptions[optionName]
-    const userValue = option.numArgs > 1 ? options[optionName] : options[optionName]?.[0]
-    const optionValue = userValue || option.default;
-    return {...merged, [optionName]: optionValue}
-  }, {})
-}
-
-const {opts, globs} = parseArgs([...process.argv].slice(2));
+const { opts, globs } = parseArgs([...process.argv].slice(2));
 
 if (!globs.length || opts.help) {
-  printHelpMessage()
+  printHelpMessage();
 } else {
-  const mergedOpts = mergeOptionsAndDefaults(opts)
+  const mergedOpts = mergeOptionsAndDefaults(opts);
   main(globs, mergedOpts);
 }

Some files were not shown because too many files changed in this diff