@holz/console-backend 0.9.1-rc.9 → 0.9.2-rc.0.sha-87f4046

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e={fatal:60,error:50,warn:40,info:30,debug:20,trace:10},t=1e3,n=60*t,r=60*n,i=24*r,a=(e,a=e)=>{let o=e.getTime()-a.getTime(),s=Math.abs(o),c=o<0?``:`+`;return s>=i?`${c}${Math.round(o/i)}d`:s>=r?`${c}${Math.round(o/r)}h`:s>=n?`${c}${Math.round(o/n)}m`:s>=t?`${c}${Math.round(o/t)}s`:`${c}${o}ms`},o=(e={})=>{let t=e.console??console,n;return e=>{let r=new Date(e.timestamp),{error:i,...o}=e.context,c=[{include:!0,format:`%s`,values:[e.message]},{include:Object.keys(o).length>0,format:`%o`,values:[o]},{include:!0,format:`%c%s`,values:[`color: gray`,a(r,n)]},{include:e.origin.length>0,format:`%c%s`,values:[`color: rgba(128, 128, 128, 0.6); font-style: italic`,e.origin.join(`:`)]},{include:i,format:`%o`,values:[i]}].filter(e=>e.include),l=c.map(e=>e.format).join(` `),u=c.flatMap(e=>e.values);t[s[e.level]](l,...u),n=r}},s={[e.trace]:`trace`,[e.debug]:`debug`,[e.info]:`info`,[e.warn]:`warn`,[e.error]:`error`,[e.fatal]:`error`};exports.createConsoleBackend=o;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@holz/core");var t=1e3,n=60*t,r=60*n,i=24*r,a=(e,a=e)=>{let o=e.getTime()-a.getTime(),s=Math.abs(o),c=o<0?``:`+`;return s>=i?`${c}${Math.round(o/i)}d`:s>=r?`${c}${Math.round(o/r)}h`:s>=n?`${c}${Math.round(o/n)}m`:s>=t?`${c}${Math.round(o/t)}s`:`${c}${o}ms`},o=(e={})=>{let t=e.console??console,n;return e=>{let r=new Date(e.timestamp),{error:i,...o}=e.context,c=[{include:!0,format:`%s`,values:[e.message]},{include:Object.keys(o).length>0,format:`%o`,values:[o]},{include:!0,format:`%c%s`,values:[`color: gray`,a(r,n)]},{include:e.origin.length>0,format:`%c%s`,values:[`color: rgba(128, 128, 128, 0.6); font-style: italic`,e.origin.join(`:`)]},{include:i,format:`%o`,values:[i]}].filter(e=>e.include),l=c.map(e=>e.format).join(` `),u=c.flatMap(e=>e.values);t[s[e.level]](l,...u),n=r}},s={[e.level.trace]:`trace`,[e.level.debug]:`debug`,[e.level.info]:`info`,[e.level.warn]:`warn`,[e.level.error]:`error`,[e.level.fatal]:`error`};exports.createConsoleBackend=o;
@@ -1,12 +1,6 @@
1
- //#region ../holz-core/dist/holz-core.js
2
- var e = {
3
- fatal: 60,
4
- error: 50,
5
- warn: 40,
6
- info: 30,
7
- debug: 20,
8
- trace: 10
9
- }, t = 1e3, n = 60 * t, r = 60 * n, i = 24 * r, a = (e, a = e) => {
1
+ import { level as e } from "@holz/core";
2
+ //#region src/time-delta.ts
3
+ var t = 1e3, n = 60 * t, r = 60 * n, i = 24 * r, a = (e, a = e) => {
10
4
  let o = e.getTime() - a.getTime(), s = Math.abs(o), c = o < 0 ? "" : "+";
11
5
  return s >= i ? `${c}${Math.round(o / i)}d` : s >= r ? `${c}${Math.round(o / r)}h` : s >= n ? `${c}${Math.round(o / n)}m` : s >= t ? `${c}${Math.round(o / t)}s` : `${c}${o}ms`;
12
6
  }, o = (e = {}) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holz/console-backend",
3
- "version": "0.9.1-rc.9+7993ae6",
3
+ "version": "0.9.2-rc.0.sha-87f4046",
4
4
  "description": "A console backend for Holz",
5
5
  "type": "module",
6
6
  "repository": {
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "exports": {
12
12
  ".": {
13
+ "source": "./src/index.ts",
13
14
  "types": "./dist/holz-console-backend.d.ts",
14
15
  "require": "./dist/holz-console-backend.cjs",
15
16
  "import": "./dist/holz-console-backend.js"
@@ -22,7 +23,9 @@
22
23
  "license": "MIT",
23
24
  "sideEffects": false,
24
25
  "files": [
25
- "dist"
26
+ "dist",
27
+ "src",
28
+ "!src/**/__tests__"
26
29
  ],
27
30
  "keywords": [
28
31
  "holz-backend",
@@ -37,18 +40,18 @@
37
40
  "test:types": "tsc"
38
41
  },
39
42
  "peerDependencies": {
40
- "@holz/core": "^0.8.0"
43
+ "@holz/core": "^0.8.0 || ^0.9.0"
41
44
  },
42
45
  "devDependencies": {
43
- "@holz/core": "^0.9.1-rc.9+7993ae6",
46
+ "@holz/core": "^0.9.2-rc.0.sha-87f4046",
44
47
  "@microsoft/api-extractor": "^7.58.8",
45
48
  "@types/node": "^24.0.0",
46
- "@vitest/coverage-v8": "^4.0.0",
49
+ "@vitest/coverage-v8": "^5.0.0",
47
50
  "typescript": "^6.0.0",
48
51
  "vite": "^8.0.0",
49
52
  "vite-plugin-dts": "^5.0.0",
50
53
  "vite-tsconfig-paths": "^6.0.0",
51
- "vitest": "^4.0.0"
54
+ "vitest": "^5.0.0"
52
55
  },
53
- "gitHead": "7993ae6757f530d908f8ce2fdd0654767dd3b595"
56
+ "gitHead": "87f40467fe9aa798fa894c04a208751403c45e8c"
54
57
  }
@@ -0,0 +1,81 @@
1
+ import { level, type LogLevel, type Log, type LogProcessor } from '@holz/core';
2
+ import { timeDelta } from './time-delta';
3
+
4
+ /**
5
+ * A backend that pretty-prints logs to a browser console, or any
6
+ * remote-attached console.
7
+ */
8
+ export const createConsoleBackend = (options: Options = {}): LogProcessor => {
9
+ const output = options.console ?? console;
10
+ let lastTimestamp: Date;
11
+
12
+ return (log: Log) => {
13
+ const time = new Date(log.timestamp);
14
+ const { error, ...plainContext } = log.context;
15
+
16
+ const segments = [
17
+ {
18
+ include: true,
19
+ format: '%s',
20
+ values: [log.message],
21
+ },
22
+ {
23
+ include: Object.keys(plainContext).length > 0,
24
+ format: '%o', // Chrome hides object content with `%O`.
25
+ values: [plainContext],
26
+ },
27
+ {
28
+ include: true,
29
+ format: '%c%s',
30
+ values: ['color: gray', timeDelta(time, lastTimestamp)],
31
+ },
32
+ {
33
+ include: log.origin.length > 0,
34
+ format: '%c%s',
35
+ values: [
36
+ 'color: rgba(128, 128, 128, 0.6); font-style: italic',
37
+ log.origin.join(':'),
38
+ ],
39
+ },
40
+ {
41
+ include: error,
42
+ format: '%o',
43
+ values: [error],
44
+ },
45
+ ].filter((segment) => segment.include);
46
+
47
+ const format = segments.map((segment) => segment.format).join(' ');
48
+ const values = segments.flatMap<unknown>((segment) => segment.values);
49
+
50
+ // Browsers have UIs for filtering by log level. Leverage that.
51
+ output[sink[log.level]](format, ...values);
52
+
53
+ // Track the time spent between logs.
54
+ lastTimestamp = time;
55
+ };
56
+ };
57
+
58
+ const sink: Record<LogLevel, keyof MinimalConsole> = {
59
+ [level.trace]: 'trace',
60
+ [level.debug]: 'debug',
61
+ [level.info]: 'info',
62
+ [level.warn]: 'warn',
63
+ [level.error]: 'error',
64
+ [level.fatal]: 'error',
65
+ };
66
+
67
+ interface Options {
68
+ console?: MinimalConsole;
69
+ }
70
+
71
+ /**
72
+ * A subset of the Console interface. Must support printf-style interpolation.
73
+ * @see https://console.spec.whatwg.org/#formatting-specifiers
74
+ *
75
+ * Note that `fatal` has no corresponding equivalent. It will be downgraded to
76
+ * `error` when printed.
77
+ */
78
+ export type MinimalConsole = Pick<
79
+ Console,
80
+ 'trace' | 'debug' | 'info' | 'warn' | 'error'
81
+ >;
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { createConsoleBackend } from './console-backend';
@@ -0,0 +1,33 @@
1
+ const second = 1_000;
2
+ const minute = 60 * second;
3
+ const hour = 60 * minute;
4
+ const day = 24 * hour;
5
+
6
+ /**
7
+ * Formats the difference between two dates in human-readable time.
8
+ *
9
+ * Inspired by the `ms` package. Thanks TJ.
10
+ */
11
+ export const timeDelta = (now: Date, then: Date = now) => {
12
+ const offset = now.getTime() - then.getTime();
13
+ const distance = Math.abs(offset);
14
+ const sign = offset < 0 ? '' : '+';
15
+
16
+ if (distance >= day) {
17
+ return `${sign}${Math.round(offset / day)}d`;
18
+ }
19
+
20
+ if (distance >= hour) {
21
+ return `${sign}${Math.round(offset / hour)}h`;
22
+ }
23
+
24
+ if (distance >= minute) {
25
+ return `${sign}${Math.round(offset / minute)}m`;
26
+ }
27
+
28
+ if (distance >= second) {
29
+ return `${sign}${Math.round(offset / second)}s`;
30
+ }
31
+
32
+ return `${sign}${offset}ms`;
33
+ };