npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gqm/context-resolver

v1.0.4

Published

Dynamic scoped context and configuration resolver for hierarchical overrides, interpolation, protocols, and structured path-based resolution.

Readme

@gqm/context-resolver

npm version npm downloads CI Release CodeQL API Regression License: MIT TypeScript ESM only Node \u2265 18 Biome Conventional Commits semantic-release

A dynamic scoped context and configuration resolver. Supports hierarchical overrides, path interpolation, protocols, and structured path-based resolution.

✨ Features

  • 🌐 Universal (Isomorphic): 100% ECMAScript. Runs flawlessly in Node.js, Deno, Bun, Cloudflare Workers, and modern browsers.
  • 📦 Pure ESM & Side-effect Free: Zero dependencies, fully tree-shakable.
  • 👨‍👦 Hierarchical Scoping: Shadow parent keys seamlessly.
  • 🪄 Dynamic Interpolation: {{ var }} tags resolve properly inside parent configurations using local child scope values.
  • 🔌 Protocols (Schemas): Built-in support for String Protocols (e.g. env:VAR) and Object Protocols (e.g. { $ref: 'path' }).
  • 🗺️ Path Semantics: a.b.c, a[0].b, and a.0.b parsed robustly.
  • 🛡️ Type Guards: Runtime assertions for bulletproof type safety.
  • ⚡ Epoch Cache: O(1) invalidation across the tree when any local context changes.

📦 Installation

Pick your favorite package manager:

# npm
npm install @gqm/context-resolver

# pnpm
pnpm add @gqm/context-resolver

# yarn
yarn add @gqm/context-resolver

# bun
bun add @gqm/context-resolver

# deno
deno add npm:@gqm/context-resolver

Features Tour

1. Hierarchical Scoping & Shadowing

Children inherit values from their parents but can shadow them locally.

import { createScope } from '@gqm/context-resolver';

const root = createScope();
root.set('api.timeout', 5000);
root.set('api.host', 'example.com');

const child = createScope({ parent: root });
child.set('api.timeout', 1500); // Shadow only the timeout

console.log(child.resolve('api.host'));    // 'example.com' (from parent)
console.log(child.resolve('api.timeout')); // 1500 (local override)

2. Dynamic Interpolation (Child-First Semantics)

When a parent template is resolved by a child, it interpolates using the child's context.

const root = createScope();
root.set('prefix', '/v1');
root.set('url', 'https://api.example.com{{prefix}}');

const child = createScope({ parent: root });
child.set('prefix', '/beta');

// The parent's template naturally adapts to the child's environment!
console.log(child.resolve('url')); // 'https://api.example.com/beta'

3. Deep Path Set & Resolve

Containers are created automatically. You can use dot-notation or brackets.

const scope = createScope();
scope.set('database.credentials.user', 'admin');
scope.set('servers[0].port', 8080);

console.log(scope.resolve('database')); 
// { credentials: { user: 'admin' } }

console.log(scope.resolve('servers[0].port')); 
// 8080

4. Built-in $ref Object Protocol

Reference values stored elsewhere in the tree.

const scope = createScope();
scope.set('system.adminEmail', '[email protected]');
scope.set('alerts.to', { $ref: 'system.adminEmail' });

console.log(scope.resolve('alerts.to')); // '[email protected]'

5. ⚡ Runtime Type Guards

Ensure the resolved value matches your TypeScript type safely.

const scope = createScope();
scope.set('retries', 3);

// Throws TypeError if the resolved value is not a number
const retries = scope.resolve('retries', (v): v is number => typeof v === 'number');

6. 🔌 Custom String Protocols (Schemas)

String protocols intercept paths with the schema:path format, letting you source values from any external provider — environment variables, vaults, files, and more.

const scope = createScope();

// Register your own `env:` schema
scope.registerStringProtocol('env', (path) => process.env[path]);

// Now resolves naturally alongside regular scope keys
console.log(scope.resolve('env:API_KEY'));

// And scope values can OVERRIDE the protocol — great for testing!
scope.set('env:API_KEY', 'mock-key-for-tests');
console.log(scope.resolve('env:API_KEY')); // 'mock-key-for-tests'

💡 The community refers to this pattern as "String Protocols" or "Schemas" — the prefix before : is the schema name.

🧠 Advanced Usage

Need to create custom Object Protocols (like $join), disable built-in protocols ($ref), or understand the O(1) Epoch Cache internals? Check out the Advanced Usage Guide.

🤝 Contributing

We love contributions! Please read our Contributing Guide to learn about our Dual Runtime (Node + Deno) setup, how to run tests, and the workflow to follow.

🤖 AI Agents: If you are using Claude, GitHub Copilot, Cursor, or any AI assistant to contribute to this repo, please point it to AGENTS.md as the absolute source of truth.

🗺️ Roadmap

Async Scope

Add resolveAsync(path) returning a Promise, allowing String and Object Protocol handlers to be async. Unlocks use cases like fetching secrets from a remote vault, reading config from the file system, or calling feature-flag APIs as part of resolution.

Open design questions: parallel AsyncScope class vs async overloads on Scope; how the Epoch Cache handles concurrent resolves.

Scope Sealing

A scope.seal() operation that makes a scope (or specific paths/protocols within it) immutable. Any set() after sealing throws a ScopeSealed error.

const scope = createScope();
scope.set('db.host', 'prod-db.example.com');
scope.seal();

scope.set('db.host', 'other'); // throws: ScopeSealed

Variants under consideration: seal() for the whole scope, seal('path') for a specific key, sealProtocols() to prevent new protocol registrations.