High-performance hierarchical indexing with O(1) lookup and GSI-style secondary indexes
npm install @statedelta-libs/gsindex> High-performance hierarchical indexing with O(1) lookup and GSI-style secondary indexes.


- O(1) Index Lookup - HashMap-based hierarchical path indexing
- Wildcards - Support for * patterns at any level
- Secondary Indexes (GSI) - Named indexes for alternative query patterns
- Query Cache - Up to 33M ops/s for repeated queries
- Zero Dependencies - Pure TypeScript, no external deps
- ~2KB gzipped - Smaller than alternatives (TinyBase 5-12KB, Orama 5-13KB, LokiJS 21KB)
``bash`
pnpm add @statedelta-libs/gsindex
`typescript
import { createStore, type Indexable } from '@statedelta-libs/gsindex';
// Define your item type
interface GameRule extends Indexable {
name: string;
damage: number;
}
// Create store
const store = createStore
cache: { enabled: true, maxSize: 1000 }
});
// Add items with hierarchical paths
store.add({
id: 'fireball',
index: 'game:combat:spell',
indexes: { byType: 'fire', byOwner: 'player1' },
name: 'Fireball',
damage: 50
});
store.add({
id: 'ice-shard',
index: 'game:combat:spell',
indexes: { byType: 'ice', byOwner: 'player1' },
name: 'Ice Shard',
damage: 30
});
// O(1) exact lookup
store.getByIndex('game:combat:spell');
// Wildcard queries
store.getCandidates({ path: 'game:combat:*' }); // All combat actions
store.getCandidates({ path: 'game:*' }); // All game actions
// GSI queries
store.getCandidates({ path: 'fire', indexName: 'byType' }); // All fire spells
store.getBySecondaryIndex('byOwner', 'player1'); // Player1's items
`
Hierarchical string with : separator (configurable):
`typescript
// Exact match
index: 'shop:cart:validate'
// Wildcards (only at the end)
index: 'shop:cart:*' // Any event in shop:cart
index: 'shop:*' // All of shop realm
index: '*' // Global (matches everything)
`
Named indexes for alternative query dimensions:
`typescript
store.add({
id: 'item-1',
index: 'game:action:attack',
indexes: {
byType: 'melee',
byOwner: 'player1',
byElement: 'fire'
}
});
// Query by any dimension
store.getBySecondaryIndex('byType', 'melee');
store.getBySecondaryIndex('byOwner', 'player1');
store.getCandidates({ path: 'fire', indexName: 'byElement' });
`
`typescript`
const store = createStore
cache: {
enabled: true, // Enable query caching
maxSize: 1000, // Max cached queries (LRU)
ttl: 60000 // Cache TTL in ms
},
separator: ':' // Path separator (default: ':')
});
`typescript`
store.add(item); // Add item
store.addMany(items); // Add multiple
store.get(id); // Get by ID
store.has(id); // Check exists
store.update(id, updates); // Update item
store.remove(id); // Remove item
store.removeMany(ids); // Remove multiple
store.clear(); // Clear all
store.all(); // Get all items
store.size; // Item count
`typescript
// Exact path - O(1)
store.getByIndex('shop:cart:validate');
// With wildcards - O(1) per matching prefix
store.getCandidates({ path: 'shop:cart:validate' });
store.getCandidates({ path: 'shop:cart:*' });
store.getCandidates({ path: 'shop:*' });
store.getCandidates({ path: '*' });
// Secondary index
store.getBySecondaryIndex('byType', 'monster');
store.getCandidates({ path: 'monster', indexName: 'byType' });
// List secondary indexes
store.getSecondaryIndexNames(); // ['byType', 'byOwner', ...]
store.getSecondaryIndexValues('byType'); // ['monster', 'spell', ...]
`
`typescript`
store.enable(id); // Enable item
store.disable(id); // Disable item
store.isEnabled(id); // Check if enabled
`typescript`
store.getCacheStats(); // { hits, misses, size, hitRate, enabled }
store.clearCache(); // Clear query cache
`typescript`
store.stats();
// {
// total: 100,
// exactPaths: 80,
// prefixPaths: 15,
// globalWildcards: 5,
// secondaryIndexes: { byType: 50, byOwner: 100 }
// }
| Operation | Performance |
|-----------|-------------|
| getByIndex (exact) | ~2.7M ops/s |
| getCandidates (cache HIT) | ~33M ops/s |
| getBySecondaryIndex | ~168K ops/s |
| Scale test (constant) | ~1M ops/s |
Performance is constant regardless of store size when using indexed paths:
| Total Items | Matching | Performance |
|-------------|----------|-------------|
| 100 | 20 | ~1M ops/s |
| 1,000 | 20 | ~1M ops/s |
| 10,000 | 20 | ~1M ops/s |
| Format | Size |
|--------|------|
| ESM (minified) | 6.5 KB |
| ESM (gzip) | ~2 KB |
| CJS (minified) | 6.5 KB |
| CJS (gzip) | ~2 KB |
`typescript
import {
// Types
type Indexable,
type IndexPath,
type IndexKey,
type SecondaryIndexes,
type IndexQuery,
type CacheConfig,
type CacheStats,
type StoreOptions,
type StoreStats,
type ItemUpdate,
// Constants
WILDCARD,
INDEX_SEPARATOR,
// Helpers
parseIndexPath,
buildIndexPath,
isWildcardPath,
getWildcardPrefix,
getQueryPrefixes,
matchesPath,
// Store
GSIndexStore,
createStore,
} from '@statedelta-libs/gsindex';
``
MIT