De-duplcation I - After

by Jeff Cave

HTML

<html>
  <script src="//cdn.jsdelivr.net/pouchdb/latest/pouchdb.min.js"></script>
  <script type="module" src="./index.js"></script>
<body>
  
  <table>
   <thead>
    <tr>
     <td>User</td>
     <td>Files</td>
     <td>Size</td>
     <td>Min</td>
     <td>Avg</td>
     <td>Max</td>
    </tr>
  </thead>
  <tbody>
    
  </tbody>
  </table>
  <pre id="display">Log ...<hr /></pre>
</body>
</html>

CSS

pre{
  border: 1px solid black;
  background-color: lightgray;
  padding: 1em;
}

td,tr{
  padding:1em;
  padding-top: 0.1em;
}

JavaScript

let db = new PouchDB('filestore');

async function CreateIndex() {
  await db.put({
    _id: '_design/allfiles',
    views: {
      'allfiles': {
        map: function(doc) {
          for (let userpath of doc.userpaths) {
            userpath = userpath.split('@');
            emit(userpath, doc.size);
          }
        }.toString(),
        reduce: '_stats'
      }
    }
  });
}

async function save(user, filename, blob) {
  let buff = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(blob));
  let hash = Array.from(new Uint8Array(buff));
  hash = hash.map(b => b.toString(16).padStart(2, '0')).join('').substr(0,4);
  let userpath = [user, filename].join('@');
  let rec = null;
  try {
    rec = await db.get(hash);
  } catch (e) {
    if (e.status !== 404) throw e;
    // create the object, with a list of user's using it
    rec = {
      _id: hash,
      userpaths: [],
      size: blob.length,
      _attachments: {
        '0': {
          content_type: 'text/plain',
          data: window.btoa(blob)
        }
      }
    }
  }
  if (!rec.userpaths.includes(userpath)) {
    rec.userpaths.push(userpath);
  }
  // finally save the record
  return db.put(rec);
}

async function dload(user, filename) {
  let recs = await db.query('allfiles', {
    reduce: false,
    include_docs: true,
    attachments: true,
    key: [user, filename]
  });
  let blob = recs.rows[0].doc._attachments['0'].data;
  blob = window.atob(blob);
  return blob;
}

function log(msg) {
  let display = document.querySelector('#display');
  if (typeof msg !== "string") {
    msg = JSON.stringify(msg);
  }
  display.innerHTML += msg + '\n';
}

function report(data) {
  let html = data.rows.map((d) => {
    return '' +
      '<tr><td>' + [
        d.key,
        d.value.count,
        d.value.sum,
        d.value.min,
        Math.floor(d.value.sum / d.value.count),
        d.value.max
      ].join('</td><td>') +
      '</td></tr>';
  }).join('');
 ...