@noego/wood 0.0.1 → 0.0.4
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/bin/wood.js +1 -0
- package/dist/bridge/backend_entry.cjs +23 -4
- package/dist/bridge/backend_entry.cjs.map +1 -1
- package/dist/bridge/backend_entry.d.cts +8 -2
- package/dist/bridge/backend_entry.d.ts +8 -2
- package/dist/bridge/backend_entry.js +22 -4
- package/dist/bridge/backend_entry.js.map +1 -1
- package/dist/bridge/buffered_ipc_sender.cjs +120 -0
- package/dist/bridge/buffered_ipc_sender.cjs.map +1 -0
- package/dist/bridge/buffered_ipc_sender.d.cts +49 -0
- package/dist/bridge/buffered_ipc_sender.d.ts +49 -0
- package/dist/bridge/buffered_ipc_sender.js +95 -0
- package/dist/bridge/buffered_ipc_sender.js.map +1 -0
- package/dist/client/controller_contract.cjs.map +1 -1
- package/dist/client/controller_contract.d.cts +3 -5
- package/dist/client/controller_contract.d.ts +3 -5
- package/dist/client/index.cjs +18 -20
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -2
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.js +18 -19
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/preload_generator.cjs +10 -4
- package/dist/codegen/preload_generator.cjs.map +1 -1
- package/dist/codegen/preload_generator.js +10 -4
- package/dist/codegen/preload_generator.js.map +1 -1
- package/dist/main/index.cjs +9 -0
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +4 -0
- package/dist/main/index.d.ts +4 -0
- package/dist/main/index.js +9 -0
- package/dist/main/index.js.map +1 -1
- package/dist/router/wood_router.cjs +1 -1
- package/dist/router/wood_router.cjs.map +1 -1
- package/dist/router/wood_router.d.cts +1 -1
- package/dist/router/wood_router.d.ts +1 -1
- package/dist/router/wood_router.js +1 -1
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/runtime.cjs +35 -24
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +5 -0
- package/dist/runtime/runtime.d.ts +5 -0
- package/dist/runtime/runtime.js +35 -24
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/tracing/index.cjs +6 -2
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +1 -1
- package/dist/tracing/index.d.ts +1 -1
- package/dist/tracing/index.js +5 -1
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/trace_hub.cjs +37 -8
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +3 -1
- package/dist/tracing/trace_hub.d.ts +3 -1
- package/dist/tracing/trace_hub.js +34 -7
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +12 -0
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +4 -1
- package/dist/tracing/trace_provider.d.ts +4 -1
- package/dist/tracing/trace_provider.js +15 -1
- package/dist/tracing/trace_provider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/WoodRecursiveRender.svelte +6 -6
- package/src/stick/WoodRecursiveRender.svelte +4 -4
- package/dist/client/wood_controller.svelte.cjs +0 -110
- package/dist/client/wood_controller.svelte.cjs.map +0 -1
- package/dist/client/wood_controller.svelte.d.cts +0 -30
- package/dist/client/wood_controller.svelte.d.ts +0 -30
- package/dist/client/wood_controller.svelte.js +0 -86
- package/dist/client/wood_controller.svelte.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.js';\nimport { SchemaValidator } from '../validation/schema_validator.js';\nimport { MiddlewareResolver } from '../middleware/middleware_resolver.js';\nimport { buildMiddlewareContext, executeMiddleware } from '../middleware/middleware_pipeline.js';\nimport { ControllerResolver, buildControllerArgs } from '../controller/controller_resolver.js';\nimport { getLogger } from '@noego/logger';\nimport { publishMainTrace } from '../tracing/index.js';\n\nconst logger = getLogger('wood:router');\n\nfunction extractTraceConversationId(value: unknown): number | string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n if (typeof record.conversationId === 'number' || typeof record.conversationId === 'string') {\n return record.conversationId;\n }\n if (typeof record.threadId === 'number' || typeof record.threadId === 'string') {\n return record.threadId;\n }\n\n return undefined;\n}\n\n/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */\nexport const RESERVED_CHANNELS = ['__load', '__navigate', '__window', '__debug', '__contextMenu'] as const;\nexport type ReservedChannel = (typeof RESERVED_CHANNELS)[number];\n\n/** Handler signature for reserved channels. */\nexport type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;\n\nexport class WoodRouter {\n private operations = new Map<string, OperationDef>();\n private reservedHandlers = new Map<ReservedChannel, ReservedChannelHandler>();\n private validator: SchemaValidator;\n private middlewareResolver: MiddlewareResolver;\n private controllerResolver: ControllerResolver;\n private container: any; // IoC Container\n\n constructor(options: {\n container: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n }) {\n this.container = options.container;\n this.validator = new SchemaValidator();\n this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);\n this.controllerResolver = new ControllerResolver(options.controllersDir, {\n mode: options.mode,\n });\n }\n\n /**\n * Load operations from a parsed operations map.\n */\n loadOperations(operations: Map<string, OperationDef>): void {\n for (const [channel, opDef] of operations) {\n this.operations.set(channel, opDef);\n }\n logger.debug(`Loaded ${operations.size} operations`);\n }\n\n /**\n * Register a handler for a reserved channel (__load, __navigate, __window).\n * These channels are internal to Wood and serve as extension points for\n * the loader runner, navigation system, and window manager.\n */\n registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void {\n this.reservedHandlers.set(channel, handler);\n logger.debug(`Registered reserved handler for \"${channel}\"`);\n }\n\n /**\n * Register IPC handlers for all operations and reserved channels.\n * In production: registers with ipcMain.handle\n * In testing/bridge mode: handlers are callable via dispatch()\n */\n registerIpcHandlers(ipcMain: any): void {\n for (const channel of this.operations.keys()) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n return this.dispatch(channel, data, _event);\n });\n }\n\n // Register reserved channels\n for (const channel of RESERVED_CHANNELS) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n const handler = this.reservedHandlers.get(channel);\n if (!handler) {\n throw new Error(`No handler registered for reserved channel \"${channel}\"`);\n }\n return handler(data, _event);\n });\n }\n\n logger.debug(\n `Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`\n );\n }\n\n /**\n * The request lifecycle -- mirrors Dinner's pipeline.\n *\n * channel -> build context -> middleware -> validate -> resolve controller\n * -> create instance -> build args -> call action -> return result\n */\n async dispatch(channel: string, data: unknown, event?: any): Promise<unknown> {\n const opDef = this.operations.get(channel);\n if (!opDef) {\n throw new Error(`Unknown operation: \"${channel}\"`);\n }\n\n const conversationId = extractTraceConversationId(data);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.start',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n\n // 1. Build IPC context\n const ipcContext: IpcContext = {\n body: data ?? {},\n params: (data as any) ?? {},\n query: {},\n context: {},\n sender: event?.sender,\n windowId: undefined,\n };\n\n // 2. Execute middleware sequentially\n if (opDef.middleware.length > 0) {\n const mwContext = buildMiddlewareContext(ipcContext, channel);\n const middlewareFns = await Promise.all(\n opDef.middleware.map(spec => this.middlewareResolver.resolve(spec))\n );\n await executeMiddleware(middlewareFns, mwContext);\n }\n\n // 3. Validate input (if schema defined)\n if (opDef.inputSchema) {\n const result = this.validator.validate(\n channel,\n opDef.inputSchema as Record<string, unknown>,\n ipcContext.body\n );\n if (!result.valid) {\n return {\n error: 'VALIDATION_ERROR',\n message: 'Request validation failed',\n details: result.errors,\n };\n }\n }\n\n // 4. Resolve controller class (cached)\n const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);\n\n // 5. Create instance via IoC (per-request scoped container)\n const scopedContainer = this.container.extend();\n const instance = await scopedContainer.instance(ControllerClass);\n\n // 6. Build controller args (fake req/res)\n const args = buildControllerArgs(ipcContext, scopedContainer);\n\n // 7. Call action, return result\n const action = instance[opDef.action];\n if (typeof action !== 'function') {\n throw new Error(\n `Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`\n );\n }\n\n try {\n const result = await action.call(instance, args);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.success',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n return result;\n } catch (error) {\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.error',\n message: error instanceof Error ? error.message : String(error),\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n throw error;\n }\n }\n\n /**\n * Pre-register a controller class by name so it is resolved from\n * the in-memory cache instead of the filesystem.\n * This is the public API used by the generated registration file.\n */\n registerController(name: string, ControllerClass: any): void {\n this.controllerResolver.register(name, ControllerClass);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed, avoiding circular dependencies.\n */\n registerControllerPath(name: string, importPath: string): void {\n this.controllerResolver.registerPath(name, importPath);\n }\n\n /**\n * Validate that every controller referenced in loaded operations is\n * pre-registered in the controller resolver. Call this after\n * loadOperations() + registerControllers() but before registerIpcHandlers().\n *\n * Throws with a clear error listing all missing controllers if any\n * operation references a controller that was not pre-registered.\n */\n validateControllers(): void {\n const missing: Array<{ channel: string; controller: string }> = [];\n\n for (const [channel, opDef] of this.operations) {\n if (!this.controllerResolver.has(opDef.controller)) {\n missing.push({ channel, controller: opDef.controller });\n }\n }\n\n if (missing.length > 0) {\n const details = missing\n .map(m => ` - channel \"${m.channel}\" requires controller \"${m.controller}\"`)\n .join('\\n');\n\n throw new Error(\n `WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.\\n` +\n `This usually means controllers.generated.ts is missing or out of date.\\n` +\n `Run \"npx wood build\" or \"npx wood dev\" to regenerate it.\\n\\n` +\n `Missing controllers:\\n${details}`\n );\n }\n\n logger.info(`All ${this.operations.size} operations have registered controllers`);\n }\n\n /** Get all registered operation channels. */\n getChannels(): string[] {\n return Array.from(this.operations.keys());\n }\n\n /** Get a specific operation definition. */\n getOperation(channel: string): OperationDef | undefined {\n return this.operations.get(channel);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.js';\nimport { SchemaValidator } from '../validation/schema_validator.js';\nimport { MiddlewareResolver } from '../middleware/middleware_resolver.js';\nimport { buildMiddlewareContext, executeMiddleware } from '../middleware/middleware_pipeline.js';\nimport { ControllerResolver, buildControllerArgs } from '../controller/controller_resolver.js';\nimport { getLogger } from '@noego/logger';\nimport { publishMainTrace } from '../tracing/index.js';\n\nconst logger = getLogger('wood:router');\n\nfunction extractTraceConversationId(value: unknown): number | string | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const record = value as Record<string, unknown>;\n if (typeof record.conversationId === 'number' || typeof record.conversationId === 'string') {\n return record.conversationId;\n }\n if (typeof record.threadId === 'number' || typeof record.threadId === 'string') {\n return record.threadId;\n }\n\n return undefined;\n}\n\n/** Reserved internal channels prefixed with __ to avoid collisions with user operations. */\nexport const RESERVED_CHANNELS = ['__load', '__navigate', '__window', '__debug', '__contextMenu', '__woodConfig'] as const;\nexport type ReservedChannel = (typeof RESERVED_CHANNELS)[number];\n\n/** Handler signature for reserved channels. */\nexport type ReservedChannelHandler = (data: unknown, event?: any) => Promise<unknown>;\n\nexport class WoodRouter {\n private operations = new Map<string, OperationDef>();\n private reservedHandlers = new Map<ReservedChannel, ReservedChannelHandler>();\n private validator: SchemaValidator;\n private middlewareResolver: MiddlewareResolver;\n private controllerResolver: ControllerResolver;\n private container: any; // IoC Container\n\n constructor(options: {\n container: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n }) {\n this.container = options.container;\n this.validator = new SchemaValidator();\n this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);\n this.controllerResolver = new ControllerResolver(options.controllersDir, {\n mode: options.mode,\n });\n }\n\n /**\n * Load operations from a parsed operations map.\n */\n loadOperations(operations: Map<string, OperationDef>): void {\n for (const [channel, opDef] of operations) {\n this.operations.set(channel, opDef);\n }\n logger.debug(`Loaded ${operations.size} operations`);\n }\n\n /**\n * Register a handler for a reserved channel (__load, __navigate, __window).\n * These channels are internal to Wood and serve as extension points for\n * the loader runner, navigation system, and window manager.\n */\n registerReservedHandler(channel: ReservedChannel, handler: ReservedChannelHandler): void {\n this.reservedHandlers.set(channel, handler);\n logger.debug(`Registered reserved handler for \"${channel}\"`);\n }\n\n /**\n * Register IPC handlers for all operations and reserved channels.\n * In production: registers with ipcMain.handle\n * In testing/bridge mode: handlers are callable via dispatch()\n */\n registerIpcHandlers(ipcMain: any): void {\n for (const channel of this.operations.keys()) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n return this.dispatch(channel, data, _event);\n });\n }\n\n // Register reserved channels\n for (const channel of RESERVED_CHANNELS) {\n ipcMain.handle(channel, async (_event: any, data: unknown) => {\n const handler = this.reservedHandlers.get(channel);\n if (!handler) {\n throw new Error(`No handler registered for reserved channel \"${channel}\"`);\n }\n return handler(data, _event);\n });\n }\n\n logger.debug(\n `Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`\n );\n }\n\n /**\n * The request lifecycle -- mirrors Dinner's pipeline.\n *\n * channel -> build context -> middleware -> validate -> resolve controller\n * -> create instance -> build args -> call action -> return result\n */\n async dispatch(channel: string, data: unknown, event?: any): Promise<unknown> {\n const opDef = this.operations.get(channel);\n if (!opDef) {\n throw new Error(`Unknown operation: \"${channel}\"`);\n }\n\n const conversationId = extractTraceConversationId(data);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.start',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n\n // 1. Build IPC context\n const ipcContext: IpcContext = {\n body: data ?? {},\n params: (data as any) ?? {},\n query: {},\n context: {},\n sender: event?.sender,\n windowId: undefined,\n };\n\n // 2. Execute middleware sequentially\n if (opDef.middleware.length > 0) {\n const mwContext = buildMiddlewareContext(ipcContext, channel);\n const middlewareFns = await Promise.all(\n opDef.middleware.map(spec => this.middlewareResolver.resolve(spec))\n );\n await executeMiddleware(middlewareFns, mwContext);\n }\n\n // 3. Validate input (if schema defined)\n if (opDef.inputSchema) {\n const result = this.validator.validate(\n channel,\n opDef.inputSchema as Record<string, unknown>,\n ipcContext.body\n );\n if (!result.valid) {\n return {\n error: 'VALIDATION_ERROR',\n message: 'Request validation failed',\n details: result.errors,\n };\n }\n }\n\n // 4. Resolve controller class (cached)\n const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);\n\n // 5. Create instance via IoC (per-request scoped container)\n const scopedContainer = this.container.extend();\n const instance = await scopedContainer.instance(ControllerClass);\n\n // 6. Build controller args (fake req/res)\n const args = buildControllerArgs(ipcContext, scopedContainer);\n\n // 7. Call action, return result\n const action = instance[opDef.action];\n if (typeof action !== 'function') {\n throw new Error(\n `Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`\n );\n }\n\n try {\n const result = await action.call(instance, args);\n publishMainTrace('debug', {\n source: 'wood.router',\n type: 'dispatch.success',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n return result;\n } catch (error) {\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.error',\n message: error instanceof Error ? error.message : String(error),\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n throw error;\n }\n }\n\n /**\n * Pre-register a controller class by name so it is resolved from\n * the in-memory cache instead of the filesystem.\n * This is the public API used by the generated registration file.\n */\n registerController(name: string, ControllerClass: any): void {\n this.controllerResolver.register(name, ControllerClass);\n }\n\n /**\n * Register an import path for a controller. The controller will be lazily\n * imported from this path when first needed, avoiding circular dependencies.\n */\n registerControllerPath(name: string, importPath: string): void {\n this.controllerResolver.registerPath(name, importPath);\n }\n\n /**\n * Validate that every controller referenced in loaded operations is\n * pre-registered in the controller resolver. Call this after\n * loadOperations() + registerControllers() but before registerIpcHandlers().\n *\n * Throws with a clear error listing all missing controllers if any\n * operation references a controller that was not pre-registered.\n */\n validateControllers(): void {\n const missing: Array<{ channel: string; controller: string }> = [];\n\n for (const [channel, opDef] of this.operations) {\n if (!this.controllerResolver.has(opDef.controller)) {\n missing.push({ channel, controller: opDef.controller });\n }\n }\n\n if (missing.length > 0) {\n const details = missing\n .map(m => ` - channel \"${m.channel}\" requires controller \"${m.controller}\"`)\n .join('\\n');\n\n throw new Error(\n `WoodRouter: ${missing.length} operation(s) reference controllers that are not registered.\\n` +\n `This usually means controllers.generated.ts is missing or out of date.\\n` +\n `Run \"npx wood build\" or \"npx wood dev\" to regenerate it.\\n\\n` +\n `Missing controllers:\\n${details}`\n );\n }\n\n logger.info(`All ${this.operations.size} operations have registered controllers`);\n }\n\n /** Get all registered operation channels. */\n getChannels(): string[] {\n return Array.from(this.operations.keys());\n }\n\n /** Get a specific operation definition. */\n getOperation(channel: string): OperationDef | undefined {\n return this.operations.get(channel);\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/runtime/runtime.cjs
CHANGED
|
@@ -25,6 +25,7 @@ var import_logger = require("@noego/logger");
|
|
|
25
25
|
var import_wood_router = require("../router/wood_router.cjs");
|
|
26
26
|
var import_get_container = require("./get_container.cjs");
|
|
27
27
|
var import_tracing = require("../tracing/index.js");
|
|
28
|
+
var import_tracing2 = require("../tracing/index.js");
|
|
28
29
|
var import_renderer_log_dispatcher = require("./renderer_log_dispatcher.js");
|
|
29
30
|
const logger = (0, import_logger.getLogger)("wood:runtime");
|
|
30
31
|
function normalizeRendererLogLevel(level) {
|
|
@@ -53,7 +54,8 @@ async function runtime(options) {
|
|
|
53
54
|
middlewareDir,
|
|
54
55
|
mode = "bundled",
|
|
55
56
|
enableRendererLogBridge = true,
|
|
56
|
-
enableRendererTraceBridge = true
|
|
57
|
+
enableRendererTraceBridge = true,
|
|
58
|
+
traceMinLevel
|
|
57
59
|
} = options;
|
|
58
60
|
const container = options.container ?? (0, import_get_container.getContainer)();
|
|
59
61
|
logger.info("runtime start", {
|
|
@@ -62,11 +64,18 @@ async function runtime(options) {
|
|
|
62
64
|
controllersDir,
|
|
63
65
|
middlewareDir,
|
|
64
66
|
enableRendererLogBridge,
|
|
65
|
-
enableRendererTraceBridge
|
|
67
|
+
enableRendererTraceBridge,
|
|
68
|
+
traceMinLevel: traceMinLevel ?? "debug"
|
|
66
69
|
});
|
|
70
|
+
if (traceMinLevel) {
|
|
71
|
+
(0, import_tracing2.setMainTraceMinLevel)(traceMinLevel);
|
|
72
|
+
}
|
|
67
73
|
if (typeof container.instance === "function") {
|
|
68
74
|
const traceConfiguration = await container.instance(import_tracing.TraceProviderConfiguration);
|
|
69
75
|
traceConfiguration.configureRuntime("main");
|
|
76
|
+
if (traceMinLevel) {
|
|
77
|
+
traceConfiguration.configureMinLevel(traceMinLevel);
|
|
78
|
+
}
|
|
70
79
|
}
|
|
71
80
|
const router = new import_wood_router.WoodRouter({
|
|
72
81
|
container,
|
|
@@ -108,6 +117,11 @@ async function runtime(options) {
|
|
|
108
117
|
}
|
|
109
118
|
return options.onContextMenu(data, event);
|
|
110
119
|
});
|
|
120
|
+
router.registerReservedHandler("__woodConfig", async () => {
|
|
121
|
+
return {
|
|
122
|
+
traceMinLevel: traceMinLevel ?? "debug"
|
|
123
|
+
};
|
|
124
|
+
});
|
|
111
125
|
if (enableRendererLogBridge) {
|
|
112
126
|
registerRendererLogBridge(ipcMain);
|
|
113
127
|
}
|
|
@@ -123,33 +137,30 @@ async function runtime(options) {
|
|
|
123
137
|
return { router };
|
|
124
138
|
}
|
|
125
139
|
function registerRendererTraceBridge(ipcMain) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
ipcMain.handle("__trace", async (_event, rawPayload) => {
|
|
130
|
-
return (0, import_tracing.dispatchRendererTracePayload)(rawPayload);
|
|
140
|
+
ipcMain.removeAllListeners?.("__trace");
|
|
141
|
+
ipcMain.on("__trace", (_event, rawPayload) => {
|
|
142
|
+
(0, import_tracing.dispatchRendererTracePayload)(rawPayload);
|
|
131
143
|
});
|
|
132
|
-
logger.info("renderer trace bridge registered");
|
|
144
|
+
logger.info("renderer trace bridge registered (fire-and-forget)");
|
|
133
145
|
}
|
|
134
146
|
function registerRendererLogBridge(ipcMain) {
|
|
135
147
|
const dispatcher = (0, import_renderer_log_dispatcher.getRendererLogDispatcher)();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return result;
|
|
148
|
+
ipcMain.removeAllListeners?.("__log");
|
|
149
|
+
ipcMain.on("__log", (_event, rawPayload) => {
|
|
150
|
+
const entry = coerceRendererLogPayload(rawPayload, null);
|
|
151
|
+
void dispatcher.dispatch(entry).then((result) => {
|
|
152
|
+
const typedResult = result;
|
|
153
|
+
if (!typedResult.ok) {
|
|
154
|
+
logger.warn("renderer log dispatch failed", {
|
|
155
|
+
logger: entry.logger,
|
|
156
|
+
messageLength: entry.message.length,
|
|
157
|
+
reason: typedResult.reason ?? null,
|
|
158
|
+
errorMessage: typedResult.errorMessage ?? null
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
});
|
|
151
162
|
});
|
|
152
|
-
logger.info("renderer log bridge registered");
|
|
163
|
+
logger.info("renderer log bridge registered (fire-and-forget)");
|
|
153
164
|
}
|
|
154
165
|
// Annotate the CommonJS export names for ESM import in node:
|
|
155
166
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.cjs';\nimport { getContainer } from './get_container.cjs';\nimport { TraceProviderConfiguration, dispatchRendererTracePayload } from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n removeHandler?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (level === 'debug' || level === 'warn' || level === 'error') {\n return level;\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n } = options;\n\n const container = options.container ?? getContainer();\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n if (typeof container.instance === 'function') {\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n }\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.registerReservedHandler('__load', async (data, event) => {\n if (!options.onLoad) {\n throw new Error('Reserved channel \"__load\" not configured. Provide runtime({ onLoad }).');\n }\n return options.onLoad(data, event);\n });\n\n router.registerReservedHandler('__navigate', async (data, event) => {\n if (!options.onNavigate) {\n throw new Error('Reserved channel \"__navigate\" not configured. Provide runtime({ onNavigate }).');\n }\n return options.onNavigate(data, event);\n });\n\n router.registerReservedHandler('__window', async (data, event) => {\n if (!options.onWindow) {\n throw new Error('Reserved channel \"__window\" not configured. Provide runtime({ onWindow }).');\n }\n return options.onWindow(data, event);\n });\n\n router.registerReservedHandler('__debug', async (data, event) => {\n if (!options.onDebug) {\n throw new Error('Reserved channel \"__debug\" not configured. Provide runtime({ onDebug }).');\n }\n return options.onDebug(data, event);\n });\n\n router.registerReservedHandler('__contextMenu', async (data, event) => {\n if (!options.onContextMenu) {\n throw new Error('Reserved channel \"__contextMenu\" not configured. Provide runtime({ onContextMenu }).');\n }\n return options.onContextMenu(data, event);\n });\n\n if (enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n\n if (enableRendererTraceBridge) {\n registerRendererTraceBridge(ipcMain);\n }\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nfunction registerRendererTraceBridge(ipcMain: IpcMainLike): void {\n if (typeof ipcMain.removeHandler === 'function') {\n ipcMain.removeHandler('__trace');\n }\n\n ipcMain.handle('__trace', async (_event, rawPayload) => {\n return dispatchRendererTracePayload(rawPayload);\n });\n\n logger.info('renderer trace bridge registered');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n if (typeof ipcMain.removeHandler === 'function') {\n ipcMain.removeHandler('__log');\n }\n\n ipcMain.handle('__log', async (event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, event);\n const result = await dispatcher.dispatch(entry) as RendererLogDispatchResult;\n if (!result.ok) {\n logger.warn('renderer log callback failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: result.reason ?? null,\n errorMessage: result.errorMessage ?? null,\n });\n }\n return result;\n });\n\n logger.info('renderer log bridge registered');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA0B;AAC1B,yBAA2B;AAC3B,2BAA6B;AAC7B,qBAAyE;AACzE,qCAKO;AAEP,MAAM,aAAS,yBAAU,cAAc;AA6CvC,SAAS,0BAA0B,OAAkC;AACnE,MAAI,UAAU,WAAW,UAAU,UAAU,UAAU,SAAS;AAC9D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,yBACP,YACA,OACkB;AAClB,QAAM,UAAW,cAAc,CAAC;AAChC,QAAM,WAAW;AAEjB,SAAO;AAAA,IACL,OAAO,0BAA0B,QAAQ,KAAK;AAAA,IAC9C,QAAQ,OAAO,QAAQ,WAAW,YAAY,QAAQ,OAAO,KAAK,EAAE,SAAS,IACzE,QAAQ,SACR;AAAA,IACJ,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAAA,IACjE,SAAS,QAAQ;AAAA,IACjB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,UAAU,OAAO,UAAU,QAAQ,OAAO,WAAW,SAAS,OAAO,KAAK;AAAA,EAC5E;AACF;AAKA,eAAsB,QAAQ,SAAiD;AAC7E,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,0BAA0B;AAAA,IAC1B,4BAA4B;AAAA,EAC9B,IAAI;AAEJ,QAAM,YAAY,QAAQ,iBAAa,mCAAa;AAEpD,SAAO,KAAK,iBAAiB;AAAA,IAC3B;AAAA,IACA,sBAAsB,CAAC,CAAC,QAAQ;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,OAAO,UAAU,aAAa,YAAY;AAC5C,UAAM,qBAAqB,MAAM,UAAU,SAAS,yCAA0B;AAC9E,uBAAmB,iBAAiB,MAAM;AAAA,EAC5C;AAEA,QAAM,SAAS,IAAI,8BAAW;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,kBAAgB,MAAM;AACtB,SAAO,KAAK,+BAA+B;AAE3C,SAAO,oBAAoB;AAC3B,SAAO,KAAK,wCAAwC;AAEpD,SAAO,wBAAwB,UAAU,OAAO,MAAM,UAAU;AAC9D,QAAI,CAAC,QAAQ,QAAQ;AACnB,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC1F;AACA,WAAO,QAAQ,OAAO,MAAM,KAAK;AAAA,EACnC,CAAC;AAED,SAAO,wBAAwB,cAAc,OAAO,MAAM,UAAU;AAClE,QAAI,CAAC,QAAQ,YAAY;AACvB,YAAM,IAAI,MAAM,gFAAgF;AAAA,IAClG;AACA,WAAO,QAAQ,WAAW,MAAM,KAAK;AAAA,EACvC,CAAC;AAED,SAAO,wBAAwB,YAAY,OAAO,MAAM,UAAU;AAChE,QAAI,CAAC,QAAQ,UAAU;AACrB,YAAM,IAAI,MAAM,4EAA4E;AAAA,IAC9F;AACA,WAAO,QAAQ,SAAS,MAAM,KAAK;AAAA,EACrC,CAAC;AAED,SAAO,wBAAwB,WAAW,OAAO,MAAM,UAAU;AAC/D,QAAI,CAAC,QAAQ,SAAS;AACpB,YAAM,IAAI,MAAM,0EAA0E;AAAA,IAC5F;AACA,WAAO,QAAQ,QAAQ,MAAM,KAAK;AAAA,EACpC,CAAC;AAED,SAAO,wBAAwB,iBAAiB,OAAO,MAAM,UAAU;AACrE,QAAI,CAAC,QAAQ,eAAe;AAC1B,YAAM,IAAI,MAAM,sFAAsF;AAAA,IACxG;AACA,WAAO,QAAQ,cAAc,MAAM,KAAK;AAAA,EAC1C,CAAC;AAED,MAAI,yBAAyB;AAC3B,8BAA0B,OAAO;AAAA,EACnC;AAEA,MAAI,2BAA2B;AAC7B,gCAA4B,OAAO;AAAA,EACrC;AAEA,SAAO,oBAAoB,OAAO;AAClC,SAAO,KAAK,mCAAmC;AAAA,IAC7C,cAAc,OAAO,YAAY,EAAE;AAAA,IACnC;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,EAAE,OAAO;AAClB;AAEA,SAAS,4BAA4B,SAA4B;AAC/D,MAAI,OAAO,QAAQ,kBAAkB,YAAY;AAC/C,YAAQ,cAAc,SAAS;AAAA,EACjC;AAEA,UAAQ,OAAO,WAAW,OAAO,QAAQ,eAAe;AACtD,eAAO,6CAA6B,UAAU;AAAA,EAChD,CAAC;AAED,SAAO,KAAK,kCAAkC;AAChD;AAEA,SAAS,0BAA0B,SAA4B;AAC7D,QAAM,iBAAa,yDAAyB;AAE5C,MAAI,OAAO,QAAQ,kBAAkB,YAAY;AAC/C,YAAQ,cAAc,OAAO;AAAA,EAC/B;AAEA,UAAQ,OAAO,SAAS,OAAO,OAAO,eAAe;AACnD,UAAM,QAAQ,yBAAyB,YAAY,KAAK;AACxD,UAAM,SAAS,MAAM,WAAW,SAAS,KAAK;AAC9C,QAAI,CAAC,OAAO,IAAI;AACd,aAAO,KAAK,gCAAgC;AAAA,QAC1C,QAAQ,MAAM;AAAA,QACd,eAAe,MAAM,QAAQ;AAAA,QAC7B,QAAQ,OAAO,UAAU;AAAA,QACzB,cAAc,OAAO,gBAAgB;AAAA,MACvC,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO,KAAK,gCAAgC;AAC9C;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.cjs';\nimport { getContainer } from './get_container.cjs';\nimport { TraceProviderConfiguration, dispatchRendererTracePayload } from '../tracing/index.js';\nimport { setMainTraceMinLevel, type TraceLevel } from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (level === 'debug' || level === 'warn' || level === 'error') {\n return level;\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n } = options;\n\n const container = options.container ?? getContainer();\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n });\n\n if (traceMinLevel) {\n setMainTraceMinLevel(traceMinLevel);\n }\n\n if (typeof container.instance === 'function') {\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (traceMinLevel) {\n traceConfiguration.configureMinLevel(traceMinLevel);\n }\n }\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.registerReservedHandler('__load', async (data, event) => {\n if (!options.onLoad) {\n throw new Error('Reserved channel \"__load\" not configured. Provide runtime({ onLoad }).');\n }\n return options.onLoad(data, event);\n });\n\n router.registerReservedHandler('__navigate', async (data, event) => {\n if (!options.onNavigate) {\n throw new Error('Reserved channel \"__navigate\" not configured. Provide runtime({ onNavigate }).');\n }\n return options.onNavigate(data, event);\n });\n\n router.registerReservedHandler('__window', async (data, event) => {\n if (!options.onWindow) {\n throw new Error('Reserved channel \"__window\" not configured. Provide runtime({ onWindow }).');\n }\n return options.onWindow(data, event);\n });\n\n router.registerReservedHandler('__debug', async (data, event) => {\n if (!options.onDebug) {\n throw new Error('Reserved channel \"__debug\" not configured. Provide runtime({ onDebug }).');\n }\n return options.onDebug(data, event);\n });\n\n router.registerReservedHandler('__contextMenu', async (data, event) => {\n if (!options.onContextMenu) {\n throw new Error('Reserved channel \"__contextMenu\" not configured. Provide runtime({ onContextMenu }).');\n }\n return options.onContextMenu(data, event);\n });\n\n router.registerReservedHandler('__woodConfig', async () => {\n return {\n traceMinLevel: traceMinLevel ?? 'debug',\n };\n });\n\n if (enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n\n if (enableRendererTraceBridge) {\n registerRendererTraceBridge(ipcMain);\n }\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nfunction registerRendererTraceBridge(ipcMain: IpcMainLike): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (_event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload);\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":["import_tracing"]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { WoodRouter } from '../router/wood_router.cjs';
|
|
2
|
+
import { TraceLevel } from '../tracing/trace_hub.cjs';
|
|
2
3
|
import '../types/operations.cjs';
|
|
4
|
+
import 'rxjs';
|
|
3
5
|
|
|
4
6
|
type IpcMainLike = {
|
|
5
7
|
handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;
|
|
8
|
+
on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;
|
|
6
9
|
removeHandler?: (channel: string) => void;
|
|
10
|
+
removeAllListeners?: (channel: string) => void;
|
|
7
11
|
};
|
|
8
12
|
interface RegisterRuntimeRouter {
|
|
9
13
|
registerController(name: string, cls: any): void;
|
|
@@ -18,6 +22,7 @@ interface RuntimeOptions {
|
|
|
18
22
|
mode?: 'bundled' | 'dev';
|
|
19
23
|
enableRendererLogBridge?: boolean;
|
|
20
24
|
enableRendererTraceBridge?: boolean;
|
|
25
|
+
traceMinLevel?: TraceLevel;
|
|
21
26
|
onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;
|
|
22
27
|
onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;
|
|
23
28
|
onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { WoodRouter } from '../router/wood_router.js';
|
|
2
|
+
import { TraceLevel } from '../tracing/trace_hub.js';
|
|
2
3
|
import '../types/operations.js';
|
|
4
|
+
import 'rxjs';
|
|
3
5
|
|
|
4
6
|
type IpcMainLike = {
|
|
5
7
|
handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;
|
|
8
|
+
on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;
|
|
6
9
|
removeHandler?: (channel: string) => void;
|
|
10
|
+
removeAllListeners?: (channel: string) => void;
|
|
7
11
|
};
|
|
8
12
|
interface RegisterRuntimeRouter {
|
|
9
13
|
registerController(name: string, cls: any): void;
|
|
@@ -18,6 +22,7 @@ interface RuntimeOptions {
|
|
|
18
22
|
mode?: 'bundled' | 'dev';
|
|
19
23
|
enableRendererLogBridge?: boolean;
|
|
20
24
|
enableRendererTraceBridge?: boolean;
|
|
25
|
+
traceMinLevel?: TraceLevel;
|
|
21
26
|
onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;
|
|
22
27
|
onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;
|
|
23
28
|
onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;
|
package/dist/runtime/runtime.js
CHANGED
|
@@ -2,6 +2,7 @@ import { getLogger } from "@noego/logger";
|
|
|
2
2
|
import { WoodRouter } from "../router/wood_router.js";
|
|
3
3
|
import { getContainer } from "./get_container.js";
|
|
4
4
|
import { TraceProviderConfiguration, dispatchRendererTracePayload } from "../tracing/index.js";
|
|
5
|
+
import { setMainTraceMinLevel } from "../tracing/index.js";
|
|
5
6
|
import {
|
|
6
7
|
getRendererLogDispatcher
|
|
7
8
|
} from "./renderer_log_dispatcher.js";
|
|
@@ -32,7 +33,8 @@ async function runtime(options) {
|
|
|
32
33
|
middlewareDir,
|
|
33
34
|
mode = "bundled",
|
|
34
35
|
enableRendererLogBridge = true,
|
|
35
|
-
enableRendererTraceBridge = true
|
|
36
|
+
enableRendererTraceBridge = true,
|
|
37
|
+
traceMinLevel
|
|
36
38
|
} = options;
|
|
37
39
|
const container = options.container ?? getContainer();
|
|
38
40
|
logger.info("runtime start", {
|
|
@@ -41,11 +43,18 @@ async function runtime(options) {
|
|
|
41
43
|
controllersDir,
|
|
42
44
|
middlewareDir,
|
|
43
45
|
enableRendererLogBridge,
|
|
44
|
-
enableRendererTraceBridge
|
|
46
|
+
enableRendererTraceBridge,
|
|
47
|
+
traceMinLevel: traceMinLevel ?? "debug"
|
|
45
48
|
});
|
|
49
|
+
if (traceMinLevel) {
|
|
50
|
+
setMainTraceMinLevel(traceMinLevel);
|
|
51
|
+
}
|
|
46
52
|
if (typeof container.instance === "function") {
|
|
47
53
|
const traceConfiguration = await container.instance(TraceProviderConfiguration);
|
|
48
54
|
traceConfiguration.configureRuntime("main");
|
|
55
|
+
if (traceMinLevel) {
|
|
56
|
+
traceConfiguration.configureMinLevel(traceMinLevel);
|
|
57
|
+
}
|
|
49
58
|
}
|
|
50
59
|
const router = new WoodRouter({
|
|
51
60
|
container,
|
|
@@ -87,6 +96,11 @@ async function runtime(options) {
|
|
|
87
96
|
}
|
|
88
97
|
return options.onContextMenu(data, event);
|
|
89
98
|
});
|
|
99
|
+
router.registerReservedHandler("__woodConfig", async () => {
|
|
100
|
+
return {
|
|
101
|
+
traceMinLevel: traceMinLevel ?? "debug"
|
|
102
|
+
};
|
|
103
|
+
});
|
|
90
104
|
if (enableRendererLogBridge) {
|
|
91
105
|
registerRendererLogBridge(ipcMain);
|
|
92
106
|
}
|
|
@@ -102,33 +116,30 @@ async function runtime(options) {
|
|
|
102
116
|
return { router };
|
|
103
117
|
}
|
|
104
118
|
function registerRendererTraceBridge(ipcMain) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
ipcMain.handle("__trace", async (_event, rawPayload) => {
|
|
109
|
-
return dispatchRendererTracePayload(rawPayload);
|
|
119
|
+
ipcMain.removeAllListeners?.("__trace");
|
|
120
|
+
ipcMain.on("__trace", (_event, rawPayload) => {
|
|
121
|
+
dispatchRendererTracePayload(rawPayload);
|
|
110
122
|
});
|
|
111
|
-
logger.info("renderer trace bridge registered");
|
|
123
|
+
logger.info("renderer trace bridge registered (fire-and-forget)");
|
|
112
124
|
}
|
|
113
125
|
function registerRendererLogBridge(ipcMain) {
|
|
114
126
|
const dispatcher = getRendererLogDispatcher();
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return result;
|
|
127
|
+
ipcMain.removeAllListeners?.("__log");
|
|
128
|
+
ipcMain.on("__log", (_event, rawPayload) => {
|
|
129
|
+
const entry = coerceRendererLogPayload(rawPayload, null);
|
|
130
|
+
void dispatcher.dispatch(entry).then((result) => {
|
|
131
|
+
const typedResult = result;
|
|
132
|
+
if (!typedResult.ok) {
|
|
133
|
+
logger.warn("renderer log dispatch failed", {
|
|
134
|
+
logger: entry.logger,
|
|
135
|
+
messageLength: entry.message.length,
|
|
136
|
+
reason: typedResult.reason ?? null,
|
|
137
|
+
errorMessage: typedResult.errorMessage ?? null
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
130
141
|
});
|
|
131
|
-
logger.info("renderer log bridge registered");
|
|
142
|
+
logger.info("renderer log bridge registered (fire-and-forget)");
|
|
132
143
|
}
|
|
133
144
|
export {
|
|
134
145
|
runtime
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.js';\nimport { getContainer } from './get_container.js';\nimport { TraceProviderConfiguration, dispatchRendererTracePayload } from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n removeHandler?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (level === 'debug' || level === 'warn' || level === 'error') {\n return level;\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n } = options;\n\n const container = options.container ?? getContainer();\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n if (typeof container.instance === 'function') {\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n }\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.registerReservedHandler('__load', async (data, event) => {\n if (!options.onLoad) {\n throw new Error('Reserved channel \"__load\" not configured. Provide runtime({ onLoad }).');\n }\n return options.onLoad(data, event);\n });\n\n router.registerReservedHandler('__navigate', async (data, event) => {\n if (!options.onNavigate) {\n throw new Error('Reserved channel \"__navigate\" not configured. Provide runtime({ onNavigate }).');\n }\n return options.onNavigate(data, event);\n });\n\n router.registerReservedHandler('__window', async (data, event) => {\n if (!options.onWindow) {\n throw new Error('Reserved channel \"__window\" not configured. Provide runtime({ onWindow }).');\n }\n return options.onWindow(data, event);\n });\n\n router.registerReservedHandler('__debug', async (data, event) => {\n if (!options.onDebug) {\n throw new Error('Reserved channel \"__debug\" not configured. Provide runtime({ onDebug }).');\n }\n return options.onDebug(data, event);\n });\n\n router.registerReservedHandler('__contextMenu', async (data, event) => {\n if (!options.onContextMenu) {\n throw new Error('Reserved channel \"__contextMenu\" not configured. Provide runtime({ onContextMenu }).');\n }\n return options.onContextMenu(data, event);\n });\n\n if (enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n\n if (enableRendererTraceBridge) {\n registerRendererTraceBridge(ipcMain);\n }\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nfunction registerRendererTraceBridge(ipcMain: IpcMainLike): void {\n if (typeof ipcMain.removeHandler === 'function') {\n ipcMain.removeHandler('__trace');\n }\n\n ipcMain.handle('__trace', async (_event, rawPayload) => {\n return dispatchRendererTracePayload(rawPayload);\n });\n\n logger.info('renderer trace bridge registered');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n if (typeof ipcMain.removeHandler === 'function') {\n ipcMain.removeHandler('__log');\n }\n\n ipcMain.handle('__log', async (event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, event);\n const result = await dispatcher.dispatch(entry) as RendererLogDispatchResult;\n if (!result.ok) {\n logger.warn('renderer log callback failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: result.reason ?? null,\n errorMessage: result.errorMessage ?? null,\n });\n }\n return result;\n });\n\n logger.info('renderer log bridge registered');\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/runtime.ts"],"sourcesContent":["import { getLogger } from '@noego/logger';\nimport { WoodRouter } from '../router/wood_router.js';\nimport { getContainer } from './get_container.js';\nimport { TraceProviderConfiguration, dispatchRendererTracePayload } from '../tracing/index.js';\nimport { setMainTraceMinLevel, type TraceLevel } from '../tracing/index.js';\nimport {\n getRendererLogDispatcher,\n type RendererLogDispatchResult,\n type RendererLogEntry,\n type RendererLogLevel,\n} from './renderer_log_dispatcher.js';\n\nconst logger = getLogger('wood:runtime');\n\ntype IpcMainLike = {\n handle: (channel: string, handler: (_event: unknown, data: unknown) => Promise<unknown> | unknown) => void;\n on: (channel: string, handler: (_event: unknown, ...args: unknown[]) => void) => void;\n removeHandler?: (channel: string) => void;\n removeAllListeners?: (channel: string) => void;\n};\n\nexport interface RegisterRuntimeRouter {\n registerController(name: string, cls: any): void;\n loadOperations(operations: Map<string, any>): void;\n}\n\nexport interface RuntimeOptions {\n ipcMain: IpcMainLike;\n registerRuntime: (router: RegisterRuntimeRouter) => void;\n container?: any;\n controllersDir: string;\n middlewareDir: string;\n mode?: 'bundled' | 'dev';\n enableRendererLogBridge?: boolean;\n enableRendererTraceBridge?: boolean;\n traceMinLevel?: TraceLevel;\n onLoad?: (data: unknown, event?: unknown) => Promise<unknown>;\n onNavigate?: (data: unknown, event?: unknown) => Promise<unknown>;\n onWindow?: (data: unknown, event?: unknown) => Promise<unknown>;\n onDebug?: (data: unknown, event?: unknown) => Promise<unknown>;\n onContextMenu?: (data: unknown, event?: unknown) => Promise<unknown>;\n}\n\nexport interface RuntimeResult {\n router: WoodRouter;\n}\n\ntype RendererLogPayload = {\n level: string;\n logger: string;\n message: string;\n context?: unknown;\n};\n\ntype IpcInvokeEventLike = {\n sender?: {\n id?: number;\n };\n};\n\nfunction normalizeRendererLogLevel(level: unknown): RendererLogLevel {\n if (level === 'debug' || level === 'warn' || level === 'error') {\n return level;\n }\n return 'info';\n}\n\nfunction coerceRendererLogPayload(\n rawPayload: unknown,\n event: unknown,\n): RendererLogEntry {\n const payload = (rawPayload ?? {}) as Partial<RendererLogPayload>;\n const ipcEvent = event as IpcInvokeEventLike;\n\n return {\n level: normalizeRendererLogLevel(payload.level),\n logger: typeof payload.logger === 'string' && payload.logger.trim().length > 0\n ? payload.logger\n : 'renderer',\n message: typeof payload.message === 'string' ? payload.message : '',\n context: payload.context,\n timestamp: new Date().toISOString(),\n senderId: typeof ipcEvent?.sender?.id === 'number' ? ipcEvent.sender.id : null,\n };\n}\n\n/**\n * Boot a bundled-safe Wood runtime using pre-generated static runtime artifacts.\n */\nexport async function runtime(options: RuntimeOptions): Promise<RuntimeResult> {\n const {\n ipcMain,\n registerRuntime,\n controllersDir,\n middlewareDir,\n mode = 'bundled',\n enableRendererLogBridge = true,\n enableRendererTraceBridge = true,\n traceMinLevel,\n } = options;\n\n const container = options.container ?? getContainer();\n\n logger.info('runtime start', {\n mode,\n hasProvidedContainer: !!options.container,\n controllersDir,\n middlewareDir,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n traceMinLevel: traceMinLevel ?? 'debug',\n });\n\n if (traceMinLevel) {\n setMainTraceMinLevel(traceMinLevel);\n }\n\n if (typeof container.instance === 'function') {\n const traceConfiguration = await container.instance(TraceProviderConfiguration);\n traceConfiguration.configureRuntime('main');\n if (traceMinLevel) {\n traceConfiguration.configureMinLevel(traceMinLevel);\n }\n }\n\n const router = new WoodRouter({\n container,\n controllersDir,\n middlewareDir,\n mode,\n });\n\n registerRuntime(router);\n logger.info('runtime registration complete');\n\n router.validateControllers();\n logger.info('runtime controller validation complete');\n\n router.registerReservedHandler('__load', async (data, event) => {\n if (!options.onLoad) {\n throw new Error('Reserved channel \"__load\" not configured. Provide runtime({ onLoad }).');\n }\n return options.onLoad(data, event);\n });\n\n router.registerReservedHandler('__navigate', async (data, event) => {\n if (!options.onNavigate) {\n throw new Error('Reserved channel \"__navigate\" not configured. Provide runtime({ onNavigate }).');\n }\n return options.onNavigate(data, event);\n });\n\n router.registerReservedHandler('__window', async (data, event) => {\n if (!options.onWindow) {\n throw new Error('Reserved channel \"__window\" not configured. Provide runtime({ onWindow }).');\n }\n return options.onWindow(data, event);\n });\n\n router.registerReservedHandler('__debug', async (data, event) => {\n if (!options.onDebug) {\n throw new Error('Reserved channel \"__debug\" not configured. Provide runtime({ onDebug }).');\n }\n return options.onDebug(data, event);\n });\n\n router.registerReservedHandler('__contextMenu', async (data, event) => {\n if (!options.onContextMenu) {\n throw new Error('Reserved channel \"__contextMenu\" not configured. Provide runtime({ onContextMenu }).');\n }\n return options.onContextMenu(data, event);\n });\n\n router.registerReservedHandler('__woodConfig', async () => {\n return {\n traceMinLevel: traceMinLevel ?? 'debug',\n };\n });\n\n if (enableRendererLogBridge) {\n registerRendererLogBridge(ipcMain);\n }\n\n if (enableRendererTraceBridge) {\n registerRendererTraceBridge(ipcMain);\n }\n\n router.registerIpcHandlers(ipcMain);\n logger.info('runtime ipc handlers registered', {\n channelCount: router.getChannels().length,\n enableRendererLogBridge,\n enableRendererTraceBridge,\n });\n\n return { router };\n}\n\nfunction registerRendererTraceBridge(ipcMain: IpcMainLike): void {\n ipcMain.removeAllListeners?.('__trace');\n\n ipcMain.on('__trace', (_event, rawPayload) => {\n dispatchRendererTracePayload(rawPayload);\n });\n\n logger.info('renderer trace bridge registered (fire-and-forget)');\n}\n\nfunction registerRendererLogBridge(ipcMain: IpcMainLike): void {\n const dispatcher = getRendererLogDispatcher();\n\n ipcMain.removeAllListeners?.('__log');\n\n ipcMain.on('__log', (_event, rawPayload) => {\n const entry = coerceRendererLogPayload(rawPayload, null);\n void dispatcher.dispatch(entry).then((result) => {\n const typedResult = result as RendererLogDispatchResult;\n if (!typedResult.ok) {\n logger.warn('renderer log dispatch failed', {\n logger: entry.logger,\n messageLength: entry.message.length,\n reason: typedResult.reason ?? null,\n errorMessage: typedResult.errorMessage ?? null,\n });\n }\n });\n });\n\n logger.info('renderer log bridge registered (fire-and-forget)');\n}\n"],"mappings":"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","names":[]}
|
package/dist/tracing/index.cjs
CHANGED
|
@@ -31,7 +31,9 @@ __export(tracing_exports, {
|
|
|
31
31
|
emitRendererTrace: () => import_trace_hub.emitRendererTrace,
|
|
32
32
|
getTraceEvents$: () => import_trace_hub.getTraceEvents$,
|
|
33
33
|
publishMainTrace: () => import_trace_hub.publishMainTrace,
|
|
34
|
-
publishTestTrace: () => import_trace_hub.publishTestTrace
|
|
34
|
+
publishTestTrace: () => import_trace_hub.publishTestTrace,
|
|
35
|
+
setMainTraceMinLevel: () => import_trace_hub.setMainTraceMinLevel,
|
|
36
|
+
setRendererTraceMinLevel: () => import_trace_hub.setRendererTraceMinLevel
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(tracing_exports);
|
|
37
39
|
var import_trace_hub = require("./trace_hub.js");
|
|
@@ -51,6 +53,8 @@ var import_trace_provider = require("./trace_provider.js");
|
|
|
51
53
|
emitRendererTrace,
|
|
52
54
|
getTraceEvents$,
|
|
53
55
|
publishMainTrace,
|
|
54
|
-
publishTestTrace
|
|
56
|
+
publishTestTrace,
|
|
57
|
+
setMainTraceMinLevel,
|
|
58
|
+
setRendererTraceMinLevel
|
|
55
59
|
});
|
|
56
60
|
//# 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 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,
|
|
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":[]}
|
package/dist/tracing/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace } from './trace_hub.cjs';
|
|
1
|
+
export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel } 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';
|
package/dist/tracing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace } from './trace_hub.js';
|
|
1
|
+
export { TraceCapture, TraceCaptureOptions, TraceDispatchResult, TraceEvent, TraceInput, TraceLevel, TraceProcess, TraceWaitOptions, clearTraceHubForTests, createTraceCapture, dispatchRendererTracePayload, emitRendererTrace, getTraceEvents$, publishMainTrace, publishTestTrace, setMainTraceMinLevel, setRendererTraceMinLevel } 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';
|
package/dist/tracing/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
getTraceEvents$,
|
|
7
7
|
publishMainTrace,
|
|
8
8
|
publishTestTrace,
|
|
9
|
+
setMainTraceMinLevel,
|
|
10
|
+
setRendererTraceMinLevel,
|
|
9
11
|
TraceCapture
|
|
10
12
|
} from "./trace_hub.js";
|
|
11
13
|
import {
|
|
@@ -30,6 +32,8 @@ export {
|
|
|
30
32
|
emitRendererTrace,
|
|
31
33
|
getTraceEvents$,
|
|
32
34
|
publishMainTrace,
|
|
33
|
-
publishTestTrace
|
|
35
|
+
publishTestTrace,
|
|
36
|
+
setMainTraceMinLevel,
|
|
37
|
+
setRendererTraceMinLevel
|
|
34
38
|
};
|
|
35
39
|
//# 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 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,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 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":[]}
|
|
@@ -35,12 +35,21 @@ __export(trace_hub_exports, {
|
|
|
35
35
|
emitRendererTrace: () => emitRendererTrace,
|
|
36
36
|
getTraceEvents$: () => getTraceEvents$,
|
|
37
37
|
publishMainTrace: () => publishMainTrace,
|
|
38
|
-
publishTestTrace: () => publishTestTrace
|
|
38
|
+
publishTestTrace: () => publishTestTrace,
|
|
39
|
+
setMainTraceMinLevel: () => setMainTraceMinLevel,
|
|
40
|
+
setRendererTraceMinLevel: () => setRendererTraceMinLevel
|
|
39
41
|
});
|
|
40
42
|
module.exports = __toCommonJS(trace_hub_exports);
|
|
41
43
|
var import_rxjs = require("rxjs");
|
|
42
44
|
var import_operators = require("rxjs/operators");
|
|
43
45
|
const TRACE_HUB_SYMBOL = /* @__PURE__ */ Symbol.for("@noego/wood.trace.hub");
|
|
46
|
+
const LEVEL_ORDER = {
|
|
47
|
+
debug: 0,
|
|
48
|
+
info: 1,
|
|
49
|
+
warn: 2,
|
|
50
|
+
error: 3
|
|
51
|
+
};
|
|
52
|
+
let rendererMinLevel = "debug";
|
|
44
53
|
function normalizeTraceInput(raw) {
|
|
45
54
|
const input = raw ?? {};
|
|
46
55
|
const source = typeof input.source === "string" && input.source.trim().length > 0 ? input.source : "unknown";
|
|
@@ -136,10 +145,14 @@ class TraceHub {
|
|
|
136
145
|
this.subject = new import_rxjs.Subject();
|
|
137
146
|
this.shared$ = this.subject.asObservable().pipe((0, import_operators.share)());
|
|
138
147
|
this.nextTraceSeq = 1;
|
|
148
|
+
this.minLevel = "debug";
|
|
139
149
|
}
|
|
140
150
|
get events$() {
|
|
141
151
|
return this.shared$;
|
|
142
152
|
}
|
|
153
|
+
setMinLevel(level) {
|
|
154
|
+
this.minLevel = level;
|
|
155
|
+
}
|
|
143
156
|
publish(process, level, input) {
|
|
144
157
|
const normalized = normalizeTraceInput(input);
|
|
145
158
|
const event = {
|
|
@@ -149,7 +162,9 @@ class TraceHub {
|
|
|
149
162
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
150
163
|
traceSeq: this.nextTraceSeq++
|
|
151
164
|
};
|
|
152
|
-
this.
|
|
165
|
+
if (LEVEL_ORDER[level] >= LEVEL_ORDER[this.minLevel]) {
|
|
166
|
+
this.subject.next(event);
|
|
167
|
+
}
|
|
153
168
|
return event;
|
|
154
169
|
}
|
|
155
170
|
capture(options = {}) {
|
|
@@ -166,6 +181,12 @@ function getGlobalTraceHub() {
|
|
|
166
181
|
function getTraceEvents$() {
|
|
167
182
|
return getGlobalTraceHub().events$;
|
|
168
183
|
}
|
|
184
|
+
function setMainTraceMinLevel(level) {
|
|
185
|
+
getGlobalTraceHub().setMinLevel(level);
|
|
186
|
+
}
|
|
187
|
+
function setRendererTraceMinLevel(level) {
|
|
188
|
+
rendererMinLevel = level;
|
|
189
|
+
}
|
|
169
190
|
function publishMainTrace(level, input) {
|
|
170
191
|
return getGlobalTraceHub().publish("main", level, input);
|
|
171
192
|
}
|
|
@@ -182,15 +203,20 @@ function dispatchRendererTracePayload(rawPayload) {
|
|
|
182
203
|
};
|
|
183
204
|
}
|
|
184
205
|
function emitRendererTrace(level, input) {
|
|
206
|
+
if (LEVEL_ORDER[level] < LEVEL_ORDER[rendererMinLevel]) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
185
209
|
const bridge = resolveTraceBridge();
|
|
186
210
|
if (!bridge || typeof bridge.__trace !== "function") {
|
|
187
211
|
return;
|
|
188
212
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
213
|
+
try {
|
|
214
|
+
bridge.__trace({
|
|
215
|
+
...normalizeTraceInput(input),
|
|
216
|
+
level
|
|
217
|
+
});
|
|
218
|
+
} catch {
|
|
219
|
+
}
|
|
194
220
|
}
|
|
195
221
|
function createTraceCapture(options = {}) {
|
|
196
222
|
return getGlobalTraceHub().capture(options);
|
|
@@ -198,6 +224,7 @@ function createTraceCapture(options = {}) {
|
|
|
198
224
|
function clearTraceHubForTests() {
|
|
199
225
|
const globalObj = globalThis;
|
|
200
226
|
delete globalObj[TRACE_HUB_SYMBOL];
|
|
227
|
+
rendererMinLevel = "debug";
|
|
201
228
|
}
|
|
202
229
|
// Annotate the CommonJS export names for ESM import in node:
|
|
203
230
|
0 && (module.exports = {
|
|
@@ -208,6 +235,8 @@ function clearTraceHubForTests() {
|
|
|
208
235
|
emitRendererTrace,
|
|
209
236
|
getTraceEvents$,
|
|
210
237
|
publishMainTrace,
|
|
211
|
-
publishTestTrace
|
|
238
|
+
publishTestTrace,
|
|
239
|
+
setMainTraceMinLevel,
|
|
240
|
+
setRendererTraceMinLevel
|
|
212
241
|
});
|
|
213
242
|
//# sourceMappingURL=trace_hub.cjs.map
|