Skip to content

Commit

Permalink
Fix types
Browse files Browse the repository at this point in the history
  • Loading branch information
terehov committed Aug 7, 2023
1 parent 6fa3885 commit f083278
Show file tree
Hide file tree
Showing 16 changed files with 151 additions and 118 deletions.
2 changes: 1 addition & 1 deletion examples/nodejs/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, ILogObj } from "../../src/index";
import { Logger, ILogObj } from "../../src/index.js";

class MyClass {
private readonly _logger: Logger<ILogObj> = new Logger({
Expand Down
2 changes: 1 addition & 1 deletion examples/nodejs/index2.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Logger, BaseLogger } from "../../src/index.js";
import { NodeRuntime } from "../../src/index";
import { NodeRuntime } from "../../src/index.js";

const defaultLogObject: {
name: string;
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"ts-jest": "^28.0.8",
"ts-jest-resolver": "^2.0.0",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
"typescript": "^5.1.6"
},
"sideEffects": false,
"keywords": [
Expand Down
127 changes: 71 additions & 56 deletions src/BaseLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,70 +186,84 @@ export class BaseLogger<LogObj> {

private _recursiveCloneAndMaskValuesOfKeys<T>(source: T, keys: (number | string)[], seen: unknown[] = []): T {
if (seen.includes(source)) {
return { ...source };
return { ...source } as T;
}
if (typeof source === "object" && source != null) {
if (typeof source === "object" && source !== null) {
seen.push(source);
}

return this.runtime.isError(source)
? source // dont copy Error
: this.runtime.isBuffer(source)
? source // dont copy Buffer
: source instanceof Map
? new Map(source)
: source instanceof Set
? new Set(source)
: Array.isArray(source)
? source.map((item) => this._recursiveCloneAndMaskValuesOfKeys(item, keys, seen))
: source instanceof Date
? new Date(source.getTime())
: this.runtime.isError(source)
? Object.getOwnPropertyNames(source).reduce((o, prop) => {
// mask
o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
? this.settings.maskPlaceholder
: this._recursiveCloneAndMaskValuesOfKeys((source as { [key: string]: unknown })[prop], keys, seen);
return o;
}, this._cloneError(source as Error))
: source != null && typeof source === "object"
? Object.getOwnPropertyNames(source).reduce((o, prop) => {
// mask
o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
? this.settings.maskPlaceholder
: this._recursiveCloneAndMaskValuesOfKeys((source as { [key: string]: unknown })[prop], keys, seen);
return o;
}, Object.create(Object.getPrototypeOf(source)))
: ((source: T): T => {
// mask regEx
this.settings?.maskValuesRegEx?.forEach((regEx) => {
source = (source as string)?.toString()?.replace(regEx, this.settings.maskPlaceholder) as T;
});
return source;
})(source);
if (this.runtime.isError(source) || this.runtime.isBuffer(source)) {
return source as T;
} else if (source instanceof Map) {
return new Map(source) as T;
} else if (source instanceof Set) {
return new Set(source) as T;
} else if (Array.isArray(source)) {
return source.map((item) => this._recursiveCloneAndMaskValuesOfKeys(item, keys, seen)) as unknown as T;
} else if (source instanceof Date) {
return new Date(source.getTime()) as T;
} else if (source !== null && typeof source === "object") {
const baseObject = this.runtime.isError(source) ? this._cloneError(source as unknown as Error) : Object.create(Object.getPrototypeOf(source));
return Object.getOwnPropertyNames(source).reduce((o, prop) => {
o[prop] = keys.includes(this.settings?.maskValuesOfKeysCaseInsensitive !== true ? prop : prop.toLowerCase())
? this.settings.maskPlaceholder
: this._recursiveCloneAndMaskValuesOfKeys((source as Record<string, unknown>)[prop], keys, seen);
return o;
}, baseObject) as T;
} else {
if (typeof source === "string") {
let modifiedSource: string = source;
for (const regEx of this.settings?.maskValuesRegEx || []) {
modifiedSource = modifiedSource.replace(regEx, this.settings?.maskPlaceholder || "");
}
return modifiedSource as unknown as T;
}
return source;
}
}

private _recursiveCloneAndExecuteFunctions<T>(source: T, seen: unknown[] = []): T {
if (seen.includes(source)) {
return { ...source };
private _recursiveCloneAndExecuteFunctions<T>(source: T, seen: (object | Array<unknown>)[] = []): T {
if (this.isObjectOrArray(source) && seen.includes(source)) {
return this.shallowCopy(source);
}
if (typeof source === "object") {

if (this.isObjectOrArray(source)) {
seen.push(source);
}

return Array.isArray(source)
? source.map((item) => this._recursiveCloneAndExecuteFunctions(item, seen))
: source instanceof Date
? new Date(source.getTime())
: source && typeof source === "object"
? Object.getOwnPropertyNames(source).reduce((o, prop) => {
Object.defineProperty(o, prop, Object.getOwnPropertyDescriptor(source, prop) as PropertyDescriptor);
// execute functions or clone
o[prop] =
typeof source[prop] === "function" ? source[prop]() : this._recursiveCloneAndExecuteFunctions((source as { [key: string]: unknown })[prop], seen);
return o;
}, Object.create(Object.getPrototypeOf(source)))
: (source as T);
if (Array.isArray(source)) {
return source.map((item) => this._recursiveCloneAndExecuteFunctions(item, seen)) as unknown as T;
} else if (source instanceof Date) {
return new Date(source.getTime()) as unknown as T;
} else if (this.isObject(source)) {
return Object.getOwnPropertyNames(source).reduce((o, prop) => {
const descriptor = Object.getOwnPropertyDescriptor(source, prop);
if (descriptor) {
Object.defineProperty(o, prop, descriptor);
const value = (source as Record<string, unknown>)[prop];
o[prop] = typeof value === "function" ? value() : this._recursiveCloneAndExecuteFunctions(value, seen);
}
return o;
}, Object.create(Object.getPrototypeOf(source))) as T;
} else {
return source;
}
}

private isObjectOrArray(value: unknown): value is object | unknown[] {
return typeof value === "object" && value !== null;
}

private isObject(value: unknown): value is object {
return typeof value === "object" && !Array.isArray(value) && value !== null;
}

private shallowCopy<T>(source: T): T {
if (Array.isArray(source)) {
return [...source] as unknown as T;
} else {
return { ...source } as unknown as T;
}
}

private _toLogObj(args: unknown[], clonedLogObj: LogObj = {} as LogObj): LogObj {
Expand All @@ -270,8 +284,9 @@ export class BaseLogger<LogObj> {
}

private _cloneError<T extends Error>(error: T): T {
type ErrorProperties = keyof Error;
const ErrorConstructor = error.constructor as new (...args: unknown[]) => T;
const errorProperties = Object.getOwnPropertyNames(error);
const errorProperties = Object.getOwnPropertyNames(error) as ErrorProperties[];
const errorArgs = errorProperties.map((propName) => error[propName]);

const newError = new ErrorConstructor(...errorArgs);
Expand Down Expand Up @@ -317,7 +332,7 @@ export class BaseLogger<LogObj> {

let template = this.settings.prettyLogTemplate;

const placeholderValues = {};
const placeholderValues: Record<string, string | number> = {};

// date and time performance fix
if (template.includes("{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}")) {
Expand Down
11 changes: 7 additions & 4 deletions src/formatTemplate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ISettings, TStyle } from "./interfaces.js";
import { ISettings, TStyle, IPrettyLogStyles } from "./interfaces.js";
import { prettyLogStyles } from "./prettyLogStyles.js";

export function formatTemplate<LogObj>(settings: ISettings<LogObj>, template: string, values: { [key: string]: string }, hideUnsetPlaceholder = false) {
export function formatTemplate<LogObj>(settings: ISettings<LogObj>, template: string, values: Record<string, string | number>, hideUnsetPlaceholder = false) {
const templateString = String(template);
const ansiColorWrap = (placeholderValue: string, code: [number, number]) => `\u001b[${code[0]}m${placeholderValue}\u001b[${code[1]}m`;

Expand All @@ -21,8 +21,11 @@ export function formatTemplate<LogObj>(settings: ISettings<LogObj>, template: st
}
};

const defaultStyle: TStyle = null;
return templateString.replace(/{{(.+?)}}/g, (_, placeholder) => {
const value = values[placeholder] != null ? values[placeholder] : hideUnsetPlaceholder ? "" : _;
return settings.stylePrettyLogs ? styleWrap(value, settings?.prettyLogStyles?.[placeholder]) + ansiColorWrap("", prettyLogStyles.reset) : value;
const value = values[placeholder] != null ? String(values[placeholder]) : hideUnsetPlaceholder ? "" : _;
return settings.stylePrettyLogs
? styleWrap(value, settings?.prettyLogStyles?.[placeholder as keyof IPrettyLogStyles] ?? defaultStyle) + ansiColorWrap("", prettyLogStyles.reset)
: value;
});
}
12 changes: 6 additions & 6 deletions src/index.browser.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { BaseLogger } from "./BaseLogger";
import { ILogObj, ILogObjMeta, ISettingsParam } from "./interfaces";
import BrowserRuntime from "./runtime/browser/index";
import { BaseLogger } from "./BaseLogger.js";
import { ILogObj, ILogObjMeta, ISettingsParam } from "./interfaces.js";
import BrowserRuntime from "./runtime/browser/index.js";

export * from "./interfaces";
export * from "./BaseLogger";
export * from "./interfaces.js";
export * from "./BaseLogger.js";
export { BrowserRuntime };

export class Logger<LogObj> extends BaseLogger<LogObj> {
constructor(settings?: ISettingsParam<LogObj>, logObj?: LogObj) {
const isBrowser = ![typeof window, typeof document].includes("undefined");
const isBrowserBlinkEngine = isBrowser ? ((window?.["chrome"] || (window.Intl && Intl?.["v8BreakIterator"])) && "CSS" in window) != null : false;
const isBrowserBlinkEngine = isBrowser ? ((window?.["chrome"] || (window.Intl && ((Intl as unknown as { v8BreakIterator: unknown })?.v8BreakIterator))) && "CSS" in window) != null : false;
const isSafari = isBrowser ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false;

settings = settings || {};
Expand Down
14 changes: 12 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,20 @@ export * from "./interfaces.js";
export * from "./BaseLogger.js";
export { BrowserRuntime, NodeRuntime };

declare global {
interface Window {
chrome?: unknown;
}

interface Intl {
v8BreakIterator?: unknown;
}
}

export class Logger<LogObj> extends BaseLogger<LogObj> {
constructor(settings?: ISettingsParam<LogObj>, logObj?: LogObj) {
const isBrowser = ![typeof window, typeof document].includes("undefined");
const isBrowserBlinkEngine = isBrowser ? ((window?.["chrome"] || (window.Intl && Intl?.["v8BreakIterator"])) && "CSS" in window) != null : false;
const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
const isBrowserBlinkEngine = isBrowser ? window.chrome !== undefined && window.CSS !== undefined && window.CSS.supports("color", "green") : false;
const isSafari = isBrowser ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false;

settings = settings || {};
Expand Down
44 changes: 23 additions & 21 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ export type TStyle =
[value: string]: null | string | string[];
};

export interface IPrettyLogStyles {
yyyy?: TStyle;
mm?: TStyle;
dd?: TStyle;
hh?: TStyle;
MM?: TStyle;
ss?: TStyle;
ms?: TStyle;
dateIsoStr?: TStyle;
logLevelName?: TStyle;
fileName?: TStyle;
filePath?: TStyle;
fileLine?: TStyle;
filePathWithLine?: TStyle;
name?: TStyle;
nameWithDelimiterPrefix?: TStyle;
nameWithDelimiterSuffix?: TStyle;
errorName?: TStyle;
errorMessage?: TStyle;
}

export interface ISettingsParam<LogObj> {
type?: "json" | "pretty" | "hidden";
name?: string;
Expand All @@ -23,26 +44,7 @@ export interface ISettingsParam<LogObj> {
prettyErrorLoggerNameDelimiter?: string;
stylePrettyLogs?: boolean;
prettyLogTimeZone?: "UTC" | "local";
prettyLogStyles?: {
yyyy?: TStyle;
mm?: TStyle;
dd?: TStyle;
hh?: TStyle;
MM?: TStyle;
ss?: TStyle;
ms?: TStyle;
dateIsoStr?: TStyle;
logLevelName?: TStyle;
fileName?: TStyle;
filePath?: TStyle;
fileLine?: TStyle;
filePathWithLine?: TStyle;
name?: TStyle;
nameWithDelimiterPrefix?: TStyle;
nameWithDelimiterSuffix?: TStyle;
errorName?: TStyle;
errorMessage?: TStyle;
};
prettyLogStyles?: IPrettyLogStyles;
prettyInspectOptions?: InspectOptions;
metaProperty?: string;
maskPlaceholder?: string;
Expand All @@ -55,7 +57,7 @@ export interface ISettingsParam<LogObj> {
/** Array of attached Transports. Use Method `attachTransport` to attach transports. */
attachedTransports?: ((transportLogger: LogObj & ILogObjMeta) => void)[];
overwrite?: {
addPlaceholders?: (logObjMeta: IMeta, placeholderValues: Record<string, string>) => void;
addPlaceholders?: (logObjMeta: IMeta, placeholderValues: Record<string, string | number>) => void;
mask?: (args: unknown[]) => unknown[];
toLogObj?: (args: unknown[], clonesLogObj?: LogObj) => LogObj;
addMeta?: (logObj: LogObj, logLevelId: number, logLevelName: string) => LogObj & ILogObjMeta;
Expand Down
Loading

0 comments on commit f083278

Please sign in to comment.