Skip to content

Instantly share code, notes, and snippets.

@typeofweb
Last active May 1, 2020 23:39
Show Gist options
  • Save typeofweb/c69ef6e6a580f425af3250b67d60d214 to your computer and use it in GitHub Desktop.
Save typeofweb/c69ef6e6a580f425af3250b67d60d214 to your computer and use it in GitHub Desktop.
Hapi plugin for CLS
// Thanks to https://gist.github.com/quezak/0a9f33d20aa0c13fd86f547f75d9da47
import { Plugin } from '@hapi/hapi';
import {
contextNs,
setContext,
getContext,
updateContext,
USER_CONTEXT_KEY,
} from './hapi-zcontext';
import uuid from 'uuid';
declare module '@hapi/hapi' {
interface PluginProperties {
cls: {
setContext: typeof setContext;
getContext: typeof getContext;
updateContext: typeof updateContext;
};
}
}
export const cls: Plugin<{}> = {
multiple: false,
name: 'cls',
version: '1.0.0',
async register(server, _options) {
server.expose('setContext', setContext);
server.expose('getContext', getContext);
server.expose('updateContext', updateContext);
server.ext('onRequest', (request, h) => {
contextNs.bindEmitter(request.raw.req);
contextNs.bindEmitter(request.raw.res);
return contextNs.runPromise(async () => {
request.server.plugins.cls.setContext(USER_CONTEXT_KEY, { currentRequestID: uuid.v4() });
return h.continue;
});
});
server.ext('onPostAuth', (request, h) => {
if (request.auth.credentials?.data) {
updateContext(USER_CONTEXT_KEY, {
user: request.auth.credentials.data.session._user.email,
});
}
return h.continue;
});
server.events.on('response', () => {
});
},
};
import { clsProxifyNamespace } from 'cls-proxify';
import { User } from '../../models/User';
export const USER_CONTEXT_KEY = 'XHQ_API_CONTEXT';
export const contextNs = clsProxifyNamespace;
interface ContextData {
currentRequestID?: string;
userEmail?: User;
}
export function setContext<T>(
name: typeof USER_CONTEXT_KEY,
updates: ContextData
): ContextData | undefined;
export function setContext<T>(name: string, values: T): T | undefined;
export function setContext<T>(name: string, values: T): T | undefined {
return contextNs.active ? contextNs.set(name, values) : undefined;
}
export function updateContext<T>(
name: typeof USER_CONTEXT_KEY,
updates: ContextData
): ContextData | undefined;
export function updateContext<T>(name: string, updates: T): T | undefined;
export function updateContext<T>(name: string, updates: T): T | undefined {
const context = getContext<T>(name) ?? setContext<T>(name, updates);
if (!context) {
return undefined;
}
Object.assign(context, updates);
return context;
}
export function getContext<T>(name: typeof USER_CONTEXT_KEY): ContextData | undefined;
export function getContext<T>(name: string): T | undefined;
export function getContext<T>(name: string): T | undefined {
return contextNs.active ? contextNs.get(name) : undefined;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment