包详细信息

@httpx/treeu

belgattitude873MIT0.5.0

Tree utilities

treeify

自述文件

@httpx/treeu

Fast and lightweight (~300B) utilities to work with trees.

npm changelog codecov bundles node browserslist size downloads license

Install

$ npm install @httpx/treeu
$ yarn add @httpx/treeu
$ pnpm add @httpx/treeu

Features

Documentation

👉 Official website or Github Readme

Usage

Search

DFSTreeSearch

Depth-First Search (DFS) algorithm for tree structures. It uses a stack rather than recursion in order to support deeply nested trees without call-stack overflows. It is well suited for exploring a branch of a data structure in depth and usually preferred when memory usage is a concern or when the data structure has many nodes with few levels.

import { Tree, type TreeNode } from '@httpx/treeu';

type CustomValue =
    | { type: 'folder'; size?: never }
    | { type: 'file'; size: number };

const treeNodes: TreeNode<CustomValue>[] = [
    {
        id: 'file2.ts',
        parentId: null,
        value: { size: 10, type: 'file' },
        children: [],
    },
    {
        id: 'folder1',
        parentId: null,
        value: { type: 'folder' },
        children: [
            {
                id: 'folder1/file1.ts',
                parentId: 'folder1',
                value: { size: 30, type: 'file' },
                children: [],
            },
        ],
    },
];

const search = new DfsTreeSearch<CustomValue>(treeNodes);
const res1 = search.findOne('folder1/file1.ts');
const res2 = search.findOne(['id', '===', 'folder1/file1.ts']);
const res3 = search.findOne((treeNode) => treeNode.value.size === 30);
const res4 = search.findOne(['parentId', '===', 'folder1']);

// res1 === res2 === res3 === res4

Mapper

FlatTreeWsMapper

FlatTreeWsMapper Description
toTreeNodes Convert to flat map with separator
fromTreeNodes Convert a tree to a flat map with separator
import { FlatTreeWsMapper, type FlatTreeWs } from '@httpx/treeu';

type CustomValue =
    | { type: 'folder'; size?: never }
    | { type: 'file'; size: number };

// Use an object or a Record<string, CustomValue>
const paths: FlatTreeWs<CustomValue> = new Map([
    [ 'file1.ts', { type: 'file', size: 10 } ],
    [ 'folder1', { type: 'folder' }],
    [ 'folder1/file1.ts', { type: 'file', size: 30 }],
]);

const mapper = new FlatTreeWsMapper<CustomValue>();

const treeResult = mapper.toTreeNodes(paths, {
    separator: '/',
});

// Will return 
const expected: TreeNode<CustomValue>[] = [
    {
        id: 'file1.ts',
        parentId: null,
        value: {
            size: 10,
            type: 'file',
        },
        children: [],
    },
    {
        id: 'folder1',
        parentId: null,
        value: {
            type: 'folder',
        },
        children: [
            {
                id: 'folder1/file1.ts',
                parentId: 'folder1',
                value: {
                    size: 30,
                    type: 'file',
                },
                children: [],
            },
        ],
    },
];

TreeNode

Example

Example of TreeNode[] typing:

import { Tree, TreeNode } from '@httpx/treeu';

type CustomValue =
    | { type: 'folder'; size?: never }
    | { type: 'file'; size: number };

const treeNodes: TreeNode<CustomValue>[] = [
    {
        id: 'file1.ts',
        parentId: null,
        value: {
            size: 10,
            type: 'file',
        },
        children: [],
    },
    {
        id: 'file2.ts',
        parentId: null,
        value: {
            size: 20,
            type: 'file',
        },
        children: [],
    },
    {
        id: 'folder1',
        parentId: null,
        value: {
            type: 'folder',
        },
        children: [
            {
                id: 'folder1/file1.ts',
                parentId: 'folder1',
                value: {
                    size: 30,
                    type: 'file',
                },
                children: [],
            },
        ],
    },
    {
        id: 'folder2',
        parentId: null,
        value: {
            type: 'folder',
        },
        children: [
            {
                id: 'folder2/file1.ts',
                parentId: 'folder2',
                value: {
                    size: 40,
                    type: 'file',
                },
                children: [],
            },
            {
                id: 'folder2/subfolder1',
                parentId: 'folder2',
                value: {
                    type: 'folder',
                },
                children: [
                    {
                        id: 'folder2/subfolder1/file1.ts',
                        parentId: 'folder2/subfolder1',
                        value: {
                            size: 50,
                            type: 'file',
                        },
                        children: [],
                    },
                ],
            },
        ],
    },
    {
        id: 'folder3',
        parentId: null,
        value: {
            type: 'folder',
        },
        children: [],
    },
];

Tree

Types

TreeNode<TValue, TId> Type Description
id `TValue extends string\ number` Unique identifier of the node.
parentId `TValue extends string\ number` Reference to the parent node
children TreeNode<TValue, TId>[] Children nodes
value `TValue\ undefined` Custom value associated with the node

Benchmarks

Performance is continuously monitored thanks to codspeed.io.

CodSpeed Badge

 RUN  v3.0.3 /home/sebastien/github/httpx/packages/treeu


 ✓ bench/search.bench.ts > Bench search (10_000 entries) 3827ms
     name                                                       hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · DfsTreeSearch.findOne(id_0) over 10_000          4,951,722.70  0.0002  0.2812  0.0002  0.0002  0.0004  0.0005  0.0009  ±0.36%  2475862   fastest
   · DfsTreeSearch.findOne(id_1000) over 10_000          36,877.99  0.0242  0.2565  0.0271  0.0265  0.0417  0.0496  0.1387  ±0.39%    18439
   · DfsTreeSearch.findOne(id_5000) over 10_000           7,109.04  0.1321  0.4006  0.1407  0.1401  0.2237  0.2336  0.3525  ±0.35%     3555
   · DfsTreeSearch.findOne(id_NotExists) over 10_000      3,637.79  0.2513  0.5789  0.2749  0.2768  0.3892  0.4068  0.5149  ±0.43%     1819   slowest

 ✓ bench/mapper.bench.ts > Bench mapper (10_000 entries) 647ms
     name                                     hz     min      max    mean     p75      p99     p995     p999     rme  samples
   · FlatTreeWsMapper.toTreeNodesOrThrow  148.37  6.3635  11.2594  6.7397  6.8240  11.2594  11.2594  11.2594  ±2.05%       75

 BENCH  Summary

  FlatTreeWsMapper.toTreeNodesOrThrow - bench/mapper.bench.ts > Bench mapper (10_000 entries)

  DfsTreeSearch.findOne(id_0) over 10_000 - bench/search.bench.ts > Bench search (10_000 entries)
    134.27x faster than DfsTreeSearch.findOne(id_1000) over 10_000
    696.54x faster than DfsTreeSearch.findOne(id_5000) over 10_000
    1361.19x faster than DfsTreeSearch.findOne(id_NotExists) over 10_000

See benchmark file for details.

Bundle size

Bundle size is tracked by a size-limit configuration

Scenario (esm) Size (compressed)
import { DfsTreeSearch } from '@httpx/treeu ~ 270B
import { FlatTreeWsMapper } from '@httpx/treeu ~ 802B

For CJS usage (not recommended) track the size on bundlephobia.

Compatibility

Level CI Description
Node CI for 20.x, 22.x & 24.x.
Browser Tested with latest chrome (vitest/playwright)
Browserslist > 95% on 01/2025. defaults, chrome >= 96, firefox >= 105, edge >= 113, safari >= 15, ios >= 15, opera >= 103, not dead
Edge Ensured on CI with @vercel/edge-runtime.
Cloudflare Ensured with @cloudflare/vitest-pool-workers (see wrangler.toml
Edge Ensured on CI with @vercel/edge-runtime.
Typescript TS 5.0 + / are-the-type-wrong checks on CI.
ES2022 Dist files checked with es-check
Performance Monitored with codspeed.io

For older browsers: most frontend frameworks can transpile the library (ie: nextjs...)

Contributors

Contributions are welcome. Have a look to the CONTRIBUTING document.

Sponsors

If my OSS work brightens your day, let's take it to new heights together! Sponsor>), coffee>), or star – any gesture of support fuels my passion to improve. Thanks for being awesome! 🙏❤️

Special thanks to

Jetbrains logo Jetbrains logo
JetBrains Embie.be

License

MIT © belgattitude and contributors.

更新日志