1.0.0 • Published 4 years ago

@borderlesslabs/context v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

Context

NPM version NPM downloads Build status Test coverage Bundle size

Tiny, type-safe, JavaScript-native context implementation.

Why? Working on utilities across browsers, serverless and node.js require different of implementations, e.g. fetch vs require('http'). Go's context package provides a nice abstraction for my needs. By implementing a JavaScript first variation, we can achieve the same benefits.

Installation

npm install @borderlesslabs/context --save

Usage

Context events and values are unidirectional, child context automatically inherit the parents values.

import { Context } from "@borderlesslabs/context";

const context = new Context();
const childContext = new Context(context);

Values

The context provides a way to attach and retrieve values.

context.set("test", true);

context.get("test"); //=> `true`
childContext.get("test"); //=> `true`

childContext.set("test", false);

context.get("test"); //=> `true`
childContext.get("test"); //=> `false`

Events

The standard for async notifications in JavaScript is the event emitter. Based on the browser AbortController, the context has an event emitter available on signal.

context.signal.on("abort", () => {});
childContext.signal.on("abort", () => {});
context.abort(); // Triggers `abort` event.

context.signal.emit("test"); // Propagates to `childContext`.
childContext.signal.emit("test"); // Events are unidirectional, `context` is not triggered.

Example

Tracing is a natural example for context:

// Use a unique symbol for tracing.
const spanKey = Symbol('span');

// Start a new span, and automatically use "parent" span.
export function startSpan(ctx: Context, name: string) {
  const newCtx = new Context(ctx);
  const span = tracer.startSpan(name, {
    childOf: ctx.get(spanKey)
  });
  newCtx.set(spanKey, span);
  return [span, newCtx];
}

// server.js
async function app(req, next) {
  const [span, req.ctx] = startSpan(req.ctx, 'request');

  try {
    return await next();
  } finally {
    span.finish();
  }
}

// middleware.js
async function middleware(req, next) {
  const [span, req.ctx] = startSpan(req.ctx, 'middleware');

  try {
    return await next();
  } finally {
    span.finish();
  }
}

License

MIT