@noego/wood 0.0.4 → 0.1.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.
Files changed (62) hide show
  1. package/README.md +9 -0
  2. package/bin/wood.js +2 -1
  3. package/dist/client/controller_contract.cjs.map +1 -1
  4. package/dist/client/controller_contract.d.cts +4 -2
  5. package/dist/client/controller_contract.d.ts +4 -2
  6. package/dist/client/index.cjs +10 -0
  7. package/dist/client/index.cjs.map +1 -1
  8. package/dist/client/index.d.cts +2 -1
  9. package/dist/client/index.d.ts +2 -1
  10. package/dist/client/index.js +11 -1
  11. package/dist/client/index.js.map +1 -1
  12. package/dist/codegen/preload_generator.cjs +26 -0
  13. package/dist/codegen/preload_generator.cjs.map +1 -1
  14. package/dist/codegen/preload_generator.js +26 -0
  15. package/dist/codegen/preload_generator.js.map +1 -1
  16. package/dist/controller/controller_lifecycle.cjs +37 -0
  17. package/dist/controller/controller_lifecycle.cjs.map +1 -0
  18. package/dist/controller/controller_lifecycle.d.cts +10 -0
  19. package/dist/controller/controller_lifecycle.d.ts +10 -0
  20. package/dist/controller/controller_lifecycle.js +13 -0
  21. package/dist/controller/controller_lifecycle.js.map +1 -0
  22. package/dist/controller/index.cjs +5 -2
  23. package/dist/controller/index.cjs.map +1 -1
  24. package/dist/controller/index.d.cts +1 -0
  25. package/dist/controller/index.d.ts +1 -0
  26. package/dist/controller/index.js +3 -1
  27. package/dist/controller/index.js.map +1 -1
  28. package/dist/index.cjs +4 -0
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +2 -1
  31. package/dist/index.d.ts +2 -1
  32. package/dist/index.js +5 -2
  33. package/dist/index.js.map +1 -1
  34. package/dist/main/index.cjs +20 -0
  35. package/dist/main/index.cjs.map +1 -1
  36. package/dist/main/index.d.cts +1 -0
  37. package/dist/main/index.d.ts +1 -0
  38. package/dist/main/index.js +21 -0
  39. package/dist/main/index.js.map +1 -1
  40. package/dist/router/wood_router.cjs +36 -11
  41. package/dist/router/wood_router.cjs.map +1 -1
  42. package/dist/router/wood_router.js +36 -11
  43. package/dist/router/wood_router.js.map +1 -1
  44. package/dist/testing/create_controller_harness.cjs +3 -4
  45. package/dist/testing/create_controller_harness.cjs.map +1 -1
  46. package/dist/testing/create_controller_harness.d.cts +1 -1
  47. package/dist/testing/create_controller_harness.d.ts +1 -1
  48. package/dist/testing/create_controller_harness.js +3 -4
  49. package/dist/testing/create_controller_harness.js.map +1 -1
  50. package/dist/tracing/index.cjs +4 -2
  51. package/dist/tracing/index.cjs.map +1 -1
  52. package/dist/tracing/index.d.cts +1 -1
  53. package/dist/tracing/index.d.ts +1 -1
  54. package/dist/tracing/index.js +3 -1
  55. package/dist/tracing/index.js.map +1 -1
  56. package/dist/tracing/trace_hub.cjs +18 -6
  57. package/dist/tracing/trace_hub.cjs.map +1 -1
  58. package/dist/tracing/trace_hub.d.cts +2 -1
  59. package/dist/tracing/trace_hub.d.ts +2 -1
  60. package/dist/tracing/trace_hub.js +16 -5
  61. package/dist/tracing/trace_hub.js.map +1 -1
  62. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/create_controller_harness.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport {\n App,\n clearClientAppForTests,\n clearClientContainerForTests,\n clearClientLoggersForTests,\n clearClientNavigationForTests,\n clearClientWindowControlsForTests,\n getApp,\n getWindowControls,\n Ipc,\n WOOD_INTERNAL_BRIDGE_KEY,\n} from '../client/index.js';\nimport { getIpc } from '../ipc/index.js';\nimport { Navigation, getNavigation } from '../navigation/index.js';\nimport { TraceProvider, TraceProviderConfiguration } from '../tracing/index.js';\nimport { parseOperations } from '../parser/operations_parser.js';\nimport type { OperationDef } from '../types/operations.js';\nimport { createRouterBridge, type RouterBridgeResult } from './create_router_bridge.js';\nimport { createTestRouter } from './create_test_router.js';\n\nexport interface CreateControllerHarnessOptions<T> {\n controllerClass: new (...args: any[]) => T;\n container: any;\n operations: string | string[];\n controllersDir: string;\n middlewareDir?: string;\n configureContainer?: (container: any) => void | Promise<void>;\n configureRouter?: (router: ReturnType<typeof createTestRouter>['router']) => void | Promise<void>;\n prepareClient?: (context: {\n bridge: Record<string, any>;\n events: RouterBridgeResult['events'];\n navigation: Navigation;\n container: any;\n }) => void | Promise<void>;\n initialize?: boolean;\n}\n\nexport interface ControllerHarnessResult<T> extends RouterBridgeResult {\n controller: T;\n container: any;\n router: ReturnType<typeof createTestRouter>['router'];\n navigation: Navigation;\n trace: TraceProvider;\n destroy: () => void;\n}\n\ntype MutableGlobal = typeof globalThis & {\n [WOOD_INTERNAL_BRIDGE_KEY]?: unknown;\n wood?: unknown;\n};\n\nfunction readOperations(input: string): Map<string, OperationDef> {\n if (input.includes('\\n') || input.includes(':')) {\n return parseOperations(input);\n }\n\n return parseOperations(readFileSync(input, 'utf-8'));\n}\n\nfunction mergeOperations(inputs: string | string[]): Map<string, OperationDef> {\n const merged = new Map<string, OperationDef>();\n\n for (const input of Array.isArray(inputs) ? inputs : [inputs]) {\n for (const [channel, operation] of readOperations(input)) {\n merged.set(channel, operation);\n }\n }\n\n return merged;\n}\n\nfunction createRpcManifest(operations: Map<string, OperationDef>) {\n return Array.from(operations.values()).map((operation) => ({\n channel: operation.channel,\n controller: operation.controller,\n action: operation.action,\n path: operation.channel.split('.'),\n hasInput: !!operation.inputSchema,\n }));\n}\n\nfunction registerClientBuiltins(container: any): void {\n if (typeof container.registerFunction !== 'function') {\n return;\n }\n\n const traceConfiguration = new TraceProviderConfiguration();\n traceConfiguration.configureMode('test');\n traceConfiguration.configureRuntime('renderer');\n\n container.registerFunction(Navigation, () => getNavigation());\n container.registerFunction(App, () => getApp());\n container.registerFunction(Ipc, () => getIpc());\n container.registerFunction(WindowControls, () => getWindowControls());\n container.registerFunction(TraceProviderConfiguration, () => traceConfiguration);\n}\n\nclass WindowControls {\n async open(_windowId: string, _options?: Record<string, unknown>): Promise<void> {}\n async close(_windowId?: string): Promise<void> {}\n async focus(_windowId: string): Promise<void> {}\n async minimize(_windowId?: string): Promise<void> {}\n async maximize(_windowId?: string): Promise<void> {}\n}\n\nexport async function createControllerHarness<T>(\n options: CreateControllerHarnessOptions<T>,\n): Promise<ControllerHarnessResult<T>> {\n await options.configureContainer?.(options.container);\n\n if (typeof options.container.instance === 'function') {\n const rootTraceConfiguration = await options.container.instance(TraceProviderConfiguration);\n rootTraceConfiguration.configureMode('test');\n rootTraceConfiguration.configureRuntime('main');\n }\n\n const operations = mergeOperations(options.operations);\n const { router } = createTestRouter('', {\n container: options.container,\n controllersDir: options.controllersDir,\n middlewareDir: options.middlewareDir,\n });\n router.loadOperations(operations);\n await options.configureRouter?.(router);\n\n const { bridge, events } = createRouterBridge(router);\n const harnessBridge = Object.assign(bridge, {\n __rpcManifest: createRpcManifest(operations),\n });\n\n const globalObj = globalThis as MutableGlobal;\n const previousInternalBridge = globalObj[WOOD_INTERNAL_BRIDGE_KEY];\n const previousWoodBridge = globalObj.wood;\n globalObj[WOOD_INTERNAL_BRIDGE_KEY] = harnessBridge;\n globalObj.wood = harnessBridge;\n\n clearClientContainerForTests();\n clearClientAppForTests();\n clearClientNavigationForTests();\n clearClientWindowControlsForTests();\n clearClientLoggersForTests();\n\n const scopedContainer = options.container.extend();\n registerClientBuiltins(scopedContainer);\n if (typeof scopedContainer.registerClass === 'function') {\n scopedContainer.registerClass(options.controllerClass);\n }\n const navigation = getNavigation();\n await options.prepareClient?.({\n bridge: harnessBridge,\n events,\n navigation,\n container: scopedContainer,\n });\n\n const controller = await scopedContainer.instance(options.controllerClass);\n const trace = await scopedContainer.instance(TraceProvider);\n if (options.initialize && typeof (controller as { initialize?: () => void }).initialize === 'function') {\n await Promise.resolve(\n (controller as { initialize: () => void | Promise<void> }).initialize(),\n );\n }\n\n trace.info({\n source: 'wood.testing.controller-harness',\n type: 'harness.created',\n payload: {\n controllerClass: options.controllerClass.name,\n },\n });\n\n return {\n controller,\n bridge: harnessBridge,\n events,\n router,\n container: scopedContainer,\n navigation,\n trace,\n destroy: () => {\n trace.info({\n source: 'wood.testing.controller-harness',\n type: 'harness.destroyed',\n });\n if (typeof (controller as { destroy?: () => void }).destroy === 'function') {\n (controller as { destroy: () => void }).destroy();\n }\n events.clear();\n clearClientContainerForTests();\n clearClientAppForTests();\n clearClientNavigationForTests();\n clearClientWindowControlsForTests();\n clearClientLoggersForTests();\n\n if (previousInternalBridge === undefined) {\n delete globalObj[WOOD_INTERNAL_BRIDGE_KEY];\n } else {\n globalObj[WOOD_INTERNAL_BRIDGE_KEY] = previousInternalBridge;\n }\n\n if (previousWoodBridge === undefined) {\n delete globalObj.wood;\n } else {\n globalObj.wood = previousWoodBridge;\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/testing/create_controller_harness.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport {\n App,\n clearClientAppForTests,\n clearClientContainerForTests,\n clearClientLoggersForTests,\n clearClientNavigationForTests,\n clearClientWindowControlsForTests,\n getApp,\n getWindowControls,\n Ipc,\n WOOD_INTERNAL_BRIDGE_KEY,\n} from '../client/index.js';\nimport { getIpc } from '../ipc/index.js';\nimport { Navigation, getNavigation } from '../navigation/index.js';\nimport { TraceProvider, TraceProviderConfiguration } from '../tracing/index.js';\nimport { parseOperations } from '../parser/operations_parser.js';\nimport type { OperationDef } from '../types/operations.js';\nimport { disposeControllerLifecycle } from '../controller/controller_lifecycle.js';\nimport { createRouterBridge, type RouterBridgeResult } from './create_router_bridge.js';\nimport { createTestRouter } from './create_test_router.js';\n\nexport interface CreateControllerHarnessOptions<T> {\n controllerClass: new (...args: any[]) => T;\n container: any;\n operations: string | string[];\n controllersDir: string;\n middlewareDir?: string;\n configureContainer?: (container: any) => void | Promise<void>;\n configureRouter?: (router: ReturnType<typeof createTestRouter>['router']) => void | Promise<void>;\n prepareClient?: (context: {\n bridge: Record<string, any>;\n events: RouterBridgeResult['events'];\n navigation: Navigation;\n container: any;\n }) => void | Promise<void>;\n initialize?: boolean;\n}\n\nexport interface ControllerHarnessResult<T> extends RouterBridgeResult {\n controller: T;\n container: any;\n router: ReturnType<typeof createTestRouter>['router'];\n navigation: Navigation;\n trace: TraceProvider;\n destroy: () => void | Promise<void>;\n}\n\ntype MutableGlobal = typeof globalThis & {\n [WOOD_INTERNAL_BRIDGE_KEY]?: unknown;\n wood?: unknown;\n};\n\nfunction readOperations(input: string): Map<string, OperationDef> {\n if (input.includes('\\n') || input.includes(':')) {\n return parseOperations(input);\n }\n\n return parseOperations(readFileSync(input, 'utf-8'));\n}\n\nfunction mergeOperations(inputs: string | string[]): Map<string, OperationDef> {\n const merged = new Map<string, OperationDef>();\n\n for (const input of Array.isArray(inputs) ? inputs : [inputs]) {\n for (const [channel, operation] of readOperations(input)) {\n merged.set(channel, operation);\n }\n }\n\n return merged;\n}\n\nfunction createRpcManifest(operations: Map<string, OperationDef>) {\n return Array.from(operations.values()).map((operation) => ({\n channel: operation.channel,\n controller: operation.controller,\n action: operation.action,\n path: operation.channel.split('.'),\n hasInput: !!operation.inputSchema,\n }));\n}\n\nfunction registerClientBuiltins(container: any): void {\n if (typeof container.registerFunction !== 'function') {\n return;\n }\n\n const traceConfiguration = new TraceProviderConfiguration();\n traceConfiguration.configureMode('test');\n traceConfiguration.configureRuntime('renderer');\n\n container.registerFunction(Navigation, () => getNavigation());\n container.registerFunction(App, () => getApp());\n container.registerFunction(Ipc, () => getIpc());\n container.registerFunction(WindowControls, () => getWindowControls());\n container.registerFunction(TraceProviderConfiguration, () => traceConfiguration);\n}\n\nclass WindowControls {\n async open(_windowId: string, _options?: Record<string, unknown>): Promise<void> {}\n async close(_windowId?: string): Promise<void> {}\n async focus(_windowId: string): Promise<void> {}\n async minimize(_windowId?: string): Promise<void> {}\n async maximize(_windowId?: string): Promise<void> {}\n}\n\nexport async function createControllerHarness<T>(\n options: CreateControllerHarnessOptions<T>,\n): Promise<ControllerHarnessResult<T>> {\n await options.configureContainer?.(options.container);\n\n if (typeof options.container.instance === 'function') {\n const rootTraceConfiguration = await options.container.instance(TraceProviderConfiguration);\n rootTraceConfiguration.configureMode('test');\n rootTraceConfiguration.configureRuntime('main');\n }\n\n const operations = mergeOperations(options.operations);\n const { router } = createTestRouter('', {\n container: options.container,\n controllersDir: options.controllersDir,\n middlewareDir: options.middlewareDir,\n });\n router.loadOperations(operations);\n await options.configureRouter?.(router);\n\n const { bridge, events } = createRouterBridge(router);\n const harnessBridge = Object.assign(bridge, {\n __rpcManifest: createRpcManifest(operations),\n });\n\n const globalObj = globalThis as MutableGlobal;\n const previousInternalBridge = globalObj[WOOD_INTERNAL_BRIDGE_KEY];\n const previousWoodBridge = globalObj.wood;\n globalObj[WOOD_INTERNAL_BRIDGE_KEY] = harnessBridge;\n globalObj.wood = harnessBridge;\n\n clearClientContainerForTests();\n clearClientAppForTests();\n clearClientNavigationForTests();\n clearClientWindowControlsForTests();\n clearClientLoggersForTests();\n\n const scopedContainer = options.container.extend();\n registerClientBuiltins(scopedContainer);\n if (typeof scopedContainer.registerClass === 'function') {\n scopedContainer.registerClass(options.controllerClass);\n }\n const navigation = getNavigation();\n await options.prepareClient?.({\n bridge: harnessBridge,\n events,\n navigation,\n container: scopedContainer,\n });\n\n const controller = await scopedContainer.instance(options.controllerClass);\n const trace = await scopedContainer.instance(TraceProvider);\n if (options.initialize && typeof (controller as { initialize?: () => void }).initialize === 'function') {\n await Promise.resolve(\n (controller as { initialize: () => void | Promise<void> }).initialize(),\n );\n }\n\n trace.info({\n source: 'wood.testing.controller-harness',\n type: 'harness.created',\n payload: {\n controllerClass: options.controllerClass.name,\n },\n });\n\n return {\n controller,\n bridge: harnessBridge,\n events,\n router,\n container: scopedContainer,\n navigation,\n trace,\n destroy: async () => {\n trace.info({\n source: 'wood.testing.controller-harness',\n type: 'harness.destroyed',\n });\n await disposeControllerLifecycle(controller);\n events.clear();\n clearClientContainerForTests();\n clearClientAppForTests();\n clearClientNavigationForTests();\n clearClientWindowControlsForTests();\n clearClientLoggersForTests();\n\n if (previousInternalBridge === undefined) {\n delete globalObj[WOOD_INTERNAL_BRIDGE_KEY];\n } else {\n globalObj[WOOD_INTERNAL_BRIDGE_KEY] = previousInternalBridge;\n }\n\n if (previousWoodBridge === undefined) {\n delete globalObj.wood;\n } else {\n globalObj.wood = previousWoodBridge;\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -33,7 +33,8 @@ __export(tracing_exports, {
33
33
  publishMainTrace: () => import_trace_hub.publishMainTrace,
34
34
  publishTestTrace: () => import_trace_hub.publishTestTrace,
35
35
  setMainTraceMinLevel: () => import_trace_hub.setMainTraceMinLevel,
36
- setRendererTraceMinLevel: () => import_trace_hub.setRendererTraceMinLevel
36
+ setRendererTraceMinLevel: () => import_trace_hub.setRendererTraceMinLevel,
37
+ setRendererTraceTransport: () => import_trace_hub.setRendererTraceTransport
37
38
  });
38
39
  module.exports = __toCommonJS(tracing_exports);
39
40
  var import_trace_hub = require("./trace_hub.js");
@@ -55,6 +56,7 @@ var import_trace_provider = require("./trace_provider.js");
55
56
  publishMainTrace,
56
57
  publishTestTrace,
57
58
  setMainTraceMinLevel,
58
- setRendererTraceMinLevel
59
+ setRendererTraceMinLevel,
60
+ setRendererTraceTransport
59
61
  });
60
62
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAkBO;AAEP,4BASO;","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAmBO;AAEP,4BASO;","names":[]}
@@ -1,4 +1,4 @@
1
- export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel } from './trace_hub.cjs';
1
+ export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.cjs';
2
2
  export { FrameworkTracer, MainTracer, RendererTracer, TestTracer, TraceProvider, TraceProviderConfiguration, TraceProviderMode, TraceRuntime } from './trace_provider.cjs';
3
3
  import 'rxjs';
4
4
  import '@noego/ioc';
@@ -1,4 +1,4 @@
1
- export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel } from './trace_hub.js';
1
+ export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel, setRendererTraceTransport } from './trace_hub.js';
2
2
  export { FrameworkTracer, MainTracer, RendererTracer, TestTracer, TraceProvider, TraceProviderConfiguration, TraceProviderMode, TraceRuntime } from './trace_provider.js';
3
3
  import 'rxjs';
4
4
  import '@noego/ioc';
@@ -8,6 +8,7 @@ import {
8
8
  publishTestTrace,
9
9
  setMainTraceMinLevel,
10
10
  setRendererTraceMinLevel,
11
+ setRendererTraceTransport,
11
12
  TraceCapture
12
13
  } from "./trace_hub.js";
13
14
  import {
@@ -34,6 +35,7 @@ export {
34
35
  publishMainTrace,
35
36
  publishTestTrace,
36
37
  setMainTraceMinLevel,
37
- setRendererTraceMinLevel
38
+ setRendererTraceMinLevel,
39
+ setRendererTraceTransport
38
40
  };
39
41
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/index.ts"],"sourcesContent":["export {\n clearTraceHubForTests,\n createTraceCapture,\n dispatchRendererTracePayload,\n emitRendererTrace,\n getTraceEvents$,\n publishMainTrace,\n publishTestTrace,\n setMainTraceMinLevel,\n setRendererTraceMinLevel,\n setRendererTraceTransport,\n TraceCapture,\n type TraceCaptureOptions,\n type TraceDispatchResult,\n type TraceEvent,\n type TraceInput,\n type TraceLevel,\n type TraceProcess,\n type TraceWaitOptions,\n} from './trace_hub.js';\n\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n type TraceProviderMode,\n type TraceRuntime,\n} from './trace_provider.js';\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;","names":[]}
@@ -37,7 +37,8 @@ __export(trace_hub_exports, {
37
37
  publishMainTrace: () => publishMainTrace,
38
38
  publishTestTrace: () => publishTestTrace,
39
39
  setMainTraceMinLevel: () => setMainTraceMinLevel,
40
- setRendererTraceMinLevel: () => setRendererTraceMinLevel
40
+ setRendererTraceMinLevel: () => setRendererTraceMinLevel,
41
+ setRendererTraceTransport: () => setRendererTraceTransport
41
42
  });
42
43
  module.exports = __toCommonJS(trace_hub_exports);
43
44
  var import_rxjs = require("rxjs");
@@ -50,6 +51,7 @@ const LEVEL_ORDER = {
50
51
  error: 3
51
52
  };
52
53
  let rendererMinLevel = "debug";
54
+ let customRendererTraceTransport = null;
53
55
  function normalizeTraceInput(raw) {
54
56
  const input = raw ?? {};
55
57
  const source = typeof input.source === "string" && input.source.trim().length > 0 ? input.source : "unknown";
@@ -202,19 +204,27 @@ function dispatchRendererTracePayload(rawPayload) {
202
204
  forwarded: true
203
205
  };
204
206
  }
207
+ function setRendererTraceTransport(fn) {
208
+ customRendererTraceTransport = fn;
209
+ }
205
210
  function emitRendererTrace(level, input) {
206
211
  if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {
207
212
  return;
208
213
  }
214
+ const normalized = { ...normalizeTraceInput(input), level };
215
+ if (customRendererTraceTransport) {
216
+ try {
217
+ customRendererTraceTransport(normalized);
218
+ return;
219
+ } catch {
220
+ }
221
+ }
209
222
  const bridge = resolveTraceBridge();
210
223
  if (!bridge || typeof bridge.__trace !== "function") {
211
224
  return;
212
225
  }
213
226
  try {
214
- bridge.__trace({
215
- ...normalizeTraceInput(input),
216
- level
217
- });
227
+ bridge.__trace(normalized);
218
228
  } catch {
219
229
  }
220
230
  }
@@ -225,6 +235,7 @@ function clearTraceHubForTests() {
225
235
  const globalObj = globalThis;
226
236
  delete globalObj[TRACE_HUB_SYMBOL];
227
237
  rendererMinLevel = "debug";
238
+ customRendererTraceTransport = null;
228
239
  }
229
240
  // Annotate the CommonJS export names for ESM import in node:
230
241
  0 && (module.exports = {
@@ -237,6 +248,7 @@ function clearTraceHubForTests() {
237
248
  publishMainTrace,
238
249
  publishTestTrace,
239
250
  setMainTraceMinLevel,
240
- setRendererTraceMinLevel
251
+ setRendererTraceMinLevel,
252
+ setRendererTraceTransport
241
253
  });
242
254
  //# sourceMappingURL=trace_hub.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevel: TraceLevel = 'debug';\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(level: TraceLevel): void {\n this.minLevel = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevel]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel(level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, payload);\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace({\n ...normalizeTraceInput(input),\n level,\n });\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevel: TraceLevel = 'debug';\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(level: TraceLevel): void {\n this.minLevel = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevel]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel(level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, payload);\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
@@ -42,8 +42,9 @@ declare function setRendererTraceMinLevel(level: TraceLevel): void;
42
42
  declare function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent;
43
43
  declare function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent;
44
44
  declare function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult;
45
+ declare function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void;
45
46
  declare function emitRendererTrace(level: TraceLevel, input: TraceInput): void;
46
47
  declare function createTraceCapture(options?: TraceCaptureOptions): TraceCapture;
47
48
  declare function clearTraceHubForTests(): void;
48
49
 
49
- export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel };
50
+ export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel, setRendererTraceTransport };
@@ -42,8 +42,9 @@ declare function setRendererTraceMinLevel(level: TraceLevel): void;
42
42
  declare function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent;
43
43
  declare function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent;
44
44
  declare function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult;
45
+ declare function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void;
45
46
  declare function emitRendererTrace(level: TraceLevel, input: TraceInput): void;
46
47
  declare function createTraceCapture(options?: TraceCaptureOptions): TraceCapture;
47
48
  declare function clearTraceHubForTests(): void;
48
49
 
49
- export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel };
50
+ export { TraceCapture, type TraceCaptureOptions, type TraceDispatchResult, type TraceEvent, type TraceInput, type TraceLevel, type TraceProcess, type TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel, setRendererTraceTransport };
@@ -8,6 +8,7 @@ const LEVEL_ORDER = {
8
8
  error: 3
9
9
  };
10
10
  let rendererMinLevel = "debug";
11
+ let customRendererTraceTransport = null;
11
12
  function normalizeTraceInput(raw) {
12
13
  const input = raw ?? {};
13
14
  const source = typeof input.source === "string" && input.source.trim().length > 0 ? input.source : "unknown";
@@ -160,19 +161,27 @@ function dispatchRendererTracePayload(rawPayload) {
160
161
  forwarded: true
161
162
  };
162
163
  }
164
+ function setRendererTraceTransport(fn) {
165
+ customRendererTraceTransport = fn;
166
+ }
163
167
  function emitRendererTrace(level, input) {
164
168
  if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {
165
169
  return;
166
170
  }
171
+ const normalized = { ...normalizeTraceInput(input), level };
172
+ if (customRendererTraceTransport) {
173
+ try {
174
+ customRendererTraceTransport(normalized);
175
+ return;
176
+ } catch {
177
+ }
178
+ }
167
179
  const bridge = resolveTraceBridge();
168
180
  if (!bridge || typeof bridge.__trace !== "function") {
169
181
  return;
170
182
  }
171
183
  try {
172
- bridge.__trace({
173
- ...normalizeTraceInput(input),
174
- level
175
- });
184
+ bridge.__trace(normalized);
176
185
  } catch {
177
186
  }
178
187
  }
@@ -183,6 +192,7 @@ function clearTraceHubForTests() {
183
192
  const globalObj = globalThis;
184
193
  delete globalObj[TRACE_HUB_SYMBOL];
185
194
  rendererMinLevel = "debug";
195
+ customRendererTraceTransport = null;
186
196
  }
187
197
  export {
188
198
  TraceCapture,
@@ -194,6 +204,7 @@ export {
194
204
  publishMainTrace,
195
205
  publishTestTrace,
196
206
  setMainTraceMinLevel,
197
- setRendererTraceMinLevel
207
+ setRendererTraceMinLevel,
208
+ setRendererTraceTransport
198
209
  };
199
210
  //# sourceMappingURL=trace_hub.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevel: TraceLevel = 'debug';\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(level: TraceLevel): void {\n this.minLevel = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevel]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel(level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, payload);\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace({\n ...normalizeTraceInput(input),\n level,\n });\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/tracing/trace_hub.ts"],"sourcesContent":["import { Observable, Subject, Subscription } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nexport type TraceLevel = 'debug' | 'info' | 'warn' | 'error';\nexport type TraceProcess = 'main' | 'renderer' | 'test';\n\nexport type TraceInput = {\n source: string;\n type: string;\n message?: string;\n conversationId?: number | string;\n payload?: Record<string, unknown>;\n};\n\nexport type TraceEvent = TraceInput & {\n level: TraceLevel;\n process: TraceProcess;\n timestamp: string;\n traceSeq: number;\n};\n\nexport type TraceDispatchResult = {\n ok: boolean;\n forwarded: boolean;\n};\n\nexport type TraceCaptureOptions = {\n maxEvents?: number;\n};\n\nexport type TraceWaitOptions = {\n timeoutMs?: number;\n};\n\nconst TRACE_HUB_SYMBOL = Symbol.for('@noego/wood.trace.hub');\n\nconst LEVEL_ORDER: Record<TraceLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nlet rendererMinLevel: TraceLevel = 'debug';\nlet customRendererTraceTransport: ((payload: unknown) => void) | null = null;\n\ntype PendingWaiter = {\n predicate: (event: TraceEvent) => boolean;\n resolve: (event: TraceEvent) => void;\n reject: (error: Error) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n};\n\ntype GlobalWithTraceHub = typeof globalThis & {\n [TRACE_HUB_SYMBOL]?: TraceHub;\n};\n\ntype TraceBridgeLike = Record<string, unknown> & {\n __trace?: (payload: unknown) => void;\n};\n\ntype GlobalWithTraceBridge = typeof globalThis & {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n window?: {\n __NOEGO_WOOD_BRIDGE__?: unknown;\n wood?: unknown;\n };\n};\n\nfunction normalizeTraceInput(raw: unknown): TraceInput {\n const input = (raw ?? {}) as Partial<TraceInput> & Record<string, unknown>;\n const source = typeof input.source === 'string' && input.source.trim().length > 0\n ? input.source\n : 'unknown';\n const type = typeof input.type === 'string' && input.type.trim().length > 0\n ? input.type\n : 'unknown';\n const message = typeof input.message === 'string' ? input.message : undefined;\n const conversationId = typeof input.conversationId === 'number' || typeof input.conversationId === 'string'\n ? input.conversationId\n : undefined;\n const payload = isRecord(input.payload) ? { ...input.payload } : undefined;\n\n return {\n source,\n type,\n ...(message ? { message } : {}),\n ...(conversationId !== undefined ? { conversationId } : {}),\n ...(payload ? { payload } : {}),\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction resolveTraceBridge(): TraceBridgeLike | null {\n const globalObj = globalThis as GlobalWithTraceBridge;\n const bridge = globalObj.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.window?.__NOEGO_WOOD_BRIDGE__\n ?? globalObj.wood\n ?? globalObj.window?.wood;\n if (!bridge || typeof bridge !== 'object') {\n return null;\n }\n return bridge as TraceBridgeLike;\n}\n\nexport class TraceCapture {\n private readonly buffer: TraceEvent[] = [];\n private readonly pending = new Set<PendingWaiter>();\n private readonly maxEvents: number;\n private subscription: Subscription;\n\n constructor(\n source$: Observable<TraceEvent>,\n options: TraceCaptureOptions = {},\n ) {\n this.maxEvents = Math.max(1, options.maxEvents ?? 1000);\n this.subscription = source$.subscribe((event) => {\n this.buffer.push(event);\n if (this.buffer.length > this.maxEvents) {\n this.buffer.splice(0, this.buffer.length - this.maxEvents);\n }\n for (const waiter of Array.from(this.pending)) {\n if (!waiter.predicate(event)) {\n continue;\n }\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n this.pending.delete(waiter);\n waiter.resolve(event);\n }\n });\n }\n\n events(): TraceEvent[] {\n return [...this.buffer];\n }\n\n async waitFor(\n predicate: (event: TraceEvent) => boolean,\n options: TraceWaitOptions = {},\n ): Promise<TraceEvent> {\n const existing = this.buffer.find(predicate);\n if (existing) {\n return existing;\n }\n\n return new Promise<TraceEvent>((resolve, reject) => {\n const waiter: PendingWaiter = {\n predicate,\n resolve,\n reject,\n };\n const timeoutMs = options.timeoutMs ?? 5000;\n waiter.timeoutId = setTimeout(() => {\n this.pending.delete(waiter);\n reject(new Error(`Timed out waiting for trace event after ${timeoutMs}ms`));\n }, timeoutMs);\n this.pending.add(waiter);\n });\n }\n\n async writeArtifact(targetPath: string): Promise<void> {\n const [{ mkdir, writeFile }, pathModule] = await Promise.all([\n import('node:fs/promises'),\n import('node:path'),\n ]);\n await mkdir(pathModule.dirname(targetPath), { recursive: true });\n const lines = this.buffer.map((event) => JSON.stringify(event)).join('\\n');\n await writeFile(targetPath, `${lines}${lines.length > 0 ? '\\n' : ''}`, 'utf8');\n }\n\n stop(): void {\n for (const waiter of this.pending) {\n if (waiter.timeoutId) {\n clearTimeout(waiter.timeoutId);\n }\n waiter.reject(new Error('Trace capture stopped before predicate matched'));\n }\n this.pending.clear();\n this.subscription.unsubscribe();\n }\n}\n\nclass TraceHub {\n private readonly subject = new Subject<TraceEvent>();\n private readonly shared$ = this.subject.asObservable().pipe(share());\n private nextTraceSeq = 1;\n private minLevel: TraceLevel = 'debug';\n\n get events$(): Observable<TraceEvent> {\n return this.shared$;\n }\n\n setMinLevel(level: TraceLevel): void {\n this.minLevel = level;\n }\n\n publish(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n const normalized = normalizeTraceInput(input);\n const event: TraceEvent = {\n ...normalized,\n level,\n process,\n timestamp: new Date().toISOString(),\n traceSeq: this.nextTraceSeq++,\n };\n if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevel]) {\n this.subject.next(event);\n }\n return event;\n }\n\n capture(options: TraceCaptureOptions = {}): TraceCapture {\n return new TraceCapture(this.events$, options);\n }\n}\n\nfunction getGlobalTraceHub(): TraceHub {\n const globalObj = globalThis as GlobalWithTraceHub;\n if (!globalObj[TRACE_HUB_SYMBOL]) {\n globalObj[TRACE_HUB_SYMBOL] = new TraceHub();\n }\n return globalObj[TRACE_HUB_SYMBOL] as TraceHub;\n}\n\nexport function getTraceEvents$(): Observable<TraceEvent> {\n return getGlobalTraceHub().events$;\n}\n\nexport function setMainTraceMinLevel(level: TraceLevel): void {\n getGlobalTraceHub().setMinLevel(level);\n}\n\nexport function setRendererTraceMinLevel(level: TraceLevel): void {\n rendererMinLevel = level;\n}\n\nexport function publishMainTrace(level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish('main', level, input);\n}\n\nexport function publishTestTrace(process: TraceProcess, level: TraceLevel, input: unknown): TraceEvent {\n return getGlobalTraceHub().publish(process, level, input);\n}\n\nexport function dispatchRendererTracePayload(rawPayload: unknown): TraceDispatchResult {\n const payload = (rawPayload ?? {}) as Partial<TraceInput> & { level?: TraceLevel };\n const level = payload.level === 'debug' || payload.level === 'info' || payload.level === 'warn' || payload.level === 'error'\n ? payload.level\n : 'info';\n getGlobalTraceHub().publish('renderer', level, payload);\n return {\n ok: true,\n forwarded: true,\n };\n}\n\nexport function setRendererTraceTransport(fn: ((payload: unknown) => void) | null): void {\n customRendererTraceTransport = fn;\n}\n\nexport function emitRendererTrace(level: TraceLevel, input: TraceInput): void {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {\n return;\n }\n const normalized = { ...normalizeTraceInput(input), level };\n\n if (customRendererTraceTransport) {\n try {\n customRendererTraceTransport(normalized);\n return;\n } catch {\n // Fall through to bridge.__trace\n }\n }\n\n const bridge = resolveTraceBridge();\n if (!bridge || typeof bridge.__trace !== 'function') {\n return;\n }\n try {\n bridge.__trace(normalized);\n } catch {\n // Tracing is observational and must never break the caller.\n }\n}\n\nexport function createTraceCapture(options: TraceCaptureOptions = {}): TraceCapture {\n return getGlobalTraceHub().capture(options);\n}\n\nexport function clearTraceHubForTests(): void {\n const globalObj = globalThis as GlobalWithTraceHub;\n delete globalObj[TRACE_HUB_SYMBOL];\n rendererMinLevel = 'debug';\n customRendererTraceTransport = null;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@noego/wood",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "author": "Shavauhn Gabay",
8
8
  "license": "ISC",
9
9
  "bin": {
10
- "axe": "./bin/axe.js",
11
- "stick": "./bin/stick.js",
12
- "wood": "./bin/wood.js"
10
+ "axe": "bin/axe.js",
11
+ "stick": "bin/stick.js",
12
+ "wood": "bin/wood.js"
13
13
  },
14
14
  "publishConfig": {
15
15
  "access": "public"