Switch to more efficient object deep cloning and shallow merging
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 23 Dec 2022 17:25:30 +0000 (18:25 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 23 Dec 2022 17:25:30 +0000 (18:25 +0100)
implementations

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
package-lock.json
package.json
rollup.config.mjs
src/charging-station/ChargingStation.ts
src/utils/Configuration.ts
src/utils/Utils.ts

index 55bad82156049213503e1830fd24d16753fa7fc2..2f1ebea9a7b3cde6325f0e9ef523ead339570bbe 100644 (file)
@@ -19,6 +19,8 @@
         "basic-ftp": "^5.0.2",
         "chalk": "^4.1.2",
         "http-status-codes": "^2.2.0",
+        "just-clone": "^6.2.0",
+        "just-merge": "^3.2.0",
         "mnemonist": "^0.39.5",
         "moment": "^2.29.4",
         "mongodb": "^4.13.0",
       }
     },
     "node_modules/cacheable-request": {
-      "version": "10.2.3",
-      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.3.tgz",
-      "integrity": "sha512-6BehRBOs7iurNjAYN9iPazTwFDaMQavJO8W1MEm3s2pH8q/tkPTtLDRUZaweWK87WFGf2Y5wLAlaCJlR5kOz3w==",
+      "version": "10.2.4",
+      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.4.tgz",
+      "integrity": "sha512-IWIea8ei1Ht4dBqvlvh7Gs7EYlMyBhlJybLDUB9sadEqHqftmdNieMLIR5ia3vs8gbjj9t8hXLBpUVg3vcQNbg==",
       "dev": true,
       "dependencies": {
-        "@types/http-cache-semantics": "^4.0.1",
         "get-stream": "^6.0.1",
         "http-cache-semantics": "^4.1.0",
         "keyv": "^4.5.2",
         "node": ">=0.6.0"
       }
     },
+    "node_modules/just-clone": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-6.2.0.tgz",
+      "integrity": "sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA=="
+    },
+    "node_modules/just-merge": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/just-merge/-/just-merge-3.2.0.tgz",
+      "integrity": "sha512-cNh5FWt44hx4SpQS1xZU8Tzr/fQA69pqCdjbwxmaYYIOuRfA8EIg+dn1bGmIW03ZUtR2vkMOCjWKc+jIbpauSw=="
+    },
     "node_modules/keyv": {
       "version": "4.5.2",
       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
       "dev": true
     },
     "cacheable-request": {
-      "version": "10.2.3",
-      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.3.tgz",
-      "integrity": "sha512-6BehRBOs7iurNjAYN9iPazTwFDaMQavJO8W1MEm3s2pH8q/tkPTtLDRUZaweWK87WFGf2Y5wLAlaCJlR5kOz3w==",
+      "version": "10.2.4",
+      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.4.tgz",
+      "integrity": "sha512-IWIea8ei1Ht4dBqvlvh7Gs7EYlMyBhlJybLDUB9sadEqHqftmdNieMLIR5ia3vs8gbjj9t8hXLBpUVg3vcQNbg==",
       "dev": true,
       "requires": {
-        "@types/http-cache-semantics": "^4.0.1",
         "get-stream": "^6.0.1",
         "http-cache-semantics": "^4.1.0",
         "keyv": "^4.5.2",
         "verror": "1.10.0"
       }
     },
+    "just-clone": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/just-clone/-/just-clone-6.2.0.tgz",
+      "integrity": "sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA=="
+    },
+    "just-merge": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/just-merge/-/just-merge-3.2.0.tgz",
+      "integrity": "sha512-cNh5FWt44hx4SpQS1xZU8Tzr/fQA69pqCdjbwxmaYYIOuRfA8EIg+dn1bGmIW03ZUtR2vkMOCjWKc+jIbpauSw=="
+    },
     "keyv": {
       "version": "4.5.2",
       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
index ea5c18894b6bd3d8fdc44d0b252b68621f1b2541..43204820cb11cea306522b7f5bf98706dddef19f 100644 (file)
@@ -82,6 +82,8 @@
     "basic-ftp": "^5.0.2",
     "chalk": "^4.1.2",
     "http-status-codes": "^2.2.0",
+    "just-clone": "^6.2.0",
+    "just-merge": "^3.2.0",
     "mnemonist": "^0.39.5",
     "moment": "^2.29.4",
     "mongodb": "^4.13.0",
index 4378f014f00ebb94d623561146680f29f0034762..231b7485adaa49fa621505f85b16bd197c44c91a 100644 (file)
@@ -44,6 +44,8 @@ export default {
     'fs',
     'http',
     'http-status-codes',
+    'just-clone',
+    'just-merge',
     'mnemonist/lru-map-with-delete',
     'moment',
     'mongodb',
index 5c8ec1e48d9ad7ae112340f4a553abad3cb0f37a..f7cad5db37beb80db1b417b183d40121718557e8 100644 (file)
@@ -1890,9 +1890,9 @@ export default class ChargingStation {
   }
 
   private getConfiguredSupervisionUrl(): URL {
-    const supervisionUrls = Utils.cloneObject<string | string[]>(
+    const supervisionUrls = (
       this.stationInfo.supervisionUrls ?? Configuration.getSupervisionUrls()
-    );
+    ).slice();
     if (!Utils.isEmptyArray(supervisionUrls)) {
       switch (Configuration.getSupervisionUrlDistribution()) {
         case SupervisionUrlDistribution.ROUND_ROBIN:
index c17cad01545cab8fe77a25a37e3d856fa956a90f..3770c6ca20e8decc848fad014cd027c2efa5f6d3 100644 (file)
@@ -3,6 +3,7 @@ import path from 'path';
 import { fileURLToPath } from 'url';
 
 import chalk from 'chalk';
+import merge from 'just-merge';
 import { WorkerChoiceStrategies } from 'poolifier';
 
 import {
@@ -68,7 +69,7 @@ export default class Configuration {
       },
     };
     if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'uiServer')) {
-      uiServerConfiguration = Configuration.deepMerge(
+      uiServerConfiguration = Configuration.merge(
         uiServerConfiguration,
         Configuration.getConfig().uiServer
       );
@@ -409,9 +410,9 @@ export default class Configuration {
     }
   }
 
-  private static isObject(item: unknown): boolean {
-    return item && typeof item === 'object' && Array.isArray(item) === false;
-  }
+  // private static isObject(item: unknown): boolean {
+  //   return item && typeof item === 'object' && Array.isArray(item) === false;
+  // }
 
   private static objectHasOwnProperty(object: unknown, property: string): boolean {
     return Object.prototype.hasOwnProperty.call(object, property) as boolean;
@@ -421,27 +422,8 @@ export default class Configuration {
     return typeof obj === 'undefined';
   }
 
-  private static deepMerge(target: object, ...sources: object[]): object {
-    if (!sources.length) {
-      return target;
-    }
-    const source = sources.shift();
-
-    if (Configuration.isObject(target) && Configuration.isObject(source)) {
-      for (const key in source) {
-        if (Configuration.isObject(source[key])) {
-          if (!target[key]) {
-            Object.assign(target, { [key]: {} });
-          }
-          // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
-          Configuration.deepMerge(target[key], source[key]);
-        } else {
-          // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
-          Object.assign(target, { [key]: source[key] });
-        }
-      }
-    }
-    return Configuration.deepMerge(target, ...sources);
+  private static merge(target: object, ...sources: object[]): object {
+    return merge(target, ...sources);
   }
 
   private static handleFileException(
index f27f06660227643ebe516f8972ee08206334af22..2fde488376ad9a2c74a75b86c925abf577c6353c 100644 (file)
@@ -1,5 +1,7 @@
 import crypto from 'crypto';
 
+import clone from 'just-clone';
+
 import { WebSocketCloseEventStatusString } from '../types/WebSocket';
 
 export default class Utils {
@@ -163,8 +165,8 @@ export default class Utils {
     );
   }
 
-  public static cloneObject<T>(object: T): T {
-    return JSON.parse(JSON.stringify(object)) as T;
+  public static cloneObject<T extends object>(object: T): T {
+    return clone<T>(object);
   }
 
   public static isIterable<T>(obj: T): boolean {