@noego/wood 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/client/index.cjs +18 -11
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +21 -1
- package/dist/client/index.d.ts +21 -1
- package/dist/client/index.js +17 -11
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +2 -9
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +2 -9
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/controller/cleanup.cjs +39 -0
- package/dist/controller/cleanup.cjs.map +1 -0
- package/dist/controller/cleanup.d.cts +4 -0
- package/dist/controller/cleanup.d.ts +4 -0
- package/dist/controller/cleanup.js +15 -0
- package/dist/controller/cleanup.js.map +1 -0
- package/dist/controller/controller_lifecycle.cjs +26 -2
- package/dist/controller/controller_lifecycle.cjs.map +1 -1
- package/dist/controller/controller_lifecycle.d.cts +3 -1
- package/dist/controller/controller_lifecycle.d.ts +3 -1
- package/dist/controller/controller_lifecycle.js +24 -1
- package/dist/controller/controller_lifecycle.js.map +1 -1
- package/dist/frontend/frontend_lifecycle.cjs +5 -7
- package/dist/frontend/frontend_lifecycle.cjs.map +1 -1
- package/dist/frontend/frontend_lifecycle.d.cts +1 -14
- package/dist/frontend/frontend_lifecycle.d.ts +1 -14
- package/dist/frontend/frontend_lifecycle.js +5 -7
- package/dist/frontend/frontend_lifecycle.js.map +1 -1
- package/dist/frontend/frontend_surface.cjs +130 -104
- package/dist/frontend/frontend_surface.cjs.map +1 -1
- package/dist/frontend/frontend_surface.js +131 -105
- package/dist/frontend/frontend_surface.js.map +1 -1
- package/dist/frontend/work_registry.cjs +29 -4
- package/dist/frontend/work_registry.cjs.map +1 -1
- package/dist/frontend/work_registry.d.cts +2 -0
- package/dist/frontend/work_registry.d.ts +2 -0
- package/dist/frontend/work_registry.js +29 -4
- package/dist/frontend/work_registry.js.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/ipc/index.cjs +6 -2
- package/dist/ipc/index.cjs.map +1 -1
- package/dist/ipc/index.d.cts +9 -0
- package/dist/ipc/index.d.ts +9 -0
- package/dist/ipc/index.js +6 -2
- package/dist/ipc/index.js.map +1 -1
- package/dist/main/index.cjs +53 -35
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +11 -2
- package/dist/main/index.d.ts +11 -2
- package/dist/main/index.js +56 -40
- package/dist/main/index.js.map +1 -1
- package/dist/main/startup_failure_handler.cjs +67 -0
- package/dist/main/startup_failure_handler.cjs.map +1 -0
- package/dist/main/startup_failure_handler.d.cts +16 -0
- package/dist/main/startup_failure_handler.d.ts +16 -0
- package/dist/main/startup_failure_handler.js +43 -0
- package/dist/main/startup_failure_handler.js.map +1 -0
- package/dist/router/index.d.cts +3 -0
- package/dist/router/index.d.ts +3 -0
- package/dist/router/wood_router.cjs +204 -123
- package/dist/router/wood_router.cjs.map +1 -1
- package/dist/router/wood_router.d.cts +20 -0
- package/dist/router/wood_router.d.ts +20 -0
- package/dist/router/wood_router.js +206 -125
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/index.cjs +13 -0
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +8 -4
- package/dist/runtime/index.d.ts +8 -4
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderer_config_extension.cjs +1 -2
- package/dist/runtime/renderer_config_extension.cjs.map +1 -1
- package/dist/runtime/renderer_config_extension.d.cts +1 -1
- package/dist/runtime/renderer_config_extension.d.ts +1 -1
- package/dist/runtime/renderer_config_extension.js +1 -2
- package/dist/runtime/renderer_config_extension.js.map +1 -1
- package/dist/runtime/renderer_log_dispatcher.cjs +2 -0
- package/dist/runtime/renderer_log_dispatcher.cjs.map +1 -1
- package/dist/runtime/renderer_log_dispatcher.d.cts +1 -1
- package/dist/runtime/renderer_log_dispatcher.d.ts +1 -1
- package/dist/runtime/renderer_log_dispatcher.js +1 -0
- package/dist/runtime/renderer_log_dispatcher.js.map +1 -1
- package/dist/runtime/runtime.cjs +107 -57
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +12 -0
- package/dist/runtime/runtime.d.ts +12 -0
- package/dist/runtime/runtime.js +110 -59
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/runtime_module.cjs +58 -0
- package/dist/runtime/runtime_module.cjs.map +1 -0
- package/dist/runtime/runtime_module.d.cts +22 -0
- package/dist/runtime/runtime_module.d.ts +22 -0
- package/dist/runtime/runtime_module.js +30 -0
- package/dist/runtime/runtime_module.js.map +1 -0
- package/dist/testing/create_controller_harness.d.cts +3 -0
- package/dist/testing/create_controller_harness.d.ts +3 -0
- package/dist/testing/create_router_bridge.d.cts +3 -0
- package/dist/testing/create_router_bridge.d.ts +3 -0
- package/dist/testing/create_test_router.d.cts +3 -0
- package/dist/testing/create_test_router.d.ts +3 -0
- package/dist/testing/index.cjs +3 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +6 -1
- package/dist/testing/index.d.ts +6 -1
- package/dist/testing/index.js +2 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/registration_only_root.cjs +168 -0
- package/dist/testing/registration_only_root.cjs.map +1 -0
- package/dist/testing/registration_only_root.d.cts +46 -0
- package/dist/testing/registration_only_root.d.ts +46 -0
- package/dist/testing/registration_only_root.js +141 -0
- package/dist/testing/registration_only_root.js.map +1 -0
- package/dist/testing/test_wood_config.cjs +382 -70
- package/dist/testing/test_wood_config.cjs.map +1 -1
- package/dist/testing/test_wood_config.d.cts +25 -1
- package/dist/testing/test_wood_config.d.ts +25 -1
- package/dist/testing/test_wood_config.js +388 -71
- package/dist/testing/test_wood_config.js.map +1 -1
- package/dist/testing/wood_dom_animation.cjs +213 -0
- package/dist/testing/wood_dom_animation.cjs.map +1 -0
- package/dist/testing/wood_dom_animation.d.cts +89 -0
- package/dist/testing/wood_dom_animation.d.ts +89 -0
- package/dist/testing/wood_dom_animation.js +185 -0
- package/dist/testing/wood_dom_animation.js.map +1 -0
- package/dist/testing/wood_env_renderer.cjs +81 -32
- package/dist/testing/wood_env_renderer.cjs.map +1 -1
- package/dist/testing/wood_env_renderer.d.cts +32 -1
- package/dist/testing/wood_env_renderer.d.ts +32 -1
- package/dist/testing/wood_env_renderer.js +84 -32
- package/dist/testing/wood_env_renderer.js.map +1 -1
- package/dist/transport/in_process_router_transport.d.cts +3 -0
- package/dist/transport/in_process_router_transport.d.ts +3 -0
- package/dist/transport/index.d.cts +3 -0
- package/dist/transport/index.d.ts +3 -0
- package/package.json +8 -6
- package/src/components/NavigationShell.svelte +12 -7
- package/src/controller/cleanup.ts +8 -0
- package/src/controller/controller_lifecycle.ts +24 -0
- package/src/navigation/layout_preservation.ts +45 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
1
2
|
import { WoodValidationError } from "../types/index.js";
|
|
2
3
|
import { SchemaValidator } from "../validation/schema_validator.js";
|
|
3
4
|
import { MiddlewareResolver } from "../middleware/middleware_resolver.js";
|
|
4
5
|
import { buildMiddlewareContext, executeMiddleware } from "../middleware/middleware_pipeline.js";
|
|
5
6
|
import { ControllerResolver, buildControllerArgs, buildOperationContext, usesOperationContext } from "../controller/controller_resolver.js";
|
|
6
|
-
import { disposeControllerLifecycle } from "../controller/controller_lifecycle.js";
|
|
7
|
+
import { disposeControllerLifecycle, guardControllerLifecycleOnce } from "../controller/controller_lifecycle.js";
|
|
7
8
|
import { getLogger } from "@noego/logger";
|
|
8
|
-
import { ExecutionContext } from "@noego/ioc";
|
|
9
|
+
import { ExecutionContext, LoadAs } from "@noego/ioc";
|
|
9
10
|
import { publishMainTrace } from "../tracing/index.js";
|
|
10
11
|
const logger = getLogger("wood:router");
|
|
11
12
|
function extractTraceConversationId(value) {
|
|
@@ -34,15 +35,42 @@ function controllerAlreadyRegistered(scope, ControllerClass) {
|
|
|
34
35
|
const candidate = scope;
|
|
35
36
|
return typeof candidate.isRegistered === "function" && candidate.isRegistered(ControllerClass);
|
|
36
37
|
}
|
|
38
|
+
async function dispatchReserved(container, reserved, data, event) {
|
|
39
|
+
const scope = container.extend();
|
|
40
|
+
let outcome;
|
|
41
|
+
try {
|
|
42
|
+
outcome = { ok: true, value: await ExecutionContext.run(scope, () => reserved(data, event)) };
|
|
43
|
+
} catch (error) {
|
|
44
|
+
outcome = { ok: false, error };
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await ExecutionContext.run(scope, () => scope.dispose?.());
|
|
48
|
+
} catch (cleanupError) {
|
|
49
|
+
throw Object.assign(new Error("Wood reserved operation cleanup failed"), {
|
|
50
|
+
cause: outcome.ok ? cleanupError : outcome.error,
|
|
51
|
+
errors: [...outcome.ok ? [] : [outcome.error], cleanupError]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (!outcome.ok) throw outcome.error;
|
|
55
|
+
return outcome.value;
|
|
56
|
+
}
|
|
37
57
|
class WoodRouter {
|
|
38
58
|
// IoC Container
|
|
39
59
|
constructor(options) {
|
|
40
60
|
this.operations = /* @__PURE__ */ new Map();
|
|
41
61
|
this.reservedHandlers = /* @__PURE__ */ new Map();
|
|
62
|
+
/**
|
|
63
|
+
* The request lifecycle -- mirrors Dinner's pipeline.
|
|
64
|
+
*
|
|
65
|
+
* channel -> build context -> middleware -> validate -> resolve controller
|
|
66
|
+
* -> create instance -> build args -> call action -> return result
|
|
67
|
+
*/
|
|
68
|
+
this.accepting = true;
|
|
69
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
42
70
|
this.container = options.container;
|
|
43
|
-
this.validator = new SchemaValidator();
|
|
44
|
-
this.middlewareResolver = new MiddlewareResolver(options.middlewareDir);
|
|
45
|
-
this.controllerResolver = new ControllerResolver(options.controllersDir, {
|
|
71
|
+
this.validator = options.validator ?? new SchemaValidator();
|
|
72
|
+
this.middlewareResolver = options.middlewareResolver ?? new MiddlewareResolver(options.middlewareDir);
|
|
73
|
+
this.controllerResolver = options.controllerResolver ?? new ControllerResolver(options.controllersDir, {
|
|
46
74
|
mode: options.mode
|
|
47
75
|
});
|
|
48
76
|
}
|
|
@@ -77,40 +105,131 @@ class WoodRouter {
|
|
|
77
105
|
}
|
|
78
106
|
for (const channel of RESERVED_CHANNELS) {
|
|
79
107
|
ipcMain.handle(channel, async (_event, data) => {
|
|
80
|
-
|
|
81
|
-
if (!handler) {
|
|
82
|
-
throw new Error(`No handler registered for reserved channel "${channel}"`);
|
|
83
|
-
}
|
|
84
|
-
return handler(data, _event);
|
|
108
|
+
return this.dispatch(channel, data, _event);
|
|
85
109
|
});
|
|
86
110
|
}
|
|
87
111
|
logger.debug(
|
|
88
112
|
`Registered ${this.operations.size} operation handlers and ${RESERVED_CHANNELS.length} reserved channels`
|
|
89
113
|
);
|
|
90
114
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!
|
|
100
|
-
|
|
115
|
+
dispatch(channel, data, event) {
|
|
116
|
+
if (!this.accepting) return Promise.reject(new Error("Wood router is closed"));
|
|
117
|
+
const work = this.dispatchOwned(channel, data, event);
|
|
118
|
+
this.pending.set(work, channel);
|
|
119
|
+
void work.then(() => this.pending.delete(work), () => this.pending.delete(work));
|
|
120
|
+
return work;
|
|
121
|
+
}
|
|
122
|
+
async drain(timeoutMs = 5e3) {
|
|
123
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) throw new Error("Wood drain timeoutMs must be finite and non-negative");
|
|
124
|
+
let timer;
|
|
125
|
+
try {
|
|
126
|
+
await Promise.race([
|
|
127
|
+
(async () => {
|
|
128
|
+
while (this.pending.size) await Promise.allSettled([...this.pending.keys()]);
|
|
129
|
+
})(),
|
|
130
|
+
new Promise((_, reject) => {
|
|
131
|
+
timer = setTimeout(() => reject(new Error(
|
|
132
|
+
`Wood drain timed out: pending operations: ${[...this.pending.values()].join(", ")}`
|
|
133
|
+
)), timeoutMs);
|
|
134
|
+
})
|
|
135
|
+
]);
|
|
136
|
+
} finally {
|
|
137
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async dispose(timeoutMs) {
|
|
141
|
+
this.accepting = false;
|
|
142
|
+
await this.drain(timeoutMs);
|
|
143
|
+
}
|
|
144
|
+
async dispatchOwned(channel, data, event) {
|
|
145
|
+
const reserved = this.reservedHandlers.get(channel);
|
|
146
|
+
if (reserved) return dispatchReserved(this.container, reserved, data, event);
|
|
147
|
+
if (RESERVED_CHANNELS.includes(channel)) {
|
|
148
|
+
throw new Error(`No handler registered for reserved channel "${channel}"`);
|
|
101
149
|
}
|
|
150
|
+
const opDef = this.operations.get(channel);
|
|
151
|
+
if (!opDef) throw new Error(`Unknown operation: "${channel}"`);
|
|
102
152
|
const conversationId = extractTraceConversationId(data);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
this.publishDispatchTrace("dispatch.start", channel, opDef, conversationId);
|
|
154
|
+
const ControllerClass = await this.prepareController(opDef);
|
|
155
|
+
const outcome = await this.executeOperation(
|
|
156
|
+
channel,
|
|
157
|
+
data,
|
|
158
|
+
event,
|
|
159
|
+
opDef,
|
|
160
|
+
ControllerClass,
|
|
161
|
+
conversationId
|
|
162
|
+
);
|
|
163
|
+
if (!outcome.ok) {
|
|
164
|
+
this.publishDispatchError(channel, opDef, conversationId, outcome.error);
|
|
165
|
+
throw outcome.error;
|
|
166
|
+
}
|
|
167
|
+
this.publishDispatchTrace("dispatch.success", channel, opDef, conversationId);
|
|
168
|
+
return outcome.value;
|
|
169
|
+
}
|
|
170
|
+
async prepareController(opDef) {
|
|
171
|
+
const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);
|
|
172
|
+
const singletonController = Reflect.getMetadata(/* @__PURE__ */ Symbol.for("ioc:component:options"), ControllerClass)?.scope === LoadAs.Singleton;
|
|
173
|
+
if (singletonController && typeof this.container.isRegistered === "function" && !controllerAlreadyRegistered(this.container, ControllerClass)) {
|
|
174
|
+
this.container.registerClass?.(ControllerClass);
|
|
175
|
+
}
|
|
176
|
+
return ControllerClass;
|
|
177
|
+
}
|
|
178
|
+
async executeOperation(channel, data, event, opDef, ControllerClass, conversationId) {
|
|
179
|
+
const scopedContainer = this.container.extend();
|
|
180
|
+
const state = { instance: void 0, ownsController: false };
|
|
181
|
+
let outcome;
|
|
182
|
+
const cleanup = [];
|
|
183
|
+
try {
|
|
184
|
+
const value = await ExecutionContext.run(
|
|
185
|
+
scopedContainer,
|
|
186
|
+
() => this.invokeController(
|
|
187
|
+
channel,
|
|
188
|
+
data,
|
|
189
|
+
event,
|
|
190
|
+
opDef,
|
|
191
|
+
ControllerClass,
|
|
192
|
+
conversationId,
|
|
193
|
+
scopedContainer,
|
|
194
|
+
state
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
outcome = { ok: true, value };
|
|
198
|
+
} catch (error) {
|
|
199
|
+
outcome = { ok: false, error };
|
|
200
|
+
} finally {
|
|
201
|
+
await this.cleanupOperation(scopedContainer, state, cleanup);
|
|
202
|
+
}
|
|
203
|
+
if (cleanup.length) {
|
|
204
|
+
throw Object.assign(
|
|
205
|
+
new Error(`Wood operation cleanup failed${outcome.ok ? "" : ": " + String(outcome.error)}`),
|
|
206
|
+
{
|
|
207
|
+
cause: outcome.ok ? cleanup[0] : outcome.error,
|
|
208
|
+
errors: [...outcome.ok ? [] : [outcome.error], ...cleanup]
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
return outcome;
|
|
213
|
+
}
|
|
214
|
+
async invokeController(channel, data, event, opDef, ControllerClass, conversationId, scopedContainer, state) {
|
|
215
|
+
const ipcContext = this.buildIpcContext(data, event);
|
|
216
|
+
await this.executeOperationMiddleware(channel, opDef, ipcContext);
|
|
217
|
+
this.validateOperation(channel, opDef, ipcContext, conversationId);
|
|
218
|
+
state.ownsController = !controllerAlreadyRegistered(this.container, ControllerClass);
|
|
219
|
+
if (!controllerAlreadyRegistered(scopedContainer, ControllerClass) && typeof scopedContainer.registerClass === "function") {
|
|
220
|
+
scopedContainer.registerClass(ControllerClass);
|
|
221
|
+
}
|
|
222
|
+
state.instance = await scopedContainer.instance(ControllerClass);
|
|
223
|
+
guardControllerLifecycleOnce(state.instance);
|
|
224
|
+
const args = usesOperationContext(ControllerClass) ? buildOperationContext(channel, ipcContext) : buildControllerArgs(ipcContext, scopedContainer);
|
|
225
|
+
const action = state.instance[opDef.action];
|
|
226
|
+
if (typeof action !== "function") {
|
|
227
|
+
throw new Error(`Controller "${opDef.controller}" has no action "${opDef.action}"`);
|
|
228
|
+
}
|
|
229
|
+
return await action.call(state.instance, args);
|
|
230
|
+
}
|
|
231
|
+
buildIpcContext(data, event) {
|
|
232
|
+
return {
|
|
114
233
|
body: data ?? {},
|
|
115
234
|
params: data ?? {},
|
|
116
235
|
query: {},
|
|
@@ -118,105 +237,67 @@ class WoodRouter {
|
|
|
118
237
|
sender: event?.sender,
|
|
119
238
|
windowId: void 0
|
|
120
239
|
};
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
240
|
+
}
|
|
241
|
+
async executeOperationMiddleware(channel, opDef, ipcContext) {
|
|
242
|
+
if (!opDef.middleware.length) return;
|
|
243
|
+
const mwContext = buildMiddlewareContext(ipcContext, channel);
|
|
244
|
+
const middlewareFns = await Promise.all(
|
|
245
|
+
opDef.middleware.map((spec) => this.middlewareResolver.resolve(spec))
|
|
246
|
+
);
|
|
247
|
+
await executeMiddleware(middlewareFns, mwContext);
|
|
248
|
+
}
|
|
249
|
+
validateOperation(channel, opDef, ipcContext, conversationId) {
|
|
250
|
+
if (!opDef.inputSchema) return;
|
|
251
|
+
const result = this.validator.validate(
|
|
252
|
+
channel,
|
|
253
|
+
opDef.inputSchema,
|
|
254
|
+
ipcContext.body
|
|
255
|
+
);
|
|
256
|
+
if (result.valid) return;
|
|
257
|
+
publishMainTrace("error", {
|
|
258
|
+
source: "wood.router",
|
|
259
|
+
type: "dispatch.validation_error",
|
|
260
|
+
message: "Request validation failed",
|
|
261
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
262
|
+
payload: {
|
|
130
263
|
channel,
|
|
131
|
-
opDef.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!result2.valid) {
|
|
135
|
-
publishMainTrace("error", {
|
|
136
|
-
source: "wood.router",
|
|
137
|
-
type: "dispatch.validation_error",
|
|
138
|
-
message: "Request validation failed",
|
|
139
|
-
...conversationId !== void 0 ? { conversationId } : {},
|
|
140
|
-
payload: {
|
|
141
|
-
channel,
|
|
142
|
-
controller: opDef.controller,
|
|
143
|
-
action: opDef.action,
|
|
144
|
-
errorCount: result2.errors?.length ?? 0
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
throw new WoodValidationError("Request validation failed", result2.errors ?? []);
|
|
264
|
+
controller: opDef.controller,
|
|
265
|
+
action: opDef.action,
|
|
266
|
+
errorCount: result.errors?.length ?? 0
|
|
148
267
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
);
|
|
159
|
-
const args = usesOperationContext(ControllerClass) ? buildOperationContext(channel, ipcContext) : buildControllerArgs(ipcContext, scopedContainer);
|
|
160
|
-
const action = instance[opDef.action];
|
|
161
|
-
let result;
|
|
162
|
-
let actionError;
|
|
163
|
-
try {
|
|
164
|
-
if (typeof action !== "function") {
|
|
165
|
-
throw new Error(
|
|
166
|
-
`Controller "${opDef.controller}" has no action "${opDef.action}"`
|
|
167
|
-
);
|
|
268
|
+
});
|
|
269
|
+
throw new WoodValidationError("Request validation failed", result.errors ?? []);
|
|
270
|
+
}
|
|
271
|
+
async cleanupOperation(scopedContainer, state, cleanup) {
|
|
272
|
+
await ExecutionContext.run(scopedContainer, async () => {
|
|
273
|
+
try {
|
|
274
|
+
if (state.ownsController) await disposeControllerLifecycle(state.instance);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
cleanup.push(error);
|
|
168
277
|
}
|
|
169
|
-
result = await ExecutionContext.run(scopedContainer, () => action.call(instance, args));
|
|
170
|
-
publishMainTrace("debug", {
|
|
171
|
-
source: "wood.router",
|
|
172
|
-
type: "dispatch.success",
|
|
173
|
-
...conversationId !== void 0 ? { conversationId } : {},
|
|
174
|
-
payload: {
|
|
175
|
-
channel,
|
|
176
|
-
controller: opDef.controller,
|
|
177
|
-
action: opDef.action
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
} catch (error) {
|
|
181
|
-
actionError = error;
|
|
182
|
-
publishMainTrace("error", {
|
|
183
|
-
source: "wood.router",
|
|
184
|
-
type: "dispatch.error",
|
|
185
|
-
message: error instanceof Error ? error.message : String(error),
|
|
186
|
-
...conversationId !== void 0 ? { conversationId } : {},
|
|
187
|
-
payload: {
|
|
188
|
-
channel,
|
|
189
|
-
controller: opDef.controller,
|
|
190
|
-
action: opDef.action
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
} finally {
|
|
194
278
|
try {
|
|
195
|
-
await
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
} catch (disposeError) {
|
|
200
|
-
publishMainTrace("error", {
|
|
201
|
-
source: "wood.router",
|
|
202
|
-
type: "dispatch.dispose.error",
|
|
203
|
-
message: disposeError instanceof Error ? disposeError.message : String(disposeError),
|
|
204
|
-
...conversationId !== void 0 ? { conversationId } : {},
|
|
205
|
-
payload: {
|
|
206
|
-
channel,
|
|
207
|
-
controller: opDef.controller,
|
|
208
|
-
action: opDef.action
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
if (!actionError) {
|
|
212
|
-
actionError = disposeError;
|
|
213
|
-
}
|
|
279
|
+
await scopedContainer.dispose?.();
|
|
280
|
+
} catch (error) {
|
|
281
|
+
cleanup.push(error);
|
|
214
282
|
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
publishDispatchTrace(type, channel, opDef, conversationId) {
|
|
286
|
+
publishMainTrace("debug", {
|
|
287
|
+
source: "wood.router",
|
|
288
|
+
type,
|
|
289
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
290
|
+
payload: { channel, controller: opDef.controller, action: opDef.action }
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
publishDispatchError(channel, opDef, conversationId, error) {
|
|
294
|
+
publishMainTrace("error", {
|
|
295
|
+
source: "wood.router",
|
|
296
|
+
type: "dispatch.error",
|
|
297
|
+
message: error instanceof Error ? error.message : String(error),
|
|
298
|
+
...conversationId !== void 0 ? { conversationId } : {},
|
|
299
|
+
payload: { channel, controller: opDef.controller, action: opDef.action }
|
|
300
|
+
});
|
|
220
301
|
}
|
|
221
302
|
/**
|
|
222
303
|
* Pre-register a controller class by name so it is resolved from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.js';\nimport { WoodValidationError } 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, buildOperationContext, usesOperationContext } from '../controller/controller_resolver.js';\nimport { disposeControllerLifecycle } from '../controller/controller_lifecycle.js';\nimport { getLogger } from '@noego/logger';\nimport { ExecutionContext } from '@noego/ioc';\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 = [\n '__load',\n '__navigate',\n '__window',\n '__debug',\n '__contextMenu',\n '__woodConfig',\n '__traceBatch',\n] 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\n/**\n * Whether the scope (or an ancestor) already holds a registration for the\n * controller token. Containers without the query (fakes, older runtimes)\n * report false so the router registers as it always did.\n */\nfunction controllerAlreadyRegistered(scope: unknown, ControllerClass: unknown): boolean {\n const candidate = scope as { isRegistered?: (label: unknown) => boolean };\n return typeof candidate.isRegistered === 'function' && candidate.isRegistered(ControllerClass);\n}\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 publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.validation_error',\n message: 'Request validation failed',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n errorCount: result.errors?.length ?? 0,\n },\n });\n throw new WoodValidationError('Request validation failed', result.errors ?? []);\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). Plain\n // undecorated controller classes are part of Wood's contract, so the\n // class is registered on the scope first — a bare registration defers\n // to @Component options when the class is decorated. A registration\n // already present in the hierarchy (a root-level substitution of the\n // controller token, e.g. a test seam) is left untouched so it keeps\n // deciding how the controller resolves inside this dispatch scope.\n const scopedContainer = this.container.extend();\n if (!controllerAlreadyRegistered(scopedContainer, ControllerClass)\n && typeof scopedContainer.registerClass === 'function') {\n scopedContainer.registerClass(ControllerClass);\n }\n // Framework boundary (D25): the whole operation — controller\n // construction included — executes under the operation scope's context.\n // Constructors may invoke injected collaborators, and any caller context\n // (e.g. an in-process renderer harness bridging into this backend root)\n // must be severed exactly as the production IPC process hop severs it.\n const instance = await ExecutionContext.run(scopedContainer, () =>\n scopedContainer.instance(ControllerClass)\n );\n\n // 6. Build the action argument: native operation context for controllers\n // that opted in (static woodContext = 'operation'), legacy fake req/res\n // args for everything else (migration-only compat).\n const args = usesOperationContext(ControllerClass)\n ? buildOperationContext(channel, ipcContext)\n : buildControllerArgs(ipcContext, scopedContainer);\n\n // 7. Call action, always dispose controller afterward\n const action = instance[opDef.action];\n let result: unknown;\n let actionError: unknown;\n\n try {\n if (typeof action !== 'function') {\n throw new Error(\n `Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`\n );\n }\n\n // Framework boundary: the dispatch executes under ITS operation scope\n // (D25 — boundaries establish context automatically). This also severs\n // any caller context, e.g. an in-process renderer harness bridging a\n // call into this backend root — the production equivalent is the IPC\n // process hop, which carries no context at all.\n result = await ExecutionContext.run(scopedContainer, () => 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 } catch (error) {\n actionError = 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 } finally {\n try {\n await disposeControllerLifecycle(instance);\n // One operation = one IoC scope: dispose the complete scoped graph\n // (services, state, resources), not only the controller instance.\n // The controller-lifecycle hook runs first so legacy dispose/destroy\n // conventions keep their ordering; scope disposal dedupes instances\n // it has already seen. Containers without dispose() (legacy fakes)\n // are tolerated during migration.\n if (typeof (scopedContainer as { dispose?: () => Promise<void> }).dispose === 'function') {\n await (scopedContainer as { dispose: () => Promise<void> }).dispose();\n }\n } catch (disposeError) {\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.dispose.error',\n message: disposeError instanceof Error ? disposeError.message : String(disposeError),\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n },\n });\n\n if (!actionError) {\n actionError = disposeError;\n }\n }\n }\n\n if (actionError) {\n throw actionError;\n }\n\n return result;\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 * Pre-register the executable for a production middleware identity so it\n * resolves from the registry instead of the filesystem — the bundled-mode\n * path for middleware, and the seam test environments use to replace an\n * identity's behavior without touching source topology.\n */\n registerMiddleware(spec: string, middleware: import('../types/index.js').WoodMiddlewareFn): void {\n this.middlewareResolver.register(spec, middleware);\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 * Register a caller-owned lazy loader for a controller: the module is\n * imported through the CALLER's `() => import('…literal specifier…')` only\n * on first dispatch, preserving the caller's module identity for the\n * controller graph (thin production slices in tests).\n */\n registerControllerLoader(name: string, loader: () => Promise<unknown>): void {\n this.controllerResolver.registerLoader(name, loader);\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 /**\n * Eagerly compile every operation's inputSchema so a malformed schema fails\n * at startup (with the offending channel named) instead of throwing an opaque\n * ajv error on the first request to that channel. Call after loadOperations().\n */\n precompileSchemas(): void {\n let compiled = 0;\n for (const [channel, opDef] of this.operations) {\n if (opDef.inputSchema) {\n this.validator.precompile(channel, opDef.inputSchema as Record<string, unknown>);\n compiled += 1;\n }\n }\n logger.info(`Pre-compiled ${compiled} operation input schema(s)`);\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":["result"]}
|
|
1
|
+
{"version":3,"sources":["../../src/router/wood_router.ts"],"sourcesContent":["import 'reflect-metadata';\nimport type { OperationDef, IpcContext, WoodMiddlewareContext } from '../types/index.js';\nimport { WoodValidationError } 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, buildOperationContext, usesOperationContext } from '../controller/controller_resolver.js';\nimport { disposeControllerLifecycle, guardControllerLifecycleOnce } from '../controller/controller_lifecycle.js';\nimport { getLogger } from '@noego/logger';\nimport { ExecutionContext, LoadAs } from '@noego/ioc';\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 = [\n '__load',\n '__navigate',\n '__window',\n '__debug',\n '__contextMenu',\n '__woodConfig',\n '__traceBatch',\n] 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\n/**\n * Whether the scope (or an ancestor) already holds a registration for the\n * controller token. Containers without the query (fakes, older runtimes)\n * report false so the router registers as it always did.\n */\nfunction controllerAlreadyRegistered(scope: unknown, ControllerClass: unknown): boolean {\n const candidate = scope as { isRegistered?: (label: unknown) => boolean };\n return typeof candidate.isRegistered === 'function' && candidate.isRegistered(ControllerClass);\n}\n\ntype ControllerClass = new (...args: any[]) => any;\n\ninterface ControllerExecutionState {\n instance: any;\n ownsController: boolean;\n}\n\ntype OperationOutcome =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: unknown };\n\nasync function dispatchReserved(\n container: any,\n reserved: ReservedChannelHandler,\n data: unknown,\n event?: any,\n): Promise<unknown> {\n const scope = container.extend();\n let outcome: OperationOutcome;\n try {\n outcome = { ok: true, value: await ExecutionContext.run(scope, () => reserved(data, event)) };\n } catch (error) {\n outcome = { ok: false, error };\n }\n\n try {\n await ExecutionContext.run(scope, () => scope.dispose?.());\n } catch (cleanupError) {\n throw Object.assign(new Error('Wood reserved operation cleanup failed'), {\n cause: outcome.ok ? cleanupError : outcome.error,\n errors: [...(outcome.ok ? [] : [outcome.error]), cleanupError],\n });\n }\n if (!outcome.ok) throw outcome.error;\n return outcome.value;\n}\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 validator?: SchemaValidator;\n middlewareResolver?: MiddlewareResolver;\n controllerResolver?: ControllerResolver;\n }) {\n this.container = options.container;\n this.validator = options.validator ?? new SchemaValidator();\n this.middlewareResolver = options.middlewareResolver ?? new MiddlewareResolver(options.middlewareDir);\n this.controllerResolver = options.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 return this.dispatch(channel, 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 private accepting = true;\n private readonly pending = new Map<Promise<unknown>, string>();\n\n dispatch(channel: string, data: unknown, event?: any): Promise<unknown> {\n if (!this.accepting) return Promise.reject(new Error('Wood router is closed'));\n const work = this.dispatchOwned(channel, data, event);\n this.pending.set(work, channel);\n void work.then(() => this.pending.delete(work), () => this.pending.delete(work));\n return work;\n }\n\n async drain(timeoutMs = 5000): Promise<void> {\n if (!Number.isFinite(timeoutMs) || timeoutMs < 0) throw new Error('Wood drain timeoutMs must be finite and non-negative');\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n (async () => { while (this.pending.size) await Promise.allSettled([...this.pending.keys()]); })(),\n new Promise<never>((_, reject) => { timer = setTimeout(() => reject(new Error(\n `Wood drain timed out: pending operations: ${[...this.pending.values()].join(', ')}`,\n )), timeoutMs); }),\n ]);\n } finally { if (timer !== undefined) clearTimeout(timer); }\n }\n\n async dispose(timeoutMs?: number): Promise<void> {\n this.accepting = false;\n await this.drain(timeoutMs);\n }\n\n private async dispatchOwned(channel: string, data: unknown, event?: any): Promise<unknown> {\n const reserved = this.reservedHandlers.get(channel as ReservedChannel);\n if (reserved) return dispatchReserved(this.container, reserved, data, event);\n if ((RESERVED_CHANNELS as readonly string[]).includes(channel)) {\n throw new Error(`No handler registered for reserved channel \"${channel}\"`);\n }\n\n const opDef = this.operations.get(channel);\n if (!opDef) throw new Error(`Unknown operation: \"${channel}\"`);\n\n const conversationId = extractTraceConversationId(data);\n this.publishDispatchTrace('dispatch.start', channel, opDef, conversationId);\n const ControllerClass = await this.prepareController(opDef);\n const outcome = await this.executeOperation(\n channel,\n data,\n event,\n opDef,\n ControllerClass,\n conversationId,\n );\n if (!outcome.ok) {\n this.publishDispatchError(channel, opDef, conversationId, outcome.error);\n throw outcome.error;\n }\n this.publishDispatchTrace('dispatch.success', channel, opDef, conversationId);\n return outcome.value;\n }\n\n private async prepareController(opDef: OperationDef): Promise<ControllerClass> {\n // Register discovered controller definitions on the application root before\n // extending: child scopes snapshot registrations, while singleton ownership\n // is root-wide. Registering first in a request scope breaks the next request.\n const ControllerClass = await this.controllerResolver.resolveClass(opDef.controller);\n const singletonController =\n Reflect.getMetadata(Symbol.for('ioc:component:options'), ControllerClass)?.scope === LoadAs.Singleton;\n if (singletonController && typeof this.container.isRegistered === 'function'\n && !controllerAlreadyRegistered(this.container, ControllerClass)) {\n this.container.registerClass?.(ControllerClass);\n }\n return ControllerClass;\n }\n\n private async executeOperation(\n channel: string,\n data: unknown,\n event: any,\n opDef: OperationDef,\n ControllerClass: ControllerClass,\n conversationId: number | string | undefined,\n ): Promise<OperationOutcome> {\n const scopedContainer = this.container.extend();\n const state: ControllerExecutionState = { instance: undefined, ownsController: false };\n let outcome: OperationOutcome;\n const cleanup: unknown[] = [];\n try {\n const value = await ExecutionContext.run(\n scopedContainer,\n () => this.invokeController(\n channel,\n data,\n event,\n opDef,\n ControllerClass,\n conversationId,\n scopedContainer,\n state,\n ),\n );\n outcome = { ok: true, value };\n } catch (error) {\n outcome = { ok: false, error };\n } finally {\n await this.cleanupOperation(scopedContainer, state, cleanup);\n }\n\n if (cleanup.length) {\n throw Object.assign(\n new Error(`Wood operation cleanup failed${outcome.ok ? '' : ': ' + String(outcome.error)}`),\n {\n cause: outcome.ok ? cleanup[0] : outcome.error,\n errors: [...(outcome.ok ? [] : [outcome.error]), ...cleanup],\n },\n );\n }\n return outcome;\n }\n\n private async invokeController(\n channel: string,\n data: unknown,\n event: any,\n opDef: OperationDef,\n ControllerClass: ControllerClass,\n conversationId: number | string | undefined,\n scopedContainer: any,\n state: ControllerExecutionState,\n ): Promise<unknown> {\n const ipcContext = this.buildIpcContext(data, event);\n await this.executeOperationMiddleware(channel, opDef, ipcContext);\n this.validateOperation(channel, opDef, ipcContext, conversationId);\n\n // Resolve the controller through the inherited, pre-overlay definition.\n state.ownsController = !controllerAlreadyRegistered(this.container, ControllerClass);\n if (!controllerAlreadyRegistered(scopedContainer, ControllerClass)\n && typeof scopedContainer.registerClass === 'function') {\n scopedContainer.registerClass(ControllerClass);\n }\n\n // Framework boundary (D25): the whole operation — controller construction\n // included — executes under the operation scope's context. Constructors may\n // invoke injected collaborators, and any caller context must be severed\n // exactly as the production IPC process hop severs it.\n state.instance = await scopedContainer.instance(ControllerClass);\n guardControllerLifecycleOnce(state.instance);\n const args = usesOperationContext(ControllerClass)\n ? buildOperationContext(channel, ipcContext)\n : buildControllerArgs(ipcContext, scopedContainer);\n const action = state.instance[opDef.action];\n if (typeof action !== 'function') {\n throw new Error(`Controller \"${opDef.controller}\" has no action \"${opDef.action}\"`);\n }\n return await action.call(state.instance, args);\n }\n\n private buildIpcContext(data: unknown, event: any): IpcContext {\n return {\n body: data ?? {},\n params: (data as any) ?? {},\n query: {},\n context: {},\n sender: event?.sender,\n windowId: undefined,\n };\n }\n\n private async executeOperationMiddleware(\n channel: string,\n opDef: OperationDef,\n ipcContext: IpcContext,\n ): Promise<void> {\n if (!opDef.middleware.length) return;\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 private validateOperation(\n channel: string,\n opDef: OperationDef,\n ipcContext: IpcContext,\n conversationId: number | string | undefined,\n ): void {\n if (!opDef.inputSchema) return;\n const result = this.validator.validate(\n channel,\n opDef.inputSchema as Record<string, unknown>,\n ipcContext.body,\n );\n if (result.valid) return;\n publishMainTrace('error', {\n source: 'wood.router',\n type: 'dispatch.validation_error',\n message: 'Request validation failed',\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: {\n channel,\n controller: opDef.controller,\n action: opDef.action,\n errorCount: result.errors?.length ?? 0,\n },\n });\n throw new WoodValidationError('Request validation failed', result.errors ?? []);\n }\n\n private async cleanupOperation(\n scopedContainer: any,\n state: ControllerExecutionState,\n cleanup: unknown[],\n ): Promise<void> {\n // Each cleanup is attempted even if the preceding hook rejects.\n await ExecutionContext.run(scopedContainer, async () => {\n try {\n if (state.ownsController) await disposeControllerLifecycle(state.instance);\n } catch (error) {\n cleanup.push(error);\n }\n try {\n await scopedContainer.dispose?.();\n } catch (error) {\n cleanup.push(error);\n }\n });\n }\n\n private publishDispatchTrace(\n type: 'dispatch.start' | 'dispatch.success',\n channel: string,\n opDef: OperationDef,\n conversationId: number | string | undefined,\n ): void {\n publishMainTrace('debug', {\n source: 'wood.router',\n type,\n ...(conversationId !== undefined ? { conversationId } : {}),\n payload: { channel, controller: opDef.controller, action: opDef.action },\n });\n }\n\n private publishDispatchError(\n channel: string,\n opDef: OperationDef,\n conversationId: number | string | undefined,\n error: unknown,\n ): void {\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: { channel, controller: opDef.controller, action: opDef.action },\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 * Pre-register the executable for a production middleware identity so it\n * resolves from the registry instead of the filesystem — the bundled-mode\n * path for middleware, and the seam test environments use to replace an\n * identity's behavior without touching source topology.\n */\n registerMiddleware(spec: string, middleware: import('../types/index.js').WoodMiddlewareFn): void {\n this.middlewareResolver.register(spec, middleware);\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 * Register a caller-owned lazy loader for a controller: the module is\n * imported through the CALLER's `() => import('…literal specifier…')` only\n * on first dispatch, preserving the caller's module identity for the\n * controller graph (thin production slices in tests).\n */\n registerControllerLoader(name: string, loader: () => Promise<unknown>): void {\n this.controllerResolver.registerLoader(name, loader);\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 /**\n * Eagerly compile every operation's inputSchema so a malformed schema fails\n * at startup (with the offending channel named) instead of throwing an opaque\n * ajv error on the first request to that channel. Call after loadOperations().\n */\n precompileSchemas(): void {\n let compiled = 0;\n for (const [channel, opDef] of this.operations) {\n if (opDef.inputSchema) {\n this.validator.precompile(channel, opDef.inputSchema as Record<string, unknown>);\n compiled += 1;\n }\n }\n logger.info(`Pre-compiled ${compiled} operation input schema(s)`);\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/index.cjs
CHANGED
|
@@ -18,6 +18,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var runtime_exports = {};
|
|
20
20
|
__export(runtime_exports, {
|
|
21
|
+
ControllerResolver: () => import_runtime_module.ControllerResolver,
|
|
22
|
+
MiddlewareResolver: () => import_runtime_module.MiddlewareResolver,
|
|
23
|
+
RendererLogDispatcher: () => import_renderer_log_dispatcher.RendererLogDispatcher,
|
|
24
|
+
SchemaValidator: () => import_runtime_module.SchemaValidator,
|
|
25
|
+
WoodRouter: () => import_runtime_module.WoodRouter,
|
|
21
26
|
clearApplicationRootForTests: () => import_application_root.clearApplicationRootForTests,
|
|
22
27
|
clearContainerRegistryForTests: () => import_get_container.clearContainerRegistryForTests,
|
|
23
28
|
clearRendererLogDispatcherForTests: () => import_renderer_log_dispatcher.clearRendererLogDispatcherForTests,
|
|
@@ -29,6 +34,7 @@ __export(runtime_exports, {
|
|
|
29
34
|
getRendererConfigExtension: () => import_renderer_config_extension.getRendererConfigExtension,
|
|
30
35
|
getRendererLogDispatcher: () => import_renderer_log_dispatcher.getRendererLogDispatcher,
|
|
31
36
|
getRendererTraceBatchReceiver: () => import_renderer_trace_batch_receiver_registry.getRendererTraceBatchReceiver,
|
|
37
|
+
installWoodRuntime: () => import_runtime_module.installWoodRuntime,
|
|
32
38
|
resolveRendererConfigExtension: () => import_renderer_config_extension.resolveRendererConfigExtension,
|
|
33
39
|
runtime: () => import_runtime.runtime,
|
|
34
40
|
setApplicationRoot: () => import_application_root.setApplicationRoot,
|
|
@@ -43,8 +49,14 @@ var import_renderer_log_dispatcher = require("./renderer_log_dispatcher.js");
|
|
|
43
49
|
var import_renderer_trace_batch_receiver_registry = require("./renderer_trace_batch_receiver_registry.js");
|
|
44
50
|
var import_renderer_config_extension = require("./renderer_config_extension.js");
|
|
45
51
|
var import_tracing = require("../tracing/index.js");
|
|
52
|
+
var import_runtime_module = require("./runtime_module.js");
|
|
46
53
|
// Annotate the CommonJS export names for ESM import in node:
|
|
47
54
|
0 && (module.exports = {
|
|
55
|
+
ControllerResolver,
|
|
56
|
+
MiddlewareResolver,
|
|
57
|
+
RendererLogDispatcher,
|
|
58
|
+
SchemaValidator,
|
|
59
|
+
WoodRouter,
|
|
48
60
|
clearApplicationRootForTests,
|
|
49
61
|
clearContainerRegistryForTests,
|
|
50
62
|
clearRendererLogDispatcherForTests,
|
|
@@ -56,6 +68,7 @@ var import_tracing = require("../tracing/index.js");
|
|
|
56
68
|
getRendererConfigExtension,
|
|
57
69
|
getRendererLogDispatcher,
|
|
58
70
|
getRendererTraceBatchReceiver,
|
|
71
|
+
installWoodRuntime,
|
|
59
72
|
resolveRendererConfigExtension,
|
|
60
73
|
runtime,
|
|
61
74
|
setApplicationRoot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["export { createWoodRoot, getContainer, clearContainerRegistryForTests } from './get_container.js';\nexport type { GetContainerOptions, CreateWoodRootOptions } from './get_container.js';\n\nexport {\n getApplicationRoot,\n setApplicationRoot,\n clearApplicationRootForTests,\n} from './application_root.js';\n\nexport { runtime } from './runtime.js';\nexport type { RuntimeOptions, RuntimeResult, RegisterRuntimeRouter } from './runtime.js';\n\nexport {\n getRendererLogDispatcher,\n clearRendererLogDispatcherForTests,\n} from './renderer_log_dispatcher.js';\nexport type {\n RendererLogLevel,\n RendererLogEntry,\n RendererLogCallback,\n RendererLogDispatchResult,\n} from './renderer_log_dispatcher.js';\n\nexport {\n clearRendererTraceBatchReceiverForTests,\n getRendererTraceBatchReceiver,\n setRendererTraceBatchReceiver,\n} from './renderer_trace_batch_receiver_registry.js';\n\nexport {\n getRendererConfigExtension,\n resolveRendererConfigExtension,\n setRendererConfigExtension,\n} from './renderer_config_extension.js';\nexport type { RendererConfigExtension } from './renderer_config_extension.js';\n\nexport { dispatchRendererTracePayload } from '../tracing/index.js';\nexport type { TraceDispatchResult } from '../tracing/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA6E;AAG7E,8BAIO;AAEP,qBAAwB;AAGxB,
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/index.ts"],"sourcesContent":["export { createWoodRoot, getContainer, clearContainerRegistryForTests } from './get_container.js';\nexport type { GetContainerOptions, CreateWoodRootOptions } from './get_container.js';\n\nexport {\n getApplicationRoot,\n setApplicationRoot,\n clearApplicationRootForTests,\n} from './application_root.js';\n\nexport { runtime } from './runtime.js';\nexport type { RuntimeOptions, RuntimeResult, RegisterRuntimeRouter } from './runtime.js';\n\nexport {\n getRendererLogDispatcher,\n RendererLogDispatcher,\n clearRendererLogDispatcherForTests,\n} from './renderer_log_dispatcher.js';\nexport type {\n RendererLogLevel,\n RendererLogEntry,\n RendererLogCallback,\n RendererLogDispatchResult,\n} from './renderer_log_dispatcher.js';\n\nexport {\n clearRendererTraceBatchReceiverForTests,\n getRendererTraceBatchReceiver,\n setRendererTraceBatchReceiver,\n} from './renderer_trace_batch_receiver_registry.js';\n\nexport {\n getRendererConfigExtension,\n resolveRendererConfigExtension,\n setRendererConfigExtension,\n} from './renderer_config_extension.js';\nexport type { RendererConfigExtension } from './renderer_config_extension.js';\n\nexport { dispatchRendererTracePayload } from '../tracing/index.js';\nexport type { TraceDispatchResult } from '../tracing/index.js';\n\nexport { installWoodRuntime, WoodRouter, SchemaValidator, MiddlewareResolver, ControllerResolver } from './runtime_module.js';\nexport type { WoodRuntimeModuleOptions } from './runtime_module.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;AAAA;AAAA;AAAA;AAAA;AAAA,2BAA6E;AAG7E,8BAIO;AAEP,qBAAwB;AAGxB,qCAIO;AAQP,oDAIO;AAEP,uCAIO;AAGP,qBAA6C;AAG7C,4BAAwG;","names":[]}
|
package/dist/runtime/index.d.cts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export { CreateWoodRootOptions, GetContainerOptions, clearContainerRegistryForTests, createWoodRoot, getContainer } from './get_container.cjs';
|
|
2
2
|
export { clearApplicationRootForTests, getApplicationRoot, setApplicationRoot } from './application_root.cjs';
|
|
3
3
|
export { RegisterRuntimeRouter, RuntimeOptions, RuntimeResult, runtime } from './runtime.cjs';
|
|
4
|
-
export { RendererLogCallback, RendererLogDispatchResult, RendererLogEntry, RendererLogLevel, clearRendererLogDispatcherForTests, getRendererLogDispatcher } from './renderer_log_dispatcher.cjs';
|
|
4
|
+
export { RendererLogCallback, RendererLogDispatchResult, RendererLogDispatcher, RendererLogEntry, RendererLogLevel, clearRendererLogDispatcherForTests, getRendererLogDispatcher } from './renderer_log_dispatcher.cjs';
|
|
5
5
|
export { clearRendererTraceBatchReceiverForTests, getRendererTraceBatchReceiver, setRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.cjs';
|
|
6
6
|
export { RendererConfigExtension, getRendererConfigExtension, resolveRendererConfigExtension, setRendererConfigExtension } from './renderer_config_extension.cjs';
|
|
7
7
|
export { T as TraceDispatchResult, o as dispatchRendererTracePayload } from '../trace_hub-Cpo_nVze.cjs';
|
|
8
|
+
export { WoodRuntimeModuleOptions, installWoodRuntime } from './runtime_module.cjs';
|
|
9
|
+
export { ControllerResolver } from '../controller/controller_resolver.cjs';
|
|
10
|
+
export { MiddlewareResolver } from '../middleware/middleware_resolver.cjs';
|
|
11
|
+
export { SchemaValidator } from '../validation/schema_validator.cjs';
|
|
12
|
+
export { WoodRouter } from '../router/wood_router.cjs';
|
|
8
13
|
import '@noego/ioc';
|
|
9
|
-
import '../router/wood_router.cjs';
|
|
10
|
-
import '../types/operations.cjs';
|
|
11
|
-
import '../types/context.cjs';
|
|
12
14
|
import '../tracing/types/wood_trace_batch.types.cjs';
|
|
13
15
|
import '@noego/telemetry/core';
|
|
14
16
|
import './app_env.cjs';
|
|
15
17
|
import 'rxjs';
|
|
18
|
+
import '../types/context.cjs';
|
|
19
|
+
import '../types/operations.cjs';
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export { CreateWoodRootOptions, GetContainerOptions, clearContainerRegistryForTests, createWoodRoot, getContainer } from './get_container.js';
|
|
2
2
|
export { clearApplicationRootForTests, getApplicationRoot, setApplicationRoot } from './application_root.js';
|
|
3
3
|
export { RegisterRuntimeRouter, RuntimeOptions, RuntimeResult, runtime } from './runtime.js';
|
|
4
|
-
export { RendererLogCallback, RendererLogDispatchResult, RendererLogEntry, RendererLogLevel, clearRendererLogDispatcherForTests, getRendererLogDispatcher } from './renderer_log_dispatcher.js';
|
|
4
|
+
export { RendererLogCallback, RendererLogDispatchResult, RendererLogDispatcher, RendererLogEntry, RendererLogLevel, clearRendererLogDispatcherForTests, getRendererLogDispatcher } from './renderer_log_dispatcher.js';
|
|
5
5
|
export { clearRendererTraceBatchReceiverForTests, getRendererTraceBatchReceiver, setRendererTraceBatchReceiver } from './renderer_trace_batch_receiver_registry.js';
|
|
6
6
|
export { RendererConfigExtension, getRendererConfigExtension, resolveRendererConfigExtension, setRendererConfigExtension } from './renderer_config_extension.js';
|
|
7
7
|
export { T as TraceDispatchResult, o as dispatchRendererTracePayload } from '../trace_hub-Cpo_nVze.js';
|
|
8
|
+
export { WoodRuntimeModuleOptions, installWoodRuntime } from './runtime_module.js';
|
|
9
|
+
export { ControllerResolver } from '../controller/controller_resolver.js';
|
|
10
|
+
export { MiddlewareResolver } from '../middleware/middleware_resolver.js';
|
|
11
|
+
export { SchemaValidator } from '../validation/schema_validator.js';
|
|
12
|
+
export { WoodRouter } from '../router/wood_router.js';
|
|
8
13
|
import '@noego/ioc';
|
|
9
|
-
import '../router/wood_router.js';
|
|
10
|
-
import '../types/operations.js';
|
|
11
|
-
import '../types/context.js';
|
|
12
14
|
import '../tracing/types/wood_trace_batch.types.js';
|
|
13
15
|
import '@noego/telemetry/core';
|
|
14
16
|
import './app_env.js';
|
|
15
17
|
import 'rxjs';
|
|
18
|
+
import '../types/context.js';
|
|
19
|
+
import '../types/operations.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { runtime } from "./runtime.js";
|
|
8
8
|
import {
|
|
9
9
|
getRendererLogDispatcher,
|
|
10
|
+
RendererLogDispatcher,
|
|
10
11
|
clearRendererLogDispatcherForTests
|
|
11
12
|
} from "./renderer_log_dispatcher.js";
|
|
12
13
|
import {
|
|
@@ -20,7 +21,13 @@ import {
|
|
|
20
21
|
setRendererConfigExtension
|
|
21
22
|
} from "./renderer_config_extension.js";
|
|
22
23
|
import { dispatchRendererTracePayload } from "../tracing/index.js";
|
|
24
|
+
import { installWoodRuntime, WoodRouter, SchemaValidator, MiddlewareResolver, ControllerResolver } from "./runtime_module.js";
|
|
23
25
|
export {
|
|
26
|
+
ControllerResolver,
|
|
27
|
+
MiddlewareResolver,
|
|
28
|
+
RendererLogDispatcher,
|
|
29
|
+
SchemaValidator,
|
|
30
|
+
WoodRouter,
|
|
24
31
|
clearApplicationRootForTests,
|
|
25
32
|
clearContainerRegistryForTests,
|
|
26
33
|
clearRendererLogDispatcherForTests,
|
|
@@ -32,6 +39,7 @@ export {
|
|
|
32
39
|
getRendererConfigExtension,
|
|
33
40
|
getRendererLogDispatcher,
|
|
34
41
|
getRendererTraceBatchReceiver,
|
|
42
|
+
installWoodRuntime,
|
|
35
43
|
resolveRendererConfigExtension,
|
|
36
44
|
runtime,
|
|
37
45
|
setApplicationRoot,
|