logged scope now includes library and version
[squeep-indieauth-helper] / lib / common.js
index cfdf9db7e5c47feda5e05b52624a17a25949d853..3bf7e55cc7e85a4cd050fd2708dc2726fa9f9d94 100644 (file)
@@ -1,24 +1,25 @@
 'use strict';
 
 const path = require('path');
+const { name: packageName, version: packageVersion } = require('../package');
+
+const libraryIdentifier = `${packageName}@${packageVersion}`;
 
 /**
  * Return a function which combines a part of the filename with a scope, for use in logging.
  * @param {string} filename
  */
 const fileScope = (filename) => {
-  let fScope = path.basename(filename, '.js');
-  if (fScope === 'index') {
-    fScope = path.basename(path.dirname(filename));
-  }
-  return (scope) => `${fScope}:${scope}`;
+  const shortFilename = path.basename(filename, '.js');
+  const fScope = (shortFilename === 'index') ? path.basename(path.dirname(filename)) : shortFilename;
+  return (scope) => [libraryIdentifier, fScope, scope].join(':');
 }
 
 
 /**
  * Pick out useful axios response fields.
- * @param {*} res
- * @returns
+ * @param {AxiosResponse} res
+ * @returns {Object}
  */
 const axiosResponseLogData = (res) => {
   const data = pick(res, [
@@ -64,9 +65,56 @@ const pick = (obj, props) => {
 };
 
 
+/**
+ * Return a set containing non-shared items between two sets.
+ * @param {Set} a
+ * @param {Set} b
+ * @returns {Set}
+ */
+const setSymmetricDifference = (a, b) => {
+  const d = new Set(a);
+  for (const x of b) {
+    if (d.has(x)) {
+      d.delete(x);
+    } else {
+      d.add(x);
+    }
+  }
+  return d;
+};
+
+
+/**
+ * URL objects have weird names.
+ * @param {String} component
+ * @returns {String}
+ */
+const properURLComponentName = (component) => {
+  // eslint-disable-next-line security/detect-object-injection
+  return {
+    hash: 'fragment',
+    protocol: 'scheme',
+  }[component] || component;
+}
+
+
+/**
+ * Encodes single-level object as form data string.
+ * @param {Object} data
+ */
+const formData = (data) => {
+  const formData = new URLSearchParams();
+  Object.entries(data).forEach(([name, value]) => formData.set(name, value));
+  return formData.toString();
+};
+
+
 module.exports = {
   fileScope,
   axiosResponseLogData,
   logTruncate,
   pick,
+  setSymmetricDifference,
+  properURLComponentName,
+  formData,
 };
\ No newline at end of file