You are reading content from Scuttlebutt
@neftaly
Re: %+fBXl12aV

This is a WIP for work, so it's not perfect, but here's an example of a nice big parent-pointer tree (as well as an index and a collection of orphaned sub-trees). You could very easily implement multiple parents in a big efficient cyclic graph for free, thanks to persistent data structures.

const entries = [
  {
    id: 'hash of { meta, data } prop',
    meta: {
      parent: 'parentId'
    },
    data: {
      ...
    }
    ...
  },
  ...
];

const tree = R.reduce(
  hydrate,
  immutable.fromJS({
    root: undefined,
    index: {},
    orphans: {}
  }),
  entries
);
import { fromJS, Map, List } from 'immutable';
import * as R from 'ramda';

const getPath = (entryId, parentId, parentPath) => {
  if (parentId === null) return List([ 'root' ]);
  return parentPath
    ? parentPath.concat([ 'tree', entryId ])
    : List([ 'orphans', parentId, entryId ]);
};

const getChildIds = tree => tree.toList(
  undefined
).flatMap(
  child => getChildIds(
    child.get('tree', Map())
  ).push(
    child.get('id')
  )
);

const updateIndexes = R.curry(
  (orphan, parentPath, index) => getChildIds(
    orphan
  ).reduce(
    (index, id) => index.update(
      id,
      path => parentPath.push(
        'tree'
      ).concat(
        path.splice(0, 2)
      )
    ),
    index
  )
);

const hydrate = (state, entry) => {
  const {
    id,
    meta: {
      parent
    }
  } = entry;
  const path = getPath(id, parent, state.getIn([ 'index', parent ]));
  const orphan = state.getIn([ 'orphans', id ], Map());
  return state.withMutations(
    state => state.update(
      'index',
      Map(),
      updateIndexes(orphan, path)
    ).setIn(
      [ 'index', id ], path // Add index
    ).setIn(
      // Add entry
      path, fromJS(entry)
    ).update(
      // Move children
      state => state.setIn(
        path.push('tree'),
        orphan
      ).deleteIn(
        [ 'orphans', id ]
      )
    )
  );
};

export default hydrate;
@cryptix
Voted this
Join Scuttlebutt now