@smb-tech/logger-react 1.0.0

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.
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # @smb-tech/logger-react
2
+
3
+ React/browser adapter for structured logging.
4
+
5
+ ## Features
6
+
7
+ - Client-side context store
8
+ - TraceId propagation to backend
9
+ - Compatible with fetch / axios
10
+ - Lightweight
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @smb-tech/logger-react
16
+ ```
17
+
18
+ ## Example
19
+
20
+ ```ts
21
+ import { BrowserContextStore, BrowserTraceContextFactory } from '@smb-tech/logger-react';
22
+
23
+ const context = BrowserTraceContextFactory.create();
24
+ BrowserContextStore.set(context);
25
+ ```
26
+
27
+ ## Sending trace headers
28
+
29
+ ```ts
30
+ const mdc = BrowserContextStore.getMdc();
31
+
32
+ fetch('/api', {
33
+ headers: {
34
+ 'x-b3-traceid': mdc.traceId
35
+ }
36
+ });
37
+ ```
package/dist/api.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/api.js ADDED
@@ -0,0 +1,30 @@
1
+ export {};
2
+ /* import { BrowserContextStore, BrowserTraceContextFactory } from './context.js';
3
+
4
+ export async function apiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
5
+ if (!BrowserContextStore.get()) {
6
+ BrowserContextStore.set(BrowserTraceContextFactory.create());
7
+ }
8
+
9
+ const mdc = BrowserContextStore.getMdc();
10
+ const headers = new Headers(init?.headers);
11
+
12
+ if (mdc.requestId) {
13
+ headers.set('x-request-id', mdc.requestId);
14
+ }
15
+
16
+ if (mdc.traceId) {
17
+ headers.set('X-B3-TraceId', mdc.traceId);
18
+ }
19
+
20
+ if (mdc.spanId) {
21
+ headers.set('X-B3-SpanId', mdc.spanId);
22
+ }
23
+
24
+ return fetch(input, {
25
+ ...init,
26
+ headers
27
+ });
28
+ }
29
+ */
30
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG"}
@@ -0,0 +1,21 @@
1
+ export interface BrowserTraceContext {
2
+ mdc: Record<string, string>;
3
+ }
4
+ export interface BrowserContextOptions {
5
+ traceId?: string;
6
+ requestId?: string;
7
+ spanId?: string;
8
+ mdc?: Record<string, string>;
9
+ }
10
+ export declare class BrowserTraceContextFactory {
11
+ static create(options?: BrowserContextOptions): BrowserTraceContext;
12
+ }
13
+ export declare class BrowserContextStore {
14
+ private static context;
15
+ static set(context: BrowserTraceContext): void;
16
+ static get(): BrowserTraceContext | null;
17
+ static getMdc(): Record<string, string>;
18
+ static setMdc(key: string, value: string): void;
19
+ static setManyMdc(values: Record<string, string>): void;
20
+ static clear(): void;
21
+ }
@@ -0,0 +1,48 @@
1
+ function createHexId(bytes) {
2
+ const data = new Uint8Array(bytes);
3
+ crypto.getRandomValues(data);
4
+ return Array.from(data, (value) => value.toString(16).padStart(2, '0')).join('');
5
+ }
6
+ export class BrowserTraceContextFactory {
7
+ static create(options) {
8
+ const requestId = options?.requestId ?? crypto.randomUUID();
9
+ const traceId = options?.traceId ?? createHexId(16);
10
+ const spanId = options?.spanId ?? createHexId(8);
11
+ return {
12
+ mdc: {
13
+ requestId,
14
+ traceId,
15
+ spanId,
16
+ ...(options?.mdc ?? {})
17
+ }
18
+ };
19
+ }
20
+ }
21
+ export class BrowserContextStore {
22
+ static context = null;
23
+ static set(context) {
24
+ this.context = context;
25
+ }
26
+ static get() {
27
+ return this.context;
28
+ }
29
+ static getMdc() {
30
+ return this.context?.mdc ?? {};
31
+ }
32
+ static setMdc(key, value) {
33
+ if (!this.context) {
34
+ this.context = { mdc: {} };
35
+ }
36
+ this.context.mdc[key] = value;
37
+ }
38
+ static setManyMdc(values) {
39
+ if (!this.context) {
40
+ this.context = { mdc: {} };
41
+ }
42
+ Object.assign(this.context.mdc, values);
43
+ }
44
+ static clear() {
45
+ this.context = null;
46
+ }
47
+ }
48
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAWA,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,OAAO,0BAA0B;IACrC,MAAM,CAAC,MAAM,CAAC,OAA+B;QAC3C,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QAEjD,OAAO;YACL,GAAG,EAAE;gBACH,SAAS;gBACT,OAAO;gBACP,MAAM;gBACN,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;aACxB;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAC,OAAO,GAA+B,IAAI,CAAC;IAE1D,MAAM,CAAC,GAAG,CAAC,OAA4B;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,GAAG;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,GAAW,EAAE,KAAa;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,MAA8B;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAC7B,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,KAAK;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './context.js';
2
+ export * from './logger.js';
3
+ export * from './provider.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './context.js';
2
+ export * from './logger.js';
3
+ export * from './provider.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Logger } from '@smb-tech/logger-core';
2
+ export declare class ReactLogger {
3
+ static get(contextName: string): Logger;
4
+ }
package/dist/logger.js ADDED
@@ -0,0 +1,29 @@
1
+ import { Logger } from '@smb-tech/logger-core';
2
+ import { BrowserContextStore } from './context.js';
3
+ class BrowserLogSink {
4
+ dispatch(line, level) {
5
+ if (level === 'ERROR' || level === 'WARN') {
6
+ console.error(line);
7
+ return;
8
+ }
9
+ console.log(line);
10
+ }
11
+ }
12
+ class BrowserRuntimeDetailsProvider {
13
+ getThreadLabel() {
14
+ return 'browser-main-thread';
15
+ }
16
+ fallbackId() {
17
+ return crypto.randomUUID();
18
+ }
19
+ }
20
+ const sink = new BrowserLogSink();
21
+ const runtimeDetailsProvider = new BrowserRuntimeDetailsProvider();
22
+ export class ReactLogger {
23
+ static get(contextName) {
24
+ return new Logger(contextName, {
25
+ getMdc: () => BrowserContextStore.getMdc()
26
+ }, sink, runtimeDetailsProvider);
27
+ }
28
+ }
29
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,cAAc;IAClB,QAAQ,CAAC,IAAY,EAAE,KAAe;QACpC,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;CACF;AAED,MAAM,6BAA6B;IACjC,cAAc;QACZ,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAED,UAAU;QACR,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,IAAI,GAAG,IAAI,cAAc,EAAE,CAAC;AAClC,MAAM,sBAAsB,GAAG,IAAI,6BAA6B,EAAE,CAAC;AAEnE,MAAM,OAAO,WAAW;IACtB,MAAM,CAAC,GAAG,CAAC,WAAmB;QAC5B,OAAO,IAAI,MAAM,CACf,WAAW,EACX;YACE,MAAM,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE;SAC3C,EACD,IAAI,EACJ,sBAAsB,CACvB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from 'react';
2
+ interface LoggingProviderProps {
3
+ children: ReactNode;
4
+ }
5
+ export declare function LoggingProvider({ children }: LoggingProviderProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,13 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from 'react';
3
+ import { BrowserContextStore, BrowserTraceContextFactory } from './context.js';
4
+ export function LoggingProvider({ children }) {
5
+ useEffect(() => {
6
+ const existing = BrowserContextStore.get();
7
+ if (!existing) {
8
+ BrowserContextStore.set(BrowserTraceContextFactory.create());
9
+ }
10
+ }, []);
11
+ return _jsx(_Fragment, { children: children });
12
+ }
13
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM/E,MAAM,UAAU,eAAe,CAAC,EAAE,QAAQ,EAAwB;IAChE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC;QAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,mBAAmB,CAAC,GAAG,CAAC,0BAA0B,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,4BAAG,QAAQ,GAAI,CAAC;AACzB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@smb-tech/logger-react",
3
+ "version": "1.0.0",
4
+ "description": "React/browser adapter for structured logging with client-side context management",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc -p tsconfig.json"
21
+ },
22
+ "peerDependencies": {
23
+ "react": "^18.0.0 || ^19.0.0"
24
+ },
25
+ "dependencies": {
26
+ "@smb-tech/logger-core": "1.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/react": "^18.3.20",
30
+ "typescript": "^5.8.2"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }