@clipboard-health/execution-context
Version:
A lightweight Node.js utility for managing execution contexts and metadata aggregation using AsyncLocalStorage.
92 lines • 3.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getExecutionContext = getExecutionContext;
exports.runWithExecutionContext = runWithExecutionContext;
exports.newExecutionContext = newExecutionContext;
exports.addMetadataToLocalContext = addMetadataToLocalContext;
exports.addToMetadataList = addToMetadataList;
exports.addToMetadataRecord = addToMetadataRecord;
require("../types/global");
const node_async_hooks_1 = require("node:async_hooks");
const util_1 = require("./util");
globalThis.threadLocalStorage ||= new node_async_hooks_1.AsyncLocalStorage();
function getAsyncLocalStorage() {
return globalThis.threadLocalStorage;
}
function getExecutionContext() {
return getAsyncLocalStorage().getStore();
}
async function runWithExecutionContext(context, callback) {
return await new Promise((resolve, reject) => {
getAsyncLocalStorage().run(context, () => {
try {
// eslint-disable-next-line promise/prefer-await-to-then
Promise.resolve(callback()).then(resolve).catch(reject); // oxlint-disable-line node/callback-return
}
catch (error) {
// oxlint-disable-next-line typescript/prefer-promise-reject-errors -- re-throwing caught error
reject(error);
}
});
});
}
/**
* This function is simply a convenience to initialize an empty context object
* @param source - The class/service that initializes the context
*/
function newExecutionContext(source) {
return {
source,
metadata: {},
};
}
/**
* A utility function that will add metadata to the current context
* @param metadata - the metadata (key-value pair), to be added to the context
*/
function addMetadataToLocalContext(metadata) {
const context = getExecutionContext();
if (context) {
context.metadata = { ...context.metadata, ...metadata };
}
}
function getMetadataListByKey(key) {
const context = getExecutionContext();
if (context?.metadata && key in context.metadata) {
const metadataForKey = context.metadata[key];
if (Array.isArray(metadataForKey)) {
return metadataForKey;
}
}
return [];
}
/**
* A utility function that will add metadata to the list under current context's key
* @param key - the list's key (string) in the context
* @param metadata - the metadata (key-value pair), to be added to the context
*/
function addToMetadataList(key, metadata) {
const metadataList = [...getMetadataListByKey(key), metadata];
addMetadataToLocalContext({ [key]: metadataList });
}
function getMetadataRecordByKey(key) {
const context = getExecutionContext();
if (context?.metadata && key in context.metadata) {
const metadataForKey = context.metadata[key];
if ((0, util_1.isRecord)(metadataForKey)) {
return metadataForKey;
}
}
return {};
}
/**
* A utility function that will add metadata to the record under current context's key,
* supporting nested records.
* @param key - the record's key (string) in the context
* @param metadata - the metadata (key-value pair), to be added to the context
*/
function addToMetadataRecord(key, metadata) {
const metadataRecord = { ...getMetadataRecordByKey(key), ...metadata };
addMetadataToLocalContext({ [key]: metadataRecord });
}
//# sourceMappingURL=contextStore.js.map