All files / logger/src stream.ts

100% Statements 18/18
100% Branches 9/9
100% Functions 7/7
100% Lines 18/18

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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89                                      71x 15x 85x   71x               71x 705x 5824x   71x               71x 2393x             71x                 71x   1672x 71x               71x           201x               201x   71x  
import type { JsonRpcCall, JsonRpcMessage } from '@metamask/kernel-utils';
import { split } from '@metamask/streams';
import type { DuplexStream } from '@metamask/streams';
import { isJsonRpcNotification } from '@metamask/utils';
 
import { TOKEN_UNDEFINED } from './constants.ts';
import type { LogEntry } from './types.ts';
 
export type LogMessage = JsonRpcCall & {
  method: 'notify';
  params: ['logger', string];
};
 
/**
 * Serializes a log entry.
 *
 * @param entry - The log entry to serialize.
 * @returns The serialized log entry.
 */
export const lser = (entry: LogEntry): string =>
  JSON.stringify(entry, (_key, value) =>
    value === undefined ? TOKEN_UNDEFINED : value,
  );
harden(lser);
 
/**
 * Deserializes a log entry.
 *
 * @param serializedEntry - The serialized log entry to deserialize.
 * @returns The deserialized log entry.
 */
export const lunser = (serializedEntry: string): LogEntry =>
  JSON.parse(serializedEntry, (_key, value) =>
    value === TOKEN_UNDEFINED ? undefined : value,
  ) as LogEntry;
harden(lunser);
 
/**
 * Checks if a message is a logger message.
 *
 * @param message - The message to check.
 * @returns Whether the message is a logger message.
 */
export const isLoggerMessage = (
  message: JsonRpcMessage,
): message is LogMessage =>
  isJsonRpcNotification(message) &&
  Array.isArray(message.params) &&
  message.params.length > 0 &&
  message.params[0] === 'logger' &&
  typeof message.params[1] === 'string';
harden(isLoggerMessage);
 
/**
 * Checks if a message is a kernel message. A kernel message is any message
 * which is not a logger message.
 *
 * @param message - The message to check.
 * @returns Whether the message is a kernel message.
 */
export const isKernelMessage = (
  message: JsonRpcMessage,
): message is JsonRpcMessage => !isLoggerMessage(message);
harden(isKernelMessage);
 
/**
 * Splits a stream into a kernel stream and a logger stream.
 *
 * @param stream - The stream to split.
 * @returns An object containing the kernel stream and the logger stream.
 */
export const splitLoggerStream = <Write>(
  stream: DuplexStream<JsonRpcMessage, Write>,
): {
  kernelStream: DuplexStream<JsonRpcMessage, Write>;
  loggerStream: DuplexStream<JsonRpcMessage, Write>;
} => {
  const [kernelStream, loggerStream] = split(
    stream,
    isKernelMessage,
    isLoggerMessage,
  ) as [
    DuplexStream<JsonRpcMessage, Write>,
    DuplexStream<JsonRpcMessage, Write>,
  ];
  return { kernelStream, loggerStream };
};
harden(splitLoggerStream);