export function nodeFromJSON()

in packages/database/src/core/snap/nodeFromJSON.ts [40:132]


export function nodeFromJSON(
  json: unknown | null,
  priority: unknown = null
): Node {
  if (json === null) {
    return ChildrenNode.EMPTY_NODE;
  }

  if (typeof json === 'object' && '.priority' in json) {
    priority = json['.priority'];
  }

  assert(
    priority === null ||
      typeof priority === 'string' ||
      typeof priority === 'number' ||
      (typeof priority === 'object' && '.sv' in (priority as object)),
    'Invalid priority type found: ' + typeof priority
  );

  if (typeof json === 'object' && '.value' in json && json['.value'] !== null) {
    json = json['.value'];
  }

  // Valid leaf nodes include non-objects or server-value wrapper objects
  if (typeof json !== 'object' || '.sv' in json) {
    const jsonLeaf = json as string | number | boolean | Indexable;
    return new LeafNode(jsonLeaf, nodeFromJSON(priority));
  }

  if (!(json instanceof Array) && USE_HINZE) {
    const children: NamedNode[] = [];
    let childrenHavePriority = false;
    const hinzeJsonObj = json;
    each(hinzeJsonObj, (key, child) => {
      if (key.substring(0, 1) !== '.') {
        // Ignore metadata nodes
        const childNode = nodeFromJSON(child);
        if (!childNode.isEmpty()) {
          childrenHavePriority =
            childrenHavePriority || !childNode.getPriority().isEmpty();
          children.push(new NamedNode(key, childNode));
        }
      }
    });

    if (children.length === 0) {
      return ChildrenNode.EMPTY_NODE;
    }

    const childSet = buildChildSet(
      children,
      NAME_ONLY_COMPARATOR,
      namedNode => namedNode.name,
      NAME_COMPARATOR
    ) as SortedMap<string, Node>;
    if (childrenHavePriority) {
      const sortedChildSet = buildChildSet(
        children,
        PRIORITY_INDEX.getCompare()
      );
      return new ChildrenNode(
        childSet,
        nodeFromJSON(priority),
        new IndexMap(
          { '.priority': sortedChildSet },
          { '.priority': PRIORITY_INDEX }
        )
      );
    } else {
      return new ChildrenNode(
        childSet,
        nodeFromJSON(priority),
        IndexMap.Default
      );
    }
  } else {
    let node: Node = ChildrenNode.EMPTY_NODE;
    each(json, (key: string, childData: unknown) => {
      if (contains(json as object, key)) {
        if (key.substring(0, 1) !== '.') {
          // ignore metadata nodes.
          const childNode = nodeFromJSON(childData);
          if (childNode.isLeafNode() || !childNode.isEmpty()) {
            node = node.updateImmediateChild(key, childNode);
          }
        }
      }
    });

    return node.updatePriority(nodeFromJSON(priority));
  }
}