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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@proc7ts/context-values

v7.1.1

Published

IoC context values provider

Downloads

1,884

Readme

IoC Context Values

NPM Build Status Code Quality Coverage GitHub Project API Documentation

IoC context allows accessing its values identified by their entries and provided somewhere else.

Features:

  • Type-safe API.

    Each context entry has definite value type specified as generic type parameter. So, when accessing context value with get() method, the returned value has that exact type, rather any.

  • Clean distinction between assets provided for context entries, and their values.

    E.g. entry value is an array, while its assets are elements of this array.

  • Customizable relation between entry assets and its value.

    This relation established by entry implementation. Typically, the entry builds its value out of its assets.

  • Reusable context entry implementations suitable for the majority of use cases.

    E.g. cxSingle() for single-valued entries, or cxArray() for array-valued ones.

  • Dynamically updatable context values.

    The cxSingle() and cxArray() entries build the value once on the first access, and return it on each subsequent access. In contrast, the cxRecent() and cxDynamic() are able to track asset changes and reflect these changes in entry value.

  • Context derivation.

    A context may derive another context to make the values from the latter available in the former.

Project Modules

Accessing Context Values

An IoC context implements a CxValues interface. This interface declares a single get() method accepting requested entry instance (CxEntry), and optional request (CxRequest).

The following code returns a string value of myEntry entry, or throws an exception if the entry has no value.

import { CxEntry, cxSingle } from '@proc7ts/context-values';

const myEntry: CxEntry<string> = {
  perContext: cxSingle(),
  toString: () => '[CxEntry myEntry]',
};

myContext.get(myEntry);

Fallback Value

Normally, if context entry has no value, an exception thrown. To avoid this, a fallback value can be provided. It will be returned in case there is no value.

import { CxEntry, cxSingle } from '@proc7ts/context-values';

const myEntry: CxEntry<string> = {
  perContext: cxSingle(),
  toString: () => '[CxEntry myEntry]',
};

myContext.get(myEntry, { or: 'empty' }); // 'empty'

A null value can be used as a fallback one.

Default Value

Context entry may have a default value that will be returned, unless the entry has an explicitly provided one or a fallback value specified. It is possible to request the default value directly:

import { CxEntry, CxRequestMethod, cxSingle } from '@proc7ts/context-values';

const myEntry: CxEntry<string> = {
  perContext: cxSingle({ byDefault: () => 'default' }),
  toString: () => '[CxEntry myEntry]',
};

myContext.get(myEntry, { by: CxRequestMethod.Defaults }); // 'default'

It is also possible to request explicitly provided value with { by: CxRequestMethod.Assets } request.

Request Callback

In addition to returning from get() method call, the context value can be passed to a callback:

import { CxEntry, CxRequestMethod, cxSingle } from '@proc7ts/context-values';

const myEntry: CxEntry<string> = {
  perContext: cxSingle({ byDefault: () => 'default' }),
  toString: () => '[CxEntry myEntry]',
};

let myValue: string | undefined;
let myValueBy: CxRequestMethod | undefined;

myContext.get(myEntry, { set: (value, by) => { myValue = value; myValueBy = my });
// myValue === 'default'
// myValueBy === CxRequestMethod.Defaults

The callback won't be called if the entry has no value.

Note that this is the only way to know the origin of the value received. I.e. whether it is

  • an explicitly provided value (CxRequestMethod.Assets),
  • a default value (CxRequestMethod.Defaults), or
  • a fallback value (CxRequestMethod.Fallback).

Providing Context Values

The @proc7ts/context-builder contains everything needed to build a context and to provide assets for it.

import { CxBuilder, cxBuildAsset, cxConstAsset } from '@proc7ts/context-builder';
import { CxEntry, cxSingle } from '@proc7ts/context-values';

const entry1: CxEntry<string> = { perContext: cxSingle(), toString: () => '[CxEntry entry1]' };
const entry2: CxEntry<number> = { perContext: cxSingle(), toString: () => '[CxEntry entry2]' };

// Create context builder.
const cxBuilder = new CxBuilder(get => ({ get }) /* create context instance with `get` method */);

// Provide asset for `entry1` as constant.
cxBuilder.provide(cxConstAsset(entry1, 'string'));

// Evaluate asset for `entry2` as the length `entry1` value.
cxBuilder.provide(cxBuildAsset(entry2, target => target.get(entry1).length));

// Obtain context instance.
const context = registry.context;

// Obtain context values.
context.get(entry1); // 'string'
context.get(entry2); // 6

Context Entry

Context entry identifies the value to obtain when passed to context's get() method. It is also responsible for combining provided assets into context value.

Context entry implements CxEntry interface containing a single perContext method. It also a good practice to override a toString() method, so that error messages contain a string representation of the entry.

There are several standard customizable CxEntry implementations. It is typically enough to use one of them:

  • cxArray() - Lazily evaluated array-valued context entry.
  • cxDynamic() - Dynamically updating context entry reflecting the changes in entry assets.
  • cxEvaluated() - Context entry with value lazily evaluated by the given function.
  • cxRecent() - Dynamically updating context entry reflecting the changes in the most recent entry asset.
  • cxSingle() - Lazily evaluated single-valued context entry.

These functions create entry definers. I.e. functions that can be used as perContext implementations.

import { CxBuilder, cxConstAsset } from '@proc7ts/context-builder';
import { cxDynamic, CxEntry } from '@proc7ts/context-values';

// Context value is a readonly array of strings,
// wwhile its assets are stringhs.
const myEntry: CxEntry<readonly string[], string> = {
  perContext: cxDynamic(),
  toString: () => '[CxEntry myEntry]',
};

const cxBuilder = new CxBuilder(get => ({ get }));
const context = cxBuilder.context;

context.get(myEntry); // []

// Provide first asset.
const supply = cxBuilder.provide(cxConstAsset(myEntry, 'foo'));

context.get(myEntry); // ['foo']

// Provide second asset.
cxBuilder.provide(cxConstAsset(myEntry, 'bar'));
context.get(myEntry); // ['foo', 'bar']

// Revoke the first asset.
supply.off();
context.get(myEntry); // ['bar']

Context Scopes

When combining multiple contexts (i.e. making one context derive another one), it is often required to obtain some entry from particular context only.

To make it possible a context may provide itself as its own context value. Then the entry implementation may obtain this context, and then obtain its value from that context.

A context entry containing a context as its value called scope. There are two context entry implementations able to handle scopes: