« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/file-size-preloader.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/file-size-preloader.js')
-rw-r--r--src/file-size-preloader.js57
1 files changed, 54 insertions, 3 deletions
diff --git a/src/file-size-preloader.js b/src/file-size-preloader.js
index 4eadde7b..b2a55407 100644
--- a/src/file-size-preloader.js
+++ b/src/file-size-preloader.js
@@ -18,8 +18,10 @@
 // are very, very fast.
 
 import {stat} from 'node:fs/promises';
+import {relative, resolve, sep} from 'node:path';
 
 import {logWarn} from '#cli';
+import {filterMultipleArrays, transposeArrays} from '#sugar';
 
 export default class FileSizePreloader {
   #paths = [];
@@ -31,6 +33,10 @@ export default class FileSizePreloader {
 
   hadErrored = false;
 
+  constructor({prefix = ''} = {}) {
+    this.prefix = prefix;
+  }
+
   loadPaths(...paths) {
     this.#paths.push(...paths.filter((p) => !this.#paths.includes(p)));
     return this.#startLoadingPaths();
@@ -45,9 +51,9 @@ export default class FileSizePreloader {
       return this.#loadingPromise;
     }
 
-    this.#loadingPromise = new Promise((resolve) => {
-      this.#resolveLoadingPromise = resolve;
-    });
+    ({promise: this.#loadingPromise,
+      resolve: this.#resolveLoadingPromise} =
+        Promise.withResolvers());
 
     this.#loadNextPath();
 
@@ -96,9 +102,54 @@ export default class FileSizePreloader {
   }
 
   getSizeOfPath(path) {
+    let size = this.#getSizeOfPath(path);
+    if (size || !this.prefix) return size;
+    const path2 = resolve(this.prefix, path);
+    if (path2 === path) return null;
+    return this.#getSizeOfPath(path2);
+  }
+
+  #getSizeOfPath(path) {
     const index = this.#paths.indexOf(path);
     if (index === -1) return null;
     if (index > this.#loadedPathIndex) return null;
     return this.#sizes[index];
   }
+
+  saveAsCache() {
+    const entries =
+      transposeArrays([
+        this.#paths.slice(0, this.#loadedPathIndex)
+          .map(path => relative(this.prefix, path)),
+
+        this.#sizes.slice(0, this.#loadedPathIndex),
+      ]);
+
+    // Do not be alarmed: This cannot be meaningfully moved to
+    // the top because stringifyCache sorts alphabetically lol
+    entries.push(['_separator', sep]);
+
+    return Object.fromEntries(entries);
+  }
+
+  loadFromCache(cache) {
+    const {_separator: cacheSep, ...rest} = cache;
+    const entries = Object.entries(rest);
+    let [newPaths, newSizes] = transposeArrays(entries);
+
+    if (sep !== cacheSep) {
+      newPaths = newPaths.map(p => p.split(cacheSep).join(sep));
+    }
+
+    newPaths = newPaths.map(p => resolve(this.prefix, p));
+
+    filterMultipleArrays(
+      newPaths,
+      newSizes,
+      path => !this.#paths.includes(path));
+
+    this.#paths.splice(this.#loadedPathIndex + 1, 0, ...newPaths);
+    this.#sizes.splice(this.#loadedPathIndex + 1, 0, ...newSizes);
+    this.#loadedPathIndex += entries.length;
+  }
 }