All files / core/blong-gogo/src semanticRecord.ts

98.14% Statements 53/54
66.66% Branches 8/12
100% Functions 2/2
98.14% Lines 53/54

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 551x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 664x 664x 664x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 563x 563x 563x 563x 231x 231x 231x 332x 332x 332x   563x 563x 332x 332x 563x 563x 332x 332x 332x 332x  
/**
 * blong's log calls, in the emitter's record model.
 *
 * The dialect itself is shared — every pino-shaped call shape is translated by
 * `@feasibleone/semantic-log/emitter`'s `toLogCall` — and this adds the one part
 * that is blong's own: the `$meta` envelope, whose `method` and `mtid` the
 * framework's pino formatter printed beside the message.
 */
 
import type {LogCall} from '@feasibleone/semantic-log/emitter';
import {toLogCall as translate} from '@feasibleone/semantic-log/emitter';
 
export type {LogCall};
 
/** Read a string property without letting a non-string through. */
function text(value: unknown): string | undefined {
    return typeof value === 'string' ? value : undefined;
}
 
/**
 * Translate one framework log call's arguments into a message and a field bag.
 *
 * The shared translation runs first, so everything that is not the envelope — a
 * bare message, an `Error`, a bag on its own, the canonical `(bag, message)`
 * order — behaves here exactly as it does for any other emitter user. Then the
 * envelope's two fields become the record's own slots, which is what puts them in
 * the header instead of in the detail beneath it, and they win over the same keys
 * on the bag itself: the envelope is the newer, structured source.
 *
 * The envelope stays in the fields as well, so a reader still sees the request it
 * came from.
 */
export function toLogCall(args: unknown[]): LogCall {
    const call = translate(args);
    const {fields} = call;
    const envelope = fields.$meta;
    if (envelope === undefined) {
        delete fields.$meta;
        return call;
    }
    const meta =
        typeof envelope === 'object' && envelope !== null
            ? (envelope as {mtid?: unknown; method?: unknown})
            : undefined;
    const operation = text(meta?.method) ?? text(fields.operation);
    if (operation !== undefined) {
        fields.operation = operation;
    }
    const messageId = text(meta?.mtid) ?? text(fields.messageId);
    if (messageId !== undefined) {
        fields.messageId = messageId;
    }
    return call;
}