diff --git a/package.json b/package.json index ac8b01c..33639b8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zeed", "type": "module", - "version": "0.25.3", + "version": "0.25.4", "description": "🌱 Simple foundation library", "author": { "name": "Dirk Holtwick", @@ -69,19 +69,19 @@ "watch": "nr build -- --watch src" }, "devDependencies": { - "@antfu/eslint-config": "^3.7", + "@antfu/eslint-config": "^3.8", "@antfu/ni": "^0.23.0", - "@types/node": "^22.7.5", + "@types/node": "^22.8.1", "@vitejs/plugin-vue": "^5.1.4", - "@vitest/browser": "^2.1.2", - "@vitest/coverage-v8": "^2.1.2", + "@vitest/browser": "^2.1.3", + "@vitest/coverage-v8": "^2.1.3", "esbuild": "^0.24.0", "eslint": "^9", - "playwright": "^1.48.0", - "tsup": "^8.3.0", + "playwright": "^1.48.2", + "tsup": "^8.3.5", "typescript": "^5.6.3", - "vite": "^5.4.8", - "vitest": "^2.1.2" + "vite": "^5.4.10", + "vitest": "^2.1.3" }, "pnpm": { "overrides": { diff --git a/src/common/data/convert.spec.ts b/src/common/data/convert.spec.ts index 196b4ce..462ef2d 100644 --- a/src/common/data/convert.spec.ts +++ b/src/common/data/convert.spec.ts @@ -1,4 +1,4 @@ -import { renderMessages, valueToBoolean, valueToBooleanNotFalse, valueToInteger, valueToString } from './convert' +import { valueToBoolean, valueToBooleanNotFalse, valueToInteger, valueToString } from './convert' describe('convert', () => { it('should convert', () => { @@ -7,29 +7,7 @@ describe('convert', () => { expect(valueToInteger('123')).toBe(123) expect(valueToInteger(true)).toBe(1) }) - - it('should print errors', () => { - expect(renderMessages(['Message', new Error('Hello')])).toContain( - 'Message Error: Hello', - ) - expect( - renderMessages(['Message', new Error('Hello')], { trace: false }), - ).toBe('Message Error: Hello') - expect( - renderMessages([ - 'Message', - { a: 1, b: null }, - null, - undefined, - Number.NaN, - 1e2, - 'string', - ]), - ).toEqual(`Message { - \"a\": 1, - \"b\": null -} null undefined NaN 100 string`) - }) + it('should have some bias', async () => { expect(valueToBoolean('123')).toBe(false) diff --git a/src/common/data/convert.ts b/src/common/data/convert.ts index 12a2261..c1215ce 100644 --- a/src/common/data/convert.ts +++ b/src/common/data/convert.ts @@ -90,48 +90,6 @@ export const toInt = valueToInteger export const toString = valueToString export const toBool = valueToBoolean -// Strings - -export interface RenderMessagesOptions { - trace?: boolean // = true - pretty?: boolean // = true -} - -export function formatMessages( - messages: any[], - opt: RenderMessagesOptions = {}, -): any[] { - const { trace = true, pretty = true } = opt - return messages.map((obj) => { - if (obj && typeof obj === 'object') { - if (pretty && (obj instanceof Uint8Array || obj instanceof ArrayBuffer)) - return `\n${Uint8ArrayToHexDump(obj)}\n` - if (typeof ErrorEvent !== 'undefined' && obj instanceof ErrorEvent) { - obj = obj.error - } - if (obj instanceof Error) { - if (!trace) - return `${obj.name || 'Error'}: ${obj.message}` - return `${obj.name || 'Error'}: ${obj.message}\n${obj.stack}` - } - try { - obj = objectPlain(obj) - return pretty ? JSON.stringify(obj, null, 2) : JSON.stringify(obj) - } - catch (err) {} - } - return String(obj) - }) -} - -export function renderMessages( - messages: any[], - opt: RenderMessagesOptions = {}, -): string { - return formatMessages(messages, opt).join(' ') -} - -// // Awesome trick from https://stackoverflow.com/a/5396742/140927 export function fixBrokenUtf8String(brokenString: string): string { diff --git a/src/common/data/index.ts b/src/common/data/index.ts index d79d9f4..f7f90af 100644 --- a/src/common/data/index.ts +++ b/src/common/data/index.ts @@ -16,6 +16,7 @@ export * from './is' export * from './json' export * from './list' export * from './math' +export * from './message' export * from './object-changes' export * from './object' export * from './orderby' diff --git a/src/common/data/message.spec.ts b/src/common/data/message.spec.ts new file mode 100644 index 0000000..52c3768 --- /dev/null +++ b/src/common/data/message.spec.ts @@ -0,0 +1,38 @@ +import { renderMessages } from './message' + +describe('message', () => { + + it('should print errors', () => { + expect(renderMessages(['Message', new Error('Hello')], { trace: false })).toMatchInlineSnapshot(`"Message Error: Hello"`) + + expect(renderMessages(['Message', new Error('Hello')], { trace: false }),).toMatchInlineSnapshot(`"Message Error: Hello"`) + + expect( + renderMessages([ + 'Message', + { a: 1, b: null }, + null, + undefined, + Number.NaN, + 1e2, + 'string', + ], { trace: false }), + ).toMatchInlineSnapshot(` + "Message { + "a": 1, + "b": null + } null undefined NaN 100 string" + `) + + // it('should handle promise rejection', async () => { + // let promise = new Promise((_, reject) => reject(new Error('Hello'))) + // let myRejectionEvent = new PromiseRejectionEvent("unhandledrejection", { + // promise, + // reason: "My house is on fire", + // }) + + // expect(renderMessages(myRejectionEvent)).toMatchInlineSnapshot() + + }) + +}) diff --git a/src/common/data/message.ts b/src/common/data/message.ts new file mode 100644 index 0000000..e6b1217 --- /dev/null +++ b/src/common/data/message.ts @@ -0,0 +1,48 @@ +import { Uint8ArrayToHexDump } from "./bin" +import { isArray } from "./is" +import { objectPlain } from "./object" + +export interface RenderMessagesOptions { + trace?: boolean // = true + pretty?: boolean // = true +} + +export function formatMessages( + messages: any[], + opt: RenderMessagesOptions = {}, +): any[] { + const { trace = true, pretty = true } = opt + return messages.map((obj) => { + if (obj && typeof obj === 'object') { + if (pretty && (obj instanceof Uint8Array || obj instanceof ArrayBuffer)) + return `\n${Uint8ArrayToHexDump(obj)}\n` + + if (obj instanceof Error) { + return `${obj.name}: ${obj.message}` + (trace ? `\n${obj.stack}` : '') + } + if (typeof ErrorEvent !== 'undefined' && obj instanceof ErrorEvent) { + return `${obj.error.name || 'ErrorEvent'}: ${obj.error.message}` + (trace ? `\n${obj.error.stack}` : '') + } + if (typeof DOMException !== 'undefined' && obj instanceof DOMException) { + return `${obj.name || 'DOMException'}: ${obj.message}` + (trace ? `\n${obj.stack}` : '') + } + if (obj && typeof obj === 'object' && 'reason' in obj) { + return `PromiseRejection ${obj.type}: ${obj.reason}` + (trace ? `\n${obj.stack}` : '') + } + + try { + obj = objectPlain(obj) + return pretty ? JSON.stringify(obj, null, 2) : JSON.stringify(obj) + } + catch (err) {} + } + return String(obj) + }) +} + +export function renderMessages( + messages: any | any[], + opt: RenderMessagesOptions = {}, +): string { + return formatMessages(isArray(messages) ? messages : [messages], opt).join(' ') +} diff --git a/src/common/eslint-defaults.js b/src/common/eslint-defaults.js index d18feac..ff498cc 100644 --- a/src/common/eslint-defaults.js +++ b/src/common/eslint-defaults.js @@ -61,7 +61,7 @@ export function eslintDefaults(opt) { return { vue: true, typescript: true, - // regexp: false, + regexp: true, ...rest, diff --git a/src/common/msg/rpc.ts b/src/common/msg/rpc.ts index a21411b..4ef8d04 100644 --- a/src/common/msg/rpc.ts +++ b/src/common/msg/rpc.ts @@ -45,17 +45,17 @@ export type RPCReturn = { let rpcCounter = 1 -enum RPCMode { +export enum RPCMode { request = 1, event = 2, resolve = 3, reject = 4, } -type RPCMessage = [ - RPCMode, - number, - string | number | any, +export type RPCMessage = [ + mode: RPCMode, + id: number, + method: string | number | any, ...any, ] diff --git a/src/node/log/log-file.ts b/src/node/log/log-file.ts index 90b94da..c8c3c6d 100644 --- a/src/node/log/log-file.ts +++ b/src/node/log/log-file.ts @@ -2,7 +2,7 @@ import type { LogHandlerOptions, LogMessage } from '../../common/log/log-base' import { createWriteStream, mkdirSync } from 'node:fs' import { dirname, resolve } from 'node:path' import process from 'node:process' -import { renderMessages } from '../../common/data/convert' +import { renderMessages } from '../../common/data/message' import { LogLevelError, LogLevelInfo, LogLevelWarn } from '../../common/log/log-base' import { useLevelFilter, useNamespaceFilter } from '../../common/log/log-filter' diff --git a/src/node/log/log-node.ts b/src/node/log/log-node.ts index 13d5f2d..a84dfea 100644 --- a/src/node/log/log-node.ts +++ b/src/node/log/log-node.ts @@ -1,7 +1,8 @@ import type { LogHandler, LogHandlerOptions, LogMessage } from '../../common/log/log-base' import process from 'node:process' import tty from 'node:tty' -import { renderMessages, valueToBoolean } from '../../common/data/convert' +import { valueToBoolean } from '../../common/data/convert' +import { renderMessages } from '../../common/data/message' import { LogLevelError, LogLevelInfo, LogLevelWarn } from '../../common/log/log-base' import { useLevelFilter, useNamespaceFilter } from '../../common/log/log-filter' import { formatMilliseconds, getTimestamp } from '../../common/time' diff --git a/tsconfig.json b/tsconfig.json index 29ef9b7..8226f94 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,9 @@ "resolveJsonModule": true, "types": [ "node", - "vitest/globals" + "vitest/globals", + "@vitest/browser/providers/webdriverio", + "@vitest/browser/providers/playwright" ], "allowJs": true, "strict": true,