# Feature Request: Historian BrowsePublisher.NodeBuilder — expose node type for folder-first sorting
## Summary
When implementing a custom historian module, the `BrowsePublisher.NodeBuilder` API does not provide a way to indicate whether a browse result is a **folder** (intermediate path node) or a **leaf tag**. This means the historian tag browser sorts everything alphabetically without grouping folders above tags — unlike the realtime tag browser, which sorts folders first.
## Current Behaviour
In our custom `AbstractQueryEngine.doBrowse()` implementation, we publish both folder nodes and leaf tag nodes using `newNode("tag", value)`:
```java
// Folder node (has sub-tags underneath)
datasetPublisher.newNode("tag", "Dallas")
.hasChildren(true)
.add();
// Leaf tag node
datasetPublisher.newNode("tag", "Temperature")
.hasChildren(false)
.add();
```
The historian tag browser (e.g., Power Chart tag selection, Tag History Binding) then displays these alphabetically:
```
├── Compressor_1 (leaf tag)
├── Dallas (folder)
├── Flow_Rate (leaf tag)
├── Houston (folder)
├── Pressure (leaf tag)
```
Users expect folder-first sorting, consistent with the realtime tag browser and file explorer conventions:
```
├── Dallas (folder)
├── Houston (folder)
├── Compressor_1 (leaf tag)
├── Flow_Rate (leaf tag)
├── Pressure (leaf tag)
```
## Analysis
Looking at the SDK internals, the infrastructure for this is largely in place:
1. **`BasicResult`** (the object created by `NodeBuilder.add()`) already has `getType()` / `setType(String)` — but `RootBrowsePublisher.ResultBuilder` never calls `setType()`, so the type is always `null` on historian browse results.
2. **`TagObjectType.Folder`** and **`TagType.Folder`** exist and are used by the realtime tag system to classify folder nodes.
3. **`AbstractBrowseNode.BrowseTreeComparator`** on the client side uses a `folderTypes` set (`Set`) to sort folder nodes above leaf nodes in the realtime tag tree.
4. The `NodeBuilder` interface only exposes: `creationTime()`, `retiredTime()`, `metadata()`, `displayPath()`, `hasChildren()`, and `add()`. There is no `type()` or `tagType()` setter.
## Proposed Change
**Option A (minimal):** Add a `type(String)` method to `BrowsePublisher.NodeBuilder`, and have `ResultBuilder.add()` call `BasicResult.setType()` with that value. Then have the historian tag browser's comparator use the type to sort folders above leaf nodes — similar to how `BrowseTreeComparator` already works for the realtime tag tree.
```java
// Proposed API addition
public interface BrowsePublisher.NodeBuilder {
// ... existing methods ...
NodeBuilder type(String type); // e.g., "Folder", "AtomicTag"
}
```
**Option B (zero API change):** Use the existing `hasChildren` flag as a sort discriminator in the historian tag browser. Nodes with `hasChildren == true` would sort above nodes with `hasChildren == false`, with alphabetical sorting within each group. This would require no SDK API changes — only a client-side comparator adjustment.
Option B would be the simplest path and would cover the vast majority of use cases, since `hasChildren(true)` is already the de facto way custom historians indicate folder nodes.
## Environment
- Ignition 8.3.3
- Historian SDK: `historian-gateway-api-1.3.3`
- Custom historian module implementing `AbstractQueryEngine.doBrowse()`
Thanks for considering this. Happy to provide more detail if helpful.