Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
unctx
Advanced tools
Changelog
v2.3.1
Readme
Composition-API in Vanilla js
Vue.js introduced an amazing pattern called Composition API that allows organizing complex logic by splitting it into reusable functions and grouping in logical order. unctx
allows easily implementing composition API pattern in your javascript libraries without hassle.
In your awesome library:
yarn add unctx
# or
npm install unctx
import { createContext } from "unctx";
const ctx = createContext();
export const useAwesome = ctx.use;
// ...
ctx.call({ test: 1 }, () => {
// This is similar to the vue setup function
// Any function called here can use `useAwesome` to get { test: 1 }
});
User code:
import { useAwesome } from "awesome-lib";
// ...
function setup() {
const ctx = useAwesome();
}
Note: When no context is presented ctx.use
will throw an error. Use ctx.tryUse
for tolerant usages (return nullable context).
To avoid issues with multiple version of the library, unctx
provides a safe global namespace to access context by key (kept in globalThis
). Important: Please use a verbose name for the key to avoid conflict with other js libraries. Using the npm package name is recommended. Using symbols has no effect since it still causes multiple context issues.
import { useContext, getContext } from "unctx";
const useAwesome = useContext("awesome-lib");
// or
// const awesomeContext = getContext('awesome-lib')
You can also create your internal namespace with createNamespace
utility for more advanced use cases.
Using context is only possible in non-async usages and only before the first await statement. This is to make sure context is not shared between concurrent calls.
async function setup() {
console.log(useAwesome()); // Returns context
setTimeout(() => {
console.log(useAwesome());
}, 1); // Returns null
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(useAwesome()); // Returns null
}
A simple workaround is caching context into a local variable:
async function setup() {
const ctx = useAwesome(); // We can directly access cached version of ctx
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(ctx);
}
This is not always an elegant and easy way by making a variable and passing it around. After all, this is the purpose of unctx to make sure context is magically available everywhere in composables!
Unctx supports Node.js AsyncLocalStorage
as a native way to preserve and track async contexts. To enable this mode, you need to set asyncContext: true
option and also provides an implementation for AsyncLocalStorage
(or provide globalThis.AsyncLocalStorage
polyfill).
See tc39 proposal for async context and cloudflare docs for relevant platform specific docs.
import { createContext } from "unctx";
import { AsyncLocalStorage } from "node:async_hooks";
const ctx = createContext({
asyncContext: true,
AsyncLocalStorage,
});
ctx.call("123", () => {
setTimeout(() => {
// Prints 123
console.log(ctx.use());
}, 100);
});
Since native async context is not supported in all platforms yet, unctx provides a build-time solution that transforms async syntax to automatically restore context after each async/await statement. This requires using a bundler such as Rollup, Vite, or Webpack.
Import and register transform plugin:
import { unctxPlugin } from "unctx/plugin";
// Rollup
// TODO: Add to rollup configuration
unctxPlugin.rollup();
// Vite
// TODO: Add to vite configuration
unctxPlugin.vite();
// Webpack
// TODO: Add to webpack configuration
unctxPlugin.webpack();
Use ctx.callAsync
instead of ctx.call
:
await ctx.callAsync("test", setup);
Any async function that requires context, should be wrapped with withAsyncContext
:
import { withAsyncContext } from "unctx";
const setup = withAsyncContext(async () => {
console.log(useAwesome()); // Returns context
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(useAwesome()); // Still returns context with dark magic!
});
If you are sure it is safe to use a shared instance (not depending to request), you can also use ctx.set
and ctx.unset
for a singleton pattern.
Note: You cannot combine set
with call
. Always use unset
before replacing the instance otherwise you will get Context conflict
error.
import { createContext } from "unctx";
const ctx = createContext();
ctx.set(new Awesome());
// Replacing instance without unset
// ctx.set(new Awesome(), true)
export const useAwesome = ctx.use;
A generic type exists on all utilities to be set for instance/context type for typescript support.
// Return type of useAwesome is Awesome | null
const { use: useAwesome } = createContext<Awesome>();
The composition of functions is possible using temporary context injection. When calling ctx.call(instance, cb)
, instance
argument will be stored in a temporary variable then cb
is called. Any function inside cb
, can then implicitly access the instance by using ctx.use
(or useAwesome
)
context can be only used before first await:
Please check Async Context section.
Context conflict
error:
In your library, you should only keep one call()
running at a time (unless calling with the same reference for the first argument)
For instance, this makes an error:
ctx.call({ test: 1 }, () => {
ctx.call({ test: 2 }, () => {
// Throws error!
});
});
MIT. Made with 💖
FAQs
Composition-api in Vanilla js
The npm package unctx receives a total of 480,747 weekly downloads. As such, unctx popularity was classified as popular.
We found that unctx demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.