@noego/wood 0.4.6 → 0.4.7
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 +6 -1
- package/dist/client/app_env.cjs +39 -0
- package/dist/client/app_env.cjs.map +1 -0
- package/dist/client/app_env.d.cts +7 -0
- package/dist/client/app_env.d.ts +7 -0
- package/dist/client/app_env.js +14 -0
- package/dist/client/app_env.js.map +1 -0
- package/dist/client/index.cjs +33 -9
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +5 -1
- package/dist/client/index.d.ts +5 -1
- package/dist/client/index.js +32 -9
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/channel_map_generator.cjs +102 -0
- package/dist/codegen/channel_map_generator.cjs.map +1 -0
- package/dist/codegen/channel_map_generator.d.cts +6 -0
- package/dist/codegen/channel_map_generator.d.ts +6 -0
- package/dist/codegen/channel_map_generator.js +78 -0
- package/dist/codegen/channel_map_generator.js.map +1 -0
- package/dist/codegen/controller_registration_generator.cjs +6 -1
- package/dist/codegen/controller_registration_generator.cjs.map +1 -1
- package/dist/codegen/controller_registration_generator.js +6 -1
- package/dist/codegen/controller_registration_generator.js.map +1 -1
- package/dist/codegen/generated_file_notice.cjs +40 -0
- package/dist/codegen/generated_file_notice.cjs.map +1 -0
- package/dist/codegen/generated_file_notice.d.cts +3 -0
- package/dist/codegen/generated_file_notice.d.ts +3 -0
- package/dist/codegen/generated_file_notice.js +16 -0
- package/dist/codegen/generated_file_notice.js.map +1 -0
- package/dist/codegen/index.cjs +3 -0
- package/dist/codegen/index.cjs.map +1 -1
- package/dist/codegen/index.d.cts +1 -0
- package/dist/codegen/index.d.ts +1 -0
- package/dist/codegen/index.js +2 -0
- package/dist/codegen/index.js.map +1 -1
- package/dist/codegen/preload_generator.cjs +97 -1
- package/dist/codegen/preload_generator.cjs.map +1 -1
- package/dist/codegen/preload_generator.js +97 -1
- package/dist/codegen/preload_generator.js.map +1 -1
- package/dist/codegen/renderer_app_generator.cjs +6 -1
- package/dist/codegen/renderer_app_generator.cjs.map +1 -1
- package/dist/codegen/renderer_app_generator.js +6 -1
- package/dist/codegen/renderer_app_generator.js.map +1 -1
- package/dist/codegen/renderer_controller_registration_generator.cjs +6 -1
- package/dist/codegen/renderer_controller_registration_generator.cjs.map +1 -1
- package/dist/codegen/renderer_controller_registration_generator.js +6 -1
- package/dist/codegen/renderer_controller_registration_generator.js.map +1 -1
- package/dist/codegen/renderer_view_manifest_generator.cjs +6 -1
- package/dist/codegen/renderer_view_manifest_generator.cjs.map +1 -1
- package/dist/codegen/renderer_view_manifest_generator.js +6 -1
- package/dist/codegen/renderer_view_manifest_generator.js.map +1 -1
- package/dist/codegen/runtime_generator.cjs +6 -1
- package/dist/codegen/runtime_generator.cjs.map +1 -1
- package/dist/codegen/runtime_generator.js +6 -1
- package/dist/codegen/runtime_generator.js.map +1 -1
- package/dist/codegen/test_mock_generator.cjs +5 -1
- package/dist/codegen/test_mock_generator.cjs.map +1 -1
- package/dist/codegen/test_mock_generator.js +5 -1
- package/dist/codegen/test_mock_generator.js.map +1 -1
- package/dist/codegen/type_generator.cjs +6 -1
- package/dist/codegen/type_generator.cjs.map +1 -1
- package/dist/codegen/type_generator.js +6 -1
- package/dist/codegen/type_generator.js.map +1 -1
- package/dist/index.cjs +19 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/main/index.cjs +133 -55
- package/dist/main/index.cjs.map +1 -1
- package/dist/main/index.d.cts +30 -2
- package/dist/main/index.d.ts +30 -2
- package/dist/main/index.js +134 -55
- package/dist/main/index.js.map +1 -1
- package/dist/main/renderer_trace_drain_coordinator.cjs +127 -0
- package/dist/main/renderer_trace_drain_coordinator.cjs.map +1 -0
- package/dist/main/renderer_trace_drain_coordinator.d.cts +46 -0
- package/dist/main/renderer_trace_drain_coordinator.d.ts +46 -0
- package/dist/main/renderer_trace_drain_coordinator.js +101 -0
- package/dist/main/renderer_trace_drain_coordinator.js.map +1 -0
- package/dist/router/wood_router.cjs +9 -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 +9 -1
- package/dist/router/wood_router.js.map +1 -1
- package/dist/runtime/app_env.cjs +52 -0
- package/dist/runtime/app_env.cjs.map +1 -0
- package/dist/runtime/app_env.d.cts +10 -0
- package/dist/runtime/app_env.d.ts +10 -0
- package/dist/runtime/app_env.js +18 -0
- package/dist/runtime/app_env.js.map +1 -0
- package/dist/runtime/index.cjs +9 -2
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +5 -1
- package/dist/runtime/index.d.ts +5 -1
- package/dist/runtime/index.js +9 -1
- package/dist/runtime/index.js.map +1 -1
- 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.map +1 -1
- package/dist/runtime/renderer_trace_batch_receiver_registry.cjs +50 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.cjs.map +1 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.cts +10 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.d.ts +10 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.js +24 -0
- package/dist/runtime/renderer_trace_batch_receiver_registry.js.map +1 -0
- package/dist/runtime/runtime.cjs +75 -57
- package/dist/runtime/runtime.cjs.map +1 -1
- package/dist/runtime/runtime.d.cts +8 -1
- package/dist/runtime/runtime.d.ts +8 -1
- package/dist/runtime/runtime.js +80 -58
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/testing/browser.cjs +540 -11
- package/dist/testing/browser.cjs.map +1 -1
- package/dist/testing/browser.d.cts +219 -3
- package/dist/testing/browser.d.ts +219 -3
- package/dist/testing/browser.js +540 -11
- package/dist/testing/browser.js.map +1 -1
- package/dist/testing/create_controller_harness.d.cts +1 -1
- package/dist/testing/create_controller_harness.d.ts +1 -1
- package/dist/testing/index.cjs +13 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +7 -2
- package/dist/testing/index.d.ts +7 -2
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/trace-testing/index.d.cts +1 -1
- package/dist/trace-testing/index.d.ts +1 -1
- package/dist/trace-testing/trace_recorder.d.cts +1 -1
- package/dist/trace-testing/trace_recorder.d.ts +1 -1
- package/dist/trace-transport/index.cjs +32 -0
- package/dist/trace-transport/index.cjs.map +1 -0
- package/dist/trace-transport/index.d.cts +6 -0
- package/dist/trace-transport/index.d.ts +6 -0
- package/dist/trace-transport/index.js +7 -0
- package/dist/trace-transport/index.js.map +1 -0
- package/dist/trace_hub-Cob54qRx.d.cts +56 -0
- package/dist/trace_hub-Cob54qRx.d.ts +56 -0
- package/dist/tracing/index.cjs +14 -0
- package/dist/tracing/index.cjs.map +1 -1
- package/dist/tracing/index.d.cts +7 -1
- package/dist/tracing/index.d.ts +7 -1
- package/dist/tracing/index.js +12 -0
- package/dist/tracing/index.js.map +1 -1
- package/dist/tracing/renderer_trace_batch_host.cjs +80 -0
- package/dist/tracing/renderer_trace_batch_host.cjs.map +1 -0
- package/dist/tracing/renderer_trace_batch_host.d.cts +16 -0
- package/dist/tracing/renderer_trace_batch_host.d.ts +16 -0
- package/dist/tracing/renderer_trace_batch_host.js +56 -0
- package/dist/tracing/renderer_trace_batch_host.js.map +1 -0
- package/dist/tracing/renderer_trace_batch_transport.cjs +313 -0
- package/dist/tracing/renderer_trace_batch_transport.cjs.map +1 -0
- package/dist/tracing/renderer_trace_batch_transport.d.cts +53 -0
- package/dist/tracing/renderer_trace_batch_transport.d.ts +53 -0
- package/dist/tracing/renderer_trace_batch_transport.js +292 -0
- package/dist/tracing/renderer_trace_batch_transport.js.map +1 -0
- package/dist/tracing/trace_commit_writer.cjs +159 -0
- package/dist/tracing/trace_commit_writer.cjs.map +1 -0
- package/dist/tracing/trace_commit_writer.d.cts +97 -0
- package/dist/tracing/trace_commit_writer.d.ts +97 -0
- package/dist/tracing/trace_commit_writer.js +135 -0
- package/dist/tracing/trace_commit_writer.js.map +1 -0
- package/dist/tracing/trace_hub.cjs +58 -3
- package/dist/tracing/trace_hub.cjs.map +1 -1
- package/dist/tracing/trace_hub.d.cts +2 -46
- package/dist/tracing/trace_hub.d.ts +2 -46
- package/dist/tracing/trace_hub.js +56 -3
- package/dist/tracing/trace_hub.js.map +1 -1
- package/dist/tracing/trace_provider.cjs +42 -12
- package/dist/tracing/trace_provider.cjs.map +1 -1
- package/dist/tracing/trace_provider.d.cts +15 -1
- package/dist/tracing/trace_provider.d.ts +15 -1
- package/dist/tracing/trace_provider.js +43 -12
- package/dist/tracing/trace_provider.js.map +1 -1
- package/dist/tracing/types/wood_trace_batch.types.cjs +17 -0
- package/dist/tracing/types/wood_trace_batch.types.cjs.map +1 -0
- package/dist/tracing/types/wood_trace_batch.types.d.cts +124 -0
- package/dist/tracing/types/wood_trace_batch.types.d.ts +124 -0
- package/dist/tracing/types/wood_trace_batch.types.js +1 -0
- package/dist/tracing/types/wood_trace_batch.types.js.map +1 -0
- package/dist/tracing/types/wood_trace_sink.types.cjs +17 -0
- package/dist/tracing/types/wood_trace_sink.types.cjs.map +1 -0
- package/dist/tracing/types/wood_trace_sink.types.d.cts +2 -0
- package/dist/tracing/types/wood_trace_sink.types.d.ts +2 -0
- package/dist/tracing/types/wood_trace_sink.types.js +1 -0
- package/dist/tracing/types/wood_trace_sink.types.js.map +1 -0
- package/dist/tracing/wood_trace_batch_contract.cjs +229 -0
- package/dist/tracing/wood_trace_batch_contract.cjs.map +1 -0
- package/dist/tracing/wood_trace_batch_contract.d.cts +23 -0
- package/dist/tracing/wood_trace_batch_contract.d.ts +23 -0
- package/dist/tracing/wood_trace_batch_contract.js +205 -0
- package/dist/tracing/wood_trace_batch_contract.js.map +1 -0
- package/dist/transport/build_transport_bridge.cjs +62 -0
- package/dist/transport/build_transport_bridge.cjs.map +1 -0
- package/dist/transport/build_transport_bridge.d.cts +29 -0
- package/dist/transport/build_transport_bridge.d.ts +29 -0
- package/dist/transport/build_transport_bridge.js +38 -0
- package/dist/transport/build_transport_bridge.js.map +1 -0
- package/dist/transport/in_process_router_transport.cjs +41 -0
- package/dist/transport/in_process_router_transport.cjs.map +1 -0
- package/dist/transport/in_process_router_transport.d.cts +31 -0
- package/dist/transport/in_process_router_transport.d.ts +31 -0
- package/dist/transport/in_process_router_transport.js +17 -0
- package/dist/transport/in_process_router_transport.js.map +1 -0
- package/dist/transport/index.cjs +42 -0
- package/dist/transport/index.cjs.map +1 -0
- package/dist/transport/index.d.cts +8 -0
- package/dist/transport/index.d.ts +8 -0
- package/dist/transport/index.js +19 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/loopback_remote_transport.cjs +270 -0
- package/dist/transport/loopback_remote_transport.cjs.map +1 -0
- package/dist/transport/loopback_remote_transport.d.cts +49 -0
- package/dist/transport/loopback_remote_transport.d.ts +49 -0
- package/dist/transport/loopback_remote_transport.js +237 -0
- package/dist/transport/loopback_remote_transport.js.map +1 -0
- package/dist/transport/loopback_serialization.cjs +116 -0
- package/dist/transport/loopback_serialization.cjs.map +1 -0
- package/dist/transport/loopback_serialization.d.cts +28 -0
- package/dist/transport/loopback_serialization.d.ts +28 -0
- package/dist/transport/loopback_serialization.js +91 -0
- package/dist/transport/loopback_serialization.js.map +1 -0
- package/dist/transport/transport_contract_suite.cjs +110 -0
- package/dist/transport/transport_contract_suite.cjs.map +1 -0
- package/dist/transport/transport_contract_suite.d.cts +23 -0
- package/dist/transport/transport_contract_suite.d.ts +23 -0
- package/dist/transport/transport_contract_suite.js +85 -0
- package/dist/transport/transport_contract_suite.js.map +1 -0
- package/dist/transport/wood_rpc_transport.cjs +17 -0
- package/dist/transport/wood_rpc_transport.cjs.map +1 -0
- package/dist/transport/wood_rpc_transport.d.cts +44 -0
- package/dist/transport/wood_rpc_transport.d.ts +44 -0
- package/dist/transport/wood_rpc_transport.js +1 -0
- package/dist/transport/wood_rpc_transport.js.map +1 -0
- package/docs/browser-testing.md +139 -1
- package/package.json +22 -3
- package/src/components/NavigationShell.browser.test.ts +236 -0
- package/src/components/NavigationShell.svelte +162 -49
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/renderer_view_manifest_generator.ts"],"sourcesContent":["import path from 'path';\nimport type { ViewDef } from '../types/index.cjs';\n\nexport interface RendererViewManifestGeneratorOptions {\n /** Absolute path to renderer component root (e.g. /app/ui) */\n componentDir: string;\n /** Absolute output directory where generated file will be written */\n outDir: string;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toIdentifier(prefix: string, value: string): string {\n const core = value\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return `${prefix}${core || 'Component'}`;\n}\n\nfunction viewKey(view: ViewDef): string {\n return `${view.windowName}.${view.pageName}`;\n}\n\nexport function generateRendererViewManifest(\n views: ViewDef[],\n options: RendererViewManifestGeneratorOptions,\n): string {\n const sortedViews = [...views].sort((a, b) => viewKey(a).localeCompare(viewKey(b)));\n\n const importLines: string[] = [];\n const viewIdentifiers = new Map<string, string>();\n const layoutIdentifiers = new Map<string, string>();\n const usedNames = new Set<string>();\n\n const allocateName = (prefix: string, filePath: string): string => {\n const base = toIdentifier(prefix, filePath);\n let name = base;\n let suffix = 2;\n while (usedNames.has(name)) {\n name = `${base}${suffix}`;\n suffix += 1;\n }\n usedNames.add(name);\n return name;\n };\n\n for (const view of sortedViews) {\n if (!viewIdentifiers.has(view.viewPath)) {\n const identifier = allocateName('View', view.viewPath);\n viewIdentifiers.set(view.viewPath, identifier);\n const abs = path.resolve(options.componentDir, view.viewPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n\n for (const layoutPath of view.layouts) {\n if (layoutIdentifiers.has(layoutPath)) continue;\n const identifier = allocateName('Layout', layoutPath);\n layoutIdentifiers.set(layoutPath, identifier);\n const abs = path.resolve(options.componentDir, layoutPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n }\n\n const manifestEntries = sortedViews.map((view) => {\n const key = viewKey(view);\n const viewIdentifier = viewIdentifiers.get(view.viewPath)!;\n const layoutList = view.layouts.map((layoutPath) => layoutIdentifiers.get(layoutPath)!);\n const controllerValue = view.controller ? `'${view.controller.replace(/'/g, \"\\\\'\")}'` : 'undefined';\n\n return ` '${key}': {\n key: '${key}',\n windowName: '${view.windowName}',\n pageName: '${view.pageName}',\n viewPath: '${view.viewPath}',\n layoutPaths: ${JSON.stringify(view.layouts)},\n controller: ${controllerValue},\n view: ${viewIdentifier},\n layouts: [${layoutList.join(', ')}],\n },`;\n });\n\n return
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/renderer_view_manifest_generator.ts"],"sourcesContent":["import path from 'path';\nimport type { ViewDef } from '../types/index.cjs';\nimport { generatedFileNotice } from './generated_file_notice.cjs';\n\nconst RENDERER_VIEW_SOURCE_INSTRUCTIONS = [\n 'To change routes, page components, or layouts, edit the views YAML configured by',\n 'wood.config.yml renderer.openapi and the matching UI source files.',\n] as const;\n\nexport interface RendererViewManifestGeneratorOptions {\n /** Absolute path to renderer component root (e.g. /app/ui) */\n componentDir: string;\n /** Absolute output directory where generated file will be written */\n outDir: string;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toIdentifier(prefix: string, value: string): string {\n const core = value\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return `${prefix}${core || 'Component'}`;\n}\n\nfunction viewKey(view: ViewDef): string {\n return `${view.windowName}.${view.pageName}`;\n}\n\nexport function generateRendererViewManifest(\n views: ViewDef[],\n options: RendererViewManifestGeneratorOptions,\n): string {\n const sortedViews = [...views].sort((a, b) => viewKey(a).localeCompare(viewKey(b)));\n\n const importLines: string[] = [];\n const viewIdentifiers = new Map<string, string>();\n const layoutIdentifiers = new Map<string, string>();\n const usedNames = new Set<string>();\n\n const allocateName = (prefix: string, filePath: string): string => {\n const base = toIdentifier(prefix, filePath);\n let name = base;\n let suffix = 2;\n while (usedNames.has(name)) {\n name = `${base}${suffix}`;\n suffix += 1;\n }\n usedNames.add(name);\n return name;\n };\n\n for (const view of sortedViews) {\n if (!viewIdentifiers.has(view.viewPath)) {\n const identifier = allocateName('View', view.viewPath);\n viewIdentifiers.set(view.viewPath, identifier);\n const abs = path.resolve(options.componentDir, view.viewPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n\n for (const layoutPath of view.layouts) {\n if (layoutIdentifiers.has(layoutPath)) continue;\n const identifier = allocateName('Layout', layoutPath);\n layoutIdentifiers.set(layoutPath, identifier);\n const abs = path.resolve(options.componentDir, layoutPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n }\n\n const manifestEntries = sortedViews.map((view) => {\n const key = viewKey(view);\n const viewIdentifier = viewIdentifiers.get(view.viewPath)!;\n const layoutList = view.layouts.map((layoutPath) => layoutIdentifiers.get(layoutPath)!);\n const controllerValue = view.controller ? `'${view.controller.replace(/'/g, \"\\\\'\")}'` : 'undefined';\n\n return ` '${key}': {\n key: '${key}',\n windowName: '${view.windowName}',\n pageName: '${view.pageName}',\n viewPath: '${view.viewPath}',\n layoutPaths: ${JSON.stringify(view.layouts)},\n controller: ${controllerValue},\n view: ${viewIdentifier},\n layouts: [${layoutList.join(', ')}],\n },`;\n });\n\n return `${generatedFileNotice(RENDERER_VIEW_SOURCE_INSTRUCTIONS)}\n${importLines.join('\\n')}\n\nexport interface GeneratedViewManifestEntry {\n key: string;\n windowName: string;\n pageName: string;\n viewPath: string;\n layoutPaths: string[];\n controller?: string;\n view: any;\n layouts: any[];\n}\n\nexport const VIEW_MANIFEST: Record<string, GeneratedViewManifestEntry> = {\n${manifestEntries.join('\\n')}\n};\n\nexport function getViewManifestEntry(viewKey: string): GeneratedViewManifestEntry | null {\n return VIEW_MANIFEST[viewKey] ?? null;\n}\n`;\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
+
import { generatedFileNotice } from "./generated_file_notice.js";
|
|
3
|
+
const RENDERER_VIEW_SOURCE_INSTRUCTIONS = [
|
|
4
|
+
"To change routes, page components, or layouts, edit the views YAML configured by",
|
|
5
|
+
"wood.config.yml renderer.openapi and the matching UI source files."
|
|
6
|
+
];
|
|
2
7
|
function computeImportPath(fromDir, toFile) {
|
|
3
8
|
let rel = path.relative(fromDir, toFile);
|
|
4
9
|
if (!rel.startsWith(".")) {
|
|
@@ -63,7 +68,7 @@ function generateRendererViewManifest(views, options) {
|
|
|
63
68
|
layouts: [${layoutList.join(", ")}],
|
|
64
69
|
},`;
|
|
65
70
|
});
|
|
66
|
-
return
|
|
71
|
+
return `${generatedFileNotice(RENDERER_VIEW_SOURCE_INSTRUCTIONS)}
|
|
67
72
|
${importLines.join("\n")}
|
|
68
73
|
|
|
69
74
|
export interface GeneratedViewManifestEntry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/renderer_view_manifest_generator.ts"],"sourcesContent":["import path from 'path';\nimport type { ViewDef } from '../types/index.js';\n\nexport interface RendererViewManifestGeneratorOptions {\n /** Absolute path to renderer component root (e.g. /app/ui) */\n componentDir: string;\n /** Absolute output directory where generated file will be written */\n outDir: string;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toIdentifier(prefix: string, value: string): string {\n const core = value\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return `${prefix}${core || 'Component'}`;\n}\n\nfunction viewKey(view: ViewDef): string {\n return `${view.windowName}.${view.pageName}`;\n}\n\nexport function generateRendererViewManifest(\n views: ViewDef[],\n options: RendererViewManifestGeneratorOptions,\n): string {\n const sortedViews = [...views].sort((a, b) => viewKey(a).localeCompare(viewKey(b)));\n\n const importLines: string[] = [];\n const viewIdentifiers = new Map<string, string>();\n const layoutIdentifiers = new Map<string, string>();\n const usedNames = new Set<string>();\n\n const allocateName = (prefix: string, filePath: string): string => {\n const base = toIdentifier(prefix, filePath);\n let name = base;\n let suffix = 2;\n while (usedNames.has(name)) {\n name = `${base}${suffix}`;\n suffix += 1;\n }\n usedNames.add(name);\n return name;\n };\n\n for (const view of sortedViews) {\n if (!viewIdentifiers.has(view.viewPath)) {\n const identifier = allocateName('View', view.viewPath);\n viewIdentifiers.set(view.viewPath, identifier);\n const abs = path.resolve(options.componentDir, view.viewPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n\n for (const layoutPath of view.layouts) {\n if (layoutIdentifiers.has(layoutPath)) continue;\n const identifier = allocateName('Layout', layoutPath);\n layoutIdentifiers.set(layoutPath, identifier);\n const abs = path.resolve(options.componentDir, layoutPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n }\n\n const manifestEntries = sortedViews.map((view) => {\n const key = viewKey(view);\n const viewIdentifier = viewIdentifiers.get(view.viewPath)!;\n const layoutList = view.layouts.map((layoutPath) => layoutIdentifiers.get(layoutPath)!);\n const controllerValue = view.controller ? `'${view.controller.replace(/'/g, \"\\\\'\")}'` : 'undefined';\n\n return ` '${key}': {\n key: '${key}',\n windowName: '${view.windowName}',\n pageName: '${view.pageName}',\n viewPath: '${view.viewPath}',\n layoutPaths: ${JSON.stringify(view.layouts)},\n controller: ${controllerValue},\n view: ${viewIdentifier},\n layouts: [${layoutList.join(', ')}],\n },`;\n });\n\n return
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/renderer_view_manifest_generator.ts"],"sourcesContent":["import path from 'path';\nimport type { ViewDef } from '../types/index.js';\nimport { generatedFileNotice } from './generated_file_notice.js';\n\nconst RENDERER_VIEW_SOURCE_INSTRUCTIONS = [\n 'To change routes, page components, or layouts, edit the views YAML configured by',\n 'wood.config.yml renderer.openapi and the matching UI source files.',\n] as const;\n\nexport interface RendererViewManifestGeneratorOptions {\n /** Absolute path to renderer component root (e.g. /app/ui) */\n componentDir: string;\n /** Absolute output directory where generated file will be written */\n outDir: string;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toIdentifier(prefix: string, value: string): string {\n const core = value\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return `${prefix}${core || 'Component'}`;\n}\n\nfunction viewKey(view: ViewDef): string {\n return `${view.windowName}.${view.pageName}`;\n}\n\nexport function generateRendererViewManifest(\n views: ViewDef[],\n options: RendererViewManifestGeneratorOptions,\n): string {\n const sortedViews = [...views].sort((a, b) => viewKey(a).localeCompare(viewKey(b)));\n\n const importLines: string[] = [];\n const viewIdentifiers = new Map<string, string>();\n const layoutIdentifiers = new Map<string, string>();\n const usedNames = new Set<string>();\n\n const allocateName = (prefix: string, filePath: string): string => {\n const base = toIdentifier(prefix, filePath);\n let name = base;\n let suffix = 2;\n while (usedNames.has(name)) {\n name = `${base}${suffix}`;\n suffix += 1;\n }\n usedNames.add(name);\n return name;\n };\n\n for (const view of sortedViews) {\n if (!viewIdentifiers.has(view.viewPath)) {\n const identifier = allocateName('View', view.viewPath);\n viewIdentifiers.set(view.viewPath, identifier);\n const abs = path.resolve(options.componentDir, view.viewPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n\n for (const layoutPath of view.layouts) {\n if (layoutIdentifiers.has(layoutPath)) continue;\n const identifier = allocateName('Layout', layoutPath);\n layoutIdentifiers.set(layoutPath, identifier);\n const abs = path.resolve(options.componentDir, layoutPath);\n const importPath = computeImportPath(options.outDir, abs);\n importLines.push(`import ${identifier} from '${importPath}';`);\n }\n }\n\n const manifestEntries = sortedViews.map((view) => {\n const key = viewKey(view);\n const viewIdentifier = viewIdentifiers.get(view.viewPath)!;\n const layoutList = view.layouts.map((layoutPath) => layoutIdentifiers.get(layoutPath)!);\n const controllerValue = view.controller ? `'${view.controller.replace(/'/g, \"\\\\'\")}'` : 'undefined';\n\n return ` '${key}': {\n key: '${key}',\n windowName: '${view.windowName}',\n pageName: '${view.pageName}',\n viewPath: '${view.viewPath}',\n layoutPaths: ${JSON.stringify(view.layouts)},\n controller: ${controllerValue},\n view: ${viewIdentifier},\n layouts: [${layoutList.join(', ')}],\n },`;\n });\n\n return `${generatedFileNotice(RENDERER_VIEW_SOURCE_INSTRUCTIONS)}\n${importLines.join('\\n')}\n\nexport interface GeneratedViewManifestEntry {\n key: string;\n windowName: string;\n pageName: string;\n viewPath: string;\n layoutPaths: string[];\n controller?: string;\n view: any;\n layouts: any[];\n}\n\nexport const VIEW_MANIFEST: Record<string, GeneratedViewManifestEntry> = {\n${manifestEntries.join('\\n')}\n};\n\nexport function getViewManifestEntry(viewKey: string): GeneratedViewManifestEntry | null {\n return VIEW_MANIFEST[viewKey] ?? null;\n}\n`;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -33,6 +33,11 @@ __export(runtime_generator_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(runtime_generator_exports);
|
|
34
34
|
var import_fs = require("fs");
|
|
35
35
|
var import_path = __toESM(require("path"), 1);
|
|
36
|
+
var import_generated_file_notice = require("./generated_file_notice.cjs");
|
|
37
|
+
const RUNTIME_SOURCE_INSTRUCTIONS = [
|
|
38
|
+
"To change IPC routing, validation schemas, or bundled controller registration,",
|
|
39
|
+
"edit the operations YAML configured by wood.config.yml main.openapi and the matching controller files."
|
|
40
|
+
];
|
|
36
41
|
const CANDIDATE_SUFFIXES = [
|
|
37
42
|
".ts",
|
|
38
43
|
".controller.ts",
|
|
@@ -116,7 +121,7 @@ Ensure each controller file exists with one of these suffixes: .ts, .controller.
|
|
|
116
121
|
}
|
|
117
122
|
const operationEntries = Array.from(operations.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);
|
|
118
123
|
const lines = [
|
|
119
|
-
|
|
124
|
+
(0, import_generated_file_notice.generatedFileNotice)(RUNTIME_SOURCE_INSTRUCTIONS),
|
|
120
125
|
"//",
|
|
121
126
|
"// Static imports ensure all controllers are bundled and available at startup.",
|
|
122
127
|
"// Operations are pre-parsed at build time to avoid runtime YAML I/O in Electron bundles.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/runtime_generator.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport path from 'path';\nimport type { OperationDef } from '../types/index.cjs';\n\nconst CANDIDATE_SUFFIXES = [\n '.ts',\n '.controller.ts',\n '.js',\n '.controller.js',\n] as const;\n\nconst INDEX_CANDIDATES = [\n 'index.ts',\n 'index.js',\n] as const;\n\nfunction resolveControllerFile(controllerName: string, controllersDir: string): string | undefined {\n const basePath = path.resolve(controllersDir, controllerName);\n\n for (const suffix of CANDIDATE_SUFFIXES) {\n const candidate = basePath + suffix;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const indexFile of INDEX_CANDIDATES) {\n const candidate = path.resolve(controllersDir, controllerName, indexFile);\n if (existsSync(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n if (rel.endsWith('.ts')) {\n rel = rel.slice(0, -3);\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toControllerClassName(controllerName: string): string {\n const pascal = controllerName\n .split(/[_\\-.]/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return pascal + 'Controller';\n}\n\nfunction extractControllerNames(operations: Map<string, OperationDef>): string[] {\n const names = new Set<string>();\n operations.forEach((op) => names.add(op.controller));\n return Array.from(names).sort();\n}\n\nexport interface RuntimeGeneratorOptions {\n controllersDir: string;\n outDir: string;\n allowUnresolved?: boolean;\n}\n\nfunction serializeOperation(op: OperationDef): string {\n const payload: Record<string, unknown> = {\n channel: op.channel,\n controller: op.controller,\n action: op.action,\n middleware: op.middleware,\n };\n\n if (op.inputSchema !== undefined) {\n payload.inputSchema = op.inputSchema;\n }\n if (op.outputSchema !== undefined) {\n payload.outputSchema = op.outputSchema;\n }\n\n return JSON.stringify(payload);\n}\n\n/**\n * Generate a single runtime registration file that registers controllers and\n * pre-parsed operations with a WoodRouter-compatible target.\n */\nexport function generateRuntime(\n operations: Map<string, OperationDef>,\n options: RuntimeGeneratorOptions,\n): string {\n const controllerNames = extractControllerNames(operations);\n const outDirResolved = path.resolve(options.outDir);\n\n const imports: string[] = [];\n const registrations: string[] = [];\n const unresolved: string[] = [];\n\n for (const name of controllerNames) {\n const filePath = resolveControllerFile(name, options.controllersDir);\n if (!filePath) {\n unresolved.push(name);\n continue;\n }\n\n const importPath = computeImportPath(outDirResolved, filePath);\n const className = toControllerClassName(name);\n\n imports.push(`import ${className} from '${importPath}';`);\n registrations.push(` router.registerController('${name}', ${className});`);\n }\n\n if (unresolved.length > 0 && !options.allowUnresolved) {\n throw new Error(\n `Runtime codegen failed: ${unresolved.length} controller(s) not found on disk:\\n` +\n unresolved.map(name => ` - \"${name}\" (searched in ${options.controllersDir})`).join('\\n') +\n `\\n\\nEnsure each controller file exists with one of these suffixes: .ts, .controller.ts, .js, .controller.js`\n );\n }\n\n const operationEntries = Array.from(operations.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);\n\n const lines: string[] = [\n
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/runtime_generator.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport path from 'path';\nimport type { OperationDef } from '../types/index.cjs';\nimport { generatedFileNotice } from './generated_file_notice.cjs';\n\nconst RUNTIME_SOURCE_INSTRUCTIONS = [\n 'To change IPC routing, validation schemas, or bundled controller registration,',\n 'edit the operations YAML configured by wood.config.yml main.openapi and the matching controller files.',\n] as const;\n\nconst CANDIDATE_SUFFIXES = [\n '.ts',\n '.controller.ts',\n '.js',\n '.controller.js',\n] as const;\n\nconst INDEX_CANDIDATES = [\n 'index.ts',\n 'index.js',\n] as const;\n\nfunction resolveControllerFile(controllerName: string, controllersDir: string): string | undefined {\n const basePath = path.resolve(controllersDir, controllerName);\n\n for (const suffix of CANDIDATE_SUFFIXES) {\n const candidate = basePath + suffix;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const indexFile of INDEX_CANDIDATES) {\n const candidate = path.resolve(controllersDir, controllerName, indexFile);\n if (existsSync(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n if (rel.endsWith('.ts')) {\n rel = rel.slice(0, -3);\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toControllerClassName(controllerName: string): string {\n const pascal = controllerName\n .split(/[_\\-.]/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return pascal + 'Controller';\n}\n\nfunction extractControllerNames(operations: Map<string, OperationDef>): string[] {\n const names = new Set<string>();\n operations.forEach((op) => names.add(op.controller));\n return Array.from(names).sort();\n}\n\nexport interface RuntimeGeneratorOptions {\n controllersDir: string;\n outDir: string;\n allowUnresolved?: boolean;\n}\n\nfunction serializeOperation(op: OperationDef): string {\n const payload: Record<string, unknown> = {\n channel: op.channel,\n controller: op.controller,\n action: op.action,\n middleware: op.middleware,\n };\n\n if (op.inputSchema !== undefined) {\n payload.inputSchema = op.inputSchema;\n }\n if (op.outputSchema !== undefined) {\n payload.outputSchema = op.outputSchema;\n }\n\n return JSON.stringify(payload);\n}\n\n/**\n * Generate a single runtime registration file that registers controllers and\n * pre-parsed operations with a WoodRouter-compatible target.\n */\nexport function generateRuntime(\n operations: Map<string, OperationDef>,\n options: RuntimeGeneratorOptions,\n): string {\n const controllerNames = extractControllerNames(operations);\n const outDirResolved = path.resolve(options.outDir);\n\n const imports: string[] = [];\n const registrations: string[] = [];\n const unresolved: string[] = [];\n\n for (const name of controllerNames) {\n const filePath = resolveControllerFile(name, options.controllersDir);\n if (!filePath) {\n unresolved.push(name);\n continue;\n }\n\n const importPath = computeImportPath(outDirResolved, filePath);\n const className = toControllerClassName(name);\n\n imports.push(`import ${className} from '${importPath}';`);\n registrations.push(` router.registerController('${name}', ${className});`);\n }\n\n if (unresolved.length > 0 && !options.allowUnresolved) {\n throw new Error(\n `Runtime codegen failed: ${unresolved.length} controller(s) not found on disk:\\n` +\n unresolved.map(name => ` - \"${name}\" (searched in ${options.controllersDir})`).join('\\n') +\n `\\n\\nEnsure each controller file exists with one of these suffixes: .ts, .controller.ts, .js, .controller.js`\n );\n }\n\n const operationEntries = Array.from(operations.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);\n\n const lines: string[] = [\n generatedFileNotice(RUNTIME_SOURCE_INSTRUCTIONS),\n '//',\n '// Static imports ensure all controllers are bundled and available at startup.',\n '// Operations are pre-parsed at build time to avoid runtime YAML I/O in Electron bundles.',\n '',\n ];\n\n lines.push(...imports);\n\n if (imports.length > 0) {\n lines.push('');\n }\n\n if (unresolved.length > 0) {\n lines.push(\n '// WARNING: The following controllers could not be resolved on disk:',\n ...unresolved.map((name) => `// - ${name}`),\n '',\n );\n }\n\n lines.push(\n 'const OPERATIONS = new Map<string, any>([',\n ...operationEntries,\n ']);',\n '',\n 'export function registerRuntime(router: {',\n ' registerController(name: string, cls: any): void;',\n ' loadOperations(operations: Map<string, any>): void;',\n '}): void {',\n ...registrations,\n ' router.loadOperations(OPERATIONS);',\n '}',\n '',\n );\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { generatedFileNotice } from "./generated_file_notice.js";
|
|
4
|
+
const RUNTIME_SOURCE_INSTRUCTIONS = [
|
|
5
|
+
"To change IPC routing, validation schemas, or bundled controller registration,",
|
|
6
|
+
"edit the operations YAML configured by wood.config.yml main.openapi and the matching controller files."
|
|
7
|
+
];
|
|
3
8
|
const CANDIDATE_SUFFIXES = [
|
|
4
9
|
".ts",
|
|
5
10
|
".controller.ts",
|
|
@@ -83,7 +88,7 @@ Ensure each controller file exists with one of these suffixes: .ts, .controller.
|
|
|
83
88
|
}
|
|
84
89
|
const operationEntries = Array.from(operations.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);
|
|
85
90
|
const lines = [
|
|
86
|
-
|
|
91
|
+
generatedFileNotice(RUNTIME_SOURCE_INSTRUCTIONS),
|
|
87
92
|
"//",
|
|
88
93
|
"// Static imports ensure all controllers are bundled and available at startup.",
|
|
89
94
|
"// Operations are pre-parsed at build time to avoid runtime YAML I/O in Electron bundles.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/runtime_generator.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport path from 'path';\nimport type { OperationDef } from '../types/index.js';\n\nconst CANDIDATE_SUFFIXES = [\n '.ts',\n '.controller.ts',\n '.js',\n '.controller.js',\n] as const;\n\nconst INDEX_CANDIDATES = [\n 'index.ts',\n 'index.js',\n] as const;\n\nfunction resolveControllerFile(controllerName: string, controllersDir: string): string | undefined {\n const basePath = path.resolve(controllersDir, controllerName);\n\n for (const suffix of CANDIDATE_SUFFIXES) {\n const candidate = basePath + suffix;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const indexFile of INDEX_CANDIDATES) {\n const candidate = path.resolve(controllersDir, controllerName, indexFile);\n if (existsSync(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n if (rel.endsWith('.ts')) {\n rel = rel.slice(0, -3);\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toControllerClassName(controllerName: string): string {\n const pascal = controllerName\n .split(/[_\\-.]/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return pascal + 'Controller';\n}\n\nfunction extractControllerNames(operations: Map<string, OperationDef>): string[] {\n const names = new Set<string>();\n operations.forEach((op) => names.add(op.controller));\n return Array.from(names).sort();\n}\n\nexport interface RuntimeGeneratorOptions {\n controllersDir: string;\n outDir: string;\n allowUnresolved?: boolean;\n}\n\nfunction serializeOperation(op: OperationDef): string {\n const payload: Record<string, unknown> = {\n channel: op.channel,\n controller: op.controller,\n action: op.action,\n middleware: op.middleware,\n };\n\n if (op.inputSchema !== undefined) {\n payload.inputSchema = op.inputSchema;\n }\n if (op.outputSchema !== undefined) {\n payload.outputSchema = op.outputSchema;\n }\n\n return JSON.stringify(payload);\n}\n\n/**\n * Generate a single runtime registration file that registers controllers and\n * pre-parsed operations with a WoodRouter-compatible target.\n */\nexport function generateRuntime(\n operations: Map<string, OperationDef>,\n options: RuntimeGeneratorOptions,\n): string {\n const controllerNames = extractControllerNames(operations);\n const outDirResolved = path.resolve(options.outDir);\n\n const imports: string[] = [];\n const registrations: string[] = [];\n const unresolved: string[] = [];\n\n for (const name of controllerNames) {\n const filePath = resolveControllerFile(name, options.controllersDir);\n if (!filePath) {\n unresolved.push(name);\n continue;\n }\n\n const importPath = computeImportPath(outDirResolved, filePath);\n const className = toControllerClassName(name);\n\n imports.push(`import ${className} from '${importPath}';`);\n registrations.push(` router.registerController('${name}', ${className});`);\n }\n\n if (unresolved.length > 0 && !options.allowUnresolved) {\n throw new Error(\n `Runtime codegen failed: ${unresolved.length} controller(s) not found on disk:\\n` +\n unresolved.map(name => ` - \"${name}\" (searched in ${options.controllersDir})`).join('\\n') +\n `\\n\\nEnsure each controller file exists with one of these suffixes: .ts, .controller.ts, .js, .controller.js`\n );\n }\n\n const operationEntries = Array.from(operations.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);\n\n const lines: string[] = [\n
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/runtime_generator.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport path from 'path';\nimport type { OperationDef } from '../types/index.js';\nimport { generatedFileNotice } from './generated_file_notice.js';\n\nconst RUNTIME_SOURCE_INSTRUCTIONS = [\n 'To change IPC routing, validation schemas, or bundled controller registration,',\n 'edit the operations YAML configured by wood.config.yml main.openapi and the matching controller files.',\n] as const;\n\nconst CANDIDATE_SUFFIXES = [\n '.ts',\n '.controller.ts',\n '.js',\n '.controller.js',\n] as const;\n\nconst INDEX_CANDIDATES = [\n 'index.ts',\n 'index.js',\n] as const;\n\nfunction resolveControllerFile(controllerName: string, controllersDir: string): string | undefined {\n const basePath = path.resolve(controllersDir, controllerName);\n\n for (const suffix of CANDIDATE_SUFFIXES) {\n const candidate = basePath + suffix;\n if (existsSync(candidate)) return candidate;\n }\n\n for (const indexFile of INDEX_CANDIDATES) {\n const candidate = path.resolve(controllersDir, controllerName, indexFile);\n if (existsSync(candidate)) return candidate;\n }\n\n return undefined;\n}\n\nfunction computeImportPath(fromDir: string, toFile: string): string {\n let rel = path.relative(fromDir, toFile);\n\n if (!rel.startsWith('.')) {\n rel = './' + rel;\n }\n\n if (rel.endsWith('.ts')) {\n rel = rel.slice(0, -3);\n }\n\n return rel.replace(/\\\\/g, '/');\n}\n\nfunction toControllerClassName(controllerName: string): string {\n const pascal = controllerName\n .split(/[_\\-.]/)\n .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))\n .join('');\n\n return pascal + 'Controller';\n}\n\nfunction extractControllerNames(operations: Map<string, OperationDef>): string[] {\n const names = new Set<string>();\n operations.forEach((op) => names.add(op.controller));\n return Array.from(names).sort();\n}\n\nexport interface RuntimeGeneratorOptions {\n controllersDir: string;\n outDir: string;\n allowUnresolved?: boolean;\n}\n\nfunction serializeOperation(op: OperationDef): string {\n const payload: Record<string, unknown> = {\n channel: op.channel,\n controller: op.controller,\n action: op.action,\n middleware: op.middleware,\n };\n\n if (op.inputSchema !== undefined) {\n payload.inputSchema = op.inputSchema;\n }\n if (op.outputSchema !== undefined) {\n payload.outputSchema = op.outputSchema;\n }\n\n return JSON.stringify(payload);\n}\n\n/**\n * Generate a single runtime registration file that registers controllers and\n * pre-parsed operations with a WoodRouter-compatible target.\n */\nexport function generateRuntime(\n operations: Map<string, OperationDef>,\n options: RuntimeGeneratorOptions,\n): string {\n const controllerNames = extractControllerNames(operations);\n const outDirResolved = path.resolve(options.outDir);\n\n const imports: string[] = [];\n const registrations: string[] = [];\n const unresolved: string[] = [];\n\n for (const name of controllerNames) {\n const filePath = resolveControllerFile(name, options.controllersDir);\n if (!filePath) {\n unresolved.push(name);\n continue;\n }\n\n const importPath = computeImportPath(outDirResolved, filePath);\n const className = toControllerClassName(name);\n\n imports.push(`import ${className} from '${importPath}';`);\n registrations.push(` router.registerController('${name}', ${className});`);\n }\n\n if (unresolved.length > 0 && !options.allowUnresolved) {\n throw new Error(\n `Runtime codegen failed: ${unresolved.length} controller(s) not found on disk:\\n` +\n unresolved.map(name => ` - \"${name}\" (searched in ${options.controllersDir})`).join('\\n') +\n `\\n\\nEnsure each controller file exists with one of these suffixes: .ts, .controller.ts, .js, .controller.js`\n );\n }\n\n const operationEntries = Array.from(operations.entries())\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([channel, op]) => ` ['${channel}', ${serializeOperation(op)}],`);\n\n const lines: string[] = [\n generatedFileNotice(RUNTIME_SOURCE_INSTRUCTIONS),\n '//',\n '// Static imports ensure all controllers are bundled and available at startup.',\n '// Operations are pre-parsed at build time to avoid runtime YAML I/O in Electron bundles.',\n '',\n ];\n\n lines.push(...imports);\n\n if (imports.length > 0) {\n lines.push('');\n }\n\n if (unresolved.length > 0) {\n lines.push(\n '// WARNING: The following controllers could not be resolved on disk:',\n ...unresolved.map((name) => `// - ${name}`),\n '',\n );\n }\n\n lines.push(\n 'const OPERATIONS = new Map<string, any>([',\n ...operationEntries,\n ']);',\n '',\n 'export function registerRuntime(router: {',\n ' registerController(name: string, cls: any): void;',\n ' loadOperations(operations: Map<string, any>): void;',\n '}): void {',\n ...registrations,\n ' router.loadOperations(OPERATIONS);',\n '}',\n '',\n );\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
|
|
@@ -21,6 +21,10 @@ __export(test_mock_generator_exports, {
|
|
|
21
21
|
generateTestMock: () => generateTestMock
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(test_mock_generator_exports);
|
|
24
|
+
var import_generated_file_notice = require("./generated_file_notice.cjs");
|
|
25
|
+
const TEST_MOCK_SOURCE_INSTRUCTIONS = [
|
|
26
|
+
"To change mocked IPC shape, edit the operations YAML configured by wood.config.yml main.openapi."
|
|
27
|
+
];
|
|
24
28
|
function buildNestedMockTree(operations) {
|
|
25
29
|
const tree = {};
|
|
26
30
|
for (const [channel, op] of operations) {
|
|
@@ -51,7 +55,7 @@ function generateMockTree(node, indent = " ") {
|
|
|
51
55
|
function generateTestMock(operations) {
|
|
52
56
|
const tree = buildNestedMockTree(operations);
|
|
53
57
|
const mockCode = generateMockTree(tree);
|
|
54
|
-
return
|
|
58
|
+
return `${(0, import_generated_file_notice.generatedFileNotice)(TEST_MOCK_SOURCE_INSTRUCTIONS)}
|
|
55
59
|
// Regenerated by noego dev and noego build when YAML changes
|
|
56
60
|
import { vi } from 'vitest';
|
|
57
61
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/test_mock_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.cjs';\n\nfunction buildNestedMockTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateMockTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n lines.push(`${indent}${key}: vi.fn().mockResolvedValue({}),`);\n } else {\n lines.push(`${indent}${key}: {`);\n lines.push(generateMockTree(entry, indent + ' '));\n lines.push(`${indent}},`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function generateTestMock(operations: Map<string, OperationDef>): string {\n const tree = buildNestedMockTree(operations);\n const mockCode = generateMockTree(tree);\n\n return
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/test_mock_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.cjs';\nimport { generatedFileNotice } from './generated_file_notice.cjs';\n\nconst TEST_MOCK_SOURCE_INSTRUCTIONS = [\n 'To change mocked IPC shape, edit the operations YAML configured by wood.config.yml main.openapi.',\n] as const;\n\nfunction buildNestedMockTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateMockTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n lines.push(`${indent}${key}: vi.fn().mockResolvedValue({}),`);\n } else {\n lines.push(`${indent}${key}: {`);\n lines.push(generateMockTree(entry, indent + ' '));\n lines.push(`${indent}},`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function generateTestMock(operations: Map<string, OperationDef>): string {\n const tree = buildNestedMockTree(operations);\n const mockCode = generateMockTree(tree);\n\n return `${generatedFileNotice(TEST_MOCK_SOURCE_INSTRUCTIONS)}\n// Regenerated by noego dev and noego build when YAML changes\nimport { vi } from 'vitest';\n\nconst __WOOD_INTERNAL_BRIDGE_KEY = '__NOEGO_WOOD_BRIDGE__';\n\nconst mockWood = {\n${mockCode}\n __load: vi.fn(),\n __navigate: vi.fn(),\n __window: {\n open: vi.fn(),\n close: vi.fn(),\n focus: vi.fn(),\n minimize: vi.fn(),\n maximize: vi.fn(),\n },\n __debug: {\n current: vi.fn().mockResolvedValue({\n ok: true,\n enabled: false,\n mode: 'production',\n windows: [],\n }),\n },\n __contextMenu: {\n show: vi.fn(),\n },\n on: vi.fn(() => vi.fn()),\n __log: vi.fn().mockResolvedValue({\n ok: true,\n forwarded: false,\n configured: false,\n reason: 'unconfigured',\n }),\n};\n\nObject.defineProperty(window, __WOOD_INTERNAL_BRIDGE_KEY, { value: mockWood, writable: true });\n`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mCAAoC;AAEpC,MAAM,gCAAgC;AAAA,EACpC;AACF;AAEA,SAAS,oBAAoB,YAAgE;AAC3F,QAAM,OAAgC,CAAC;AACvC,aAAW,CAAC,SAAS,EAAE,KAAK,YAAY;AACtC,UAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,QAAI,UAAmC;AACvC,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,UAAI,CAAC,QAAQ,MAAM,CAAC,CAAC,EAAG,SAAQ,MAAM,CAAC,CAAC,IAAI,CAAC;AAC7C,gBAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC5B;AACA,YAAQ,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,EAAE,aAAa,GAAG;AAAA,EACvD;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAA+B,SAAiB,MAAc;AACtF,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,QAAQ;AACd,QAAI,MAAM,aAAa;AACrB,YAAM,KAAK,GAAG,MAAM,GAAG,GAAG,kCAAkC;AAAA,IAC9D,OAAO;AACL,YAAM,KAAK,GAAG,MAAM,GAAG,GAAG,KAAK;AAC/B,YAAM,KAAK,iBAAiB,OAAO,SAAS,IAAI,CAAC;AACjD,YAAM,KAAK,GAAG,MAAM,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,iBAAiB,YAA+C;AAC9E,QAAM,OAAO,oBAAoB,UAAU;AAC3C,QAAM,WAAW,iBAAiB,IAAI;AAEtC,SAAO,OAAG,kDAAoB,6BAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5D,QAAQ;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;AAAA;AAAA;AAAA;AAAA;AAgCV;","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { generatedFileNotice } from "./generated_file_notice.js";
|
|
2
|
+
const TEST_MOCK_SOURCE_INSTRUCTIONS = [
|
|
3
|
+
"To change mocked IPC shape, edit the operations YAML configured by wood.config.yml main.openapi."
|
|
4
|
+
];
|
|
1
5
|
function buildNestedMockTree(operations) {
|
|
2
6
|
const tree = {};
|
|
3
7
|
for (const [channel, op] of operations) {
|
|
@@ -28,7 +32,7 @@ function generateMockTree(node, indent = " ") {
|
|
|
28
32
|
function generateTestMock(operations) {
|
|
29
33
|
const tree = buildNestedMockTree(operations);
|
|
30
34
|
const mockCode = generateMockTree(tree);
|
|
31
|
-
return
|
|
35
|
+
return `${generatedFileNotice(TEST_MOCK_SOURCE_INSTRUCTIONS)}
|
|
32
36
|
// Regenerated by noego dev and noego build when YAML changes
|
|
33
37
|
import { vi } from 'vitest';
|
|
34
38
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/test_mock_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.js';\n\nfunction buildNestedMockTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateMockTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n lines.push(`${indent}${key}: vi.fn().mockResolvedValue({}),`);\n } else {\n lines.push(`${indent}${key}: {`);\n lines.push(generateMockTree(entry, indent + ' '));\n lines.push(`${indent}},`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function generateTestMock(operations: Map<string, OperationDef>): string {\n const tree = buildNestedMockTree(operations);\n const mockCode = generateMockTree(tree);\n\n return
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/test_mock_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.js';\nimport { generatedFileNotice } from './generated_file_notice.js';\n\nconst TEST_MOCK_SOURCE_INSTRUCTIONS = [\n 'To change mocked IPC shape, edit the operations YAML configured by wood.config.yml main.openapi.',\n] as const;\n\nfunction buildNestedMockTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateMockTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n lines.push(`${indent}${key}: vi.fn().mockResolvedValue({}),`);\n } else {\n lines.push(`${indent}${key}: {`);\n lines.push(generateMockTree(entry, indent + ' '));\n lines.push(`${indent}},`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function generateTestMock(operations: Map<string, OperationDef>): string {\n const tree = buildNestedMockTree(operations);\n const mockCode = generateMockTree(tree);\n\n return `${generatedFileNotice(TEST_MOCK_SOURCE_INSTRUCTIONS)}\n// Regenerated by noego dev and noego build when YAML changes\nimport { vi } from 'vitest';\n\nconst __WOOD_INTERNAL_BRIDGE_KEY = '__NOEGO_WOOD_BRIDGE__';\n\nconst mockWood = {\n${mockCode}\n __load: vi.fn(),\n __navigate: vi.fn(),\n __window: {\n open: vi.fn(),\n close: vi.fn(),\n focus: vi.fn(),\n minimize: vi.fn(),\n maximize: vi.fn(),\n },\n __debug: {\n current: vi.fn().mockResolvedValue({\n ok: true,\n enabled: false,\n mode: 'production',\n windows: [],\n }),\n },\n __contextMenu: {\n show: vi.fn(),\n },\n on: vi.fn(() => vi.fn()),\n __log: vi.fn().mockResolvedValue({\n ok: true,\n forwarded: false,\n configured: false,\n reason: 'unconfigured',\n }),\n};\n\nObject.defineProperty(window, __WOOD_INTERNAL_BRIDGE_KEY, { value: mockWood, writable: true });\n`;\n}\n"],"mappings":"AACA,SAAS,2BAA2B;AAEpC,MAAM,gCAAgC;AAAA,EACpC;AACF;AAEA,SAAS,oBAAoB,YAAgE;AAC3F,QAAM,OAAgC,CAAC;AACvC,aAAW,CAAC,SAAS,EAAE,KAAK,YAAY;AACtC,UAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,QAAI,UAAmC;AACvC,aAAS,IAAI,GAAG,IAAI,MAAM,SAAS,GAAG,KAAK;AACzC,UAAI,CAAC,QAAQ,MAAM,CAAC,CAAC,EAAG,SAAQ,MAAM,CAAC,CAAC,IAAI,CAAC;AAC7C,gBAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC5B;AACA,YAAQ,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,EAAE,aAAa,GAAG;AAAA,EACvD;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAA+B,SAAiB,MAAc;AACtF,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,QAAQ;AACd,QAAI,MAAM,aAAa;AACrB,YAAM,KAAK,GAAG,MAAM,GAAG,GAAG,kCAAkC;AAAA,IAC9D,OAAO;AACL,YAAM,KAAK,GAAG,MAAM,GAAG,GAAG,KAAK;AAC/B,YAAM,KAAK,iBAAiB,OAAO,SAAS,IAAI,CAAC;AACjD,YAAM,KAAK,GAAG,MAAM,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,iBAAiB,YAA+C;AAC9E,QAAM,OAAO,oBAAoB,UAAU;AAC3C,QAAM,WAAW,iBAAiB,IAAI;AAEtC,SAAO,GAAG,oBAAoB,6BAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5D,QAAQ;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;AAAA;AAAA;AAAA;AAAA;AAgCV;","names":[]}
|
|
@@ -21,6 +21,11 @@ __export(type_generator_exports, {
|
|
|
21
21
|
generateTypes: () => generateTypes
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(type_generator_exports);
|
|
24
|
+
var import_generated_file_notice = require("./generated_file_notice.cjs");
|
|
25
|
+
const TYPE_SOURCE_INSTRUCTIONS = [
|
|
26
|
+
"To change IPC channels, input schemas, controller/action names, or renderer bridge types,",
|
|
27
|
+
"edit the operations YAML configured by wood.config.yml main.openapi and the matching controller methods."
|
|
28
|
+
];
|
|
24
29
|
function formatPropertyKey(key) {
|
|
25
30
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
26
31
|
return key;
|
|
@@ -144,7 +149,7 @@ function generateTypes(operations) {
|
|
|
144
149
|
const tree = buildNestedTypeTree(operations);
|
|
145
150
|
const typesCode = generateTypeTree(tree);
|
|
146
151
|
const rpcTypeCode = generateRpcTypeTree(operations);
|
|
147
|
-
return
|
|
152
|
+
return `${(0, import_generated_file_notice.generatedFileNotice)(TYPE_SOURCE_INSTRUCTIONS)}
|
|
148
153
|
export interface WoodRpcManifestEntry {
|
|
149
154
|
channel: string;
|
|
150
155
|
controller: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/type_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.cjs';\n\nfunction formatPropertyKey(key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return key;\n }\n\n return JSON.stringify(key);\n}\n\nfunction operationHasInput(op: OperationDef): boolean {\n return Boolean(\n op.inputSchema &&\n (op.inputSchema as Record<string, unknown>).type === 'object' &&\n Object.keys((op.inputSchema as Record<string, Record<string, unknown>>).properties ?? {}).length > 0,\n );\n}\n\nfunction jsonSchemaToTS(schema: Record<string, unknown> | undefined, indent: string = ''): string {\n if (!schema) return 'unknown';\n\n const type = schema.type as string | undefined;\n\n if (type === 'string') {\n if (schema.enum) {\n return (schema.enum as string[]).map((v) => `'${v}'`).join(' | ');\n }\n return 'string';\n }\n if (type === 'number' || type === 'integer') return 'number';\n if (type === 'boolean') return 'boolean';\n if (type === 'array') {\n const itemType = jsonSchemaToTS(schema.items as Record<string, unknown>, indent);\n return `Array<${itemType}>`;\n }\n if (type === 'object') {\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[]) ?? []);\n const entries = Object.entries(props);\n if (entries.length === 0) return 'Record<string, unknown>';\n\n const lines = entries.map(([key, val]) => {\n const optional = required.has(key) ? '' : '?';\n const valType = jsonSchemaToTS(val, indent + ' ');\n return `${indent} ${formatPropertyKey(key)}${optional}: ${valType};`;\n });\n return `{\\n${lines.join('\\n')}\\n${indent}}`;\n }\n\n return 'unknown';\n}\n\nfunction buildNestedTypeTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateTypeTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n const op = entry.__operation as OperationDef;\n const inputType = jsonSchemaToTS(op.inputSchema as Record<string, unknown>, indent + ' ');\n const outputType = jsonSchemaToTS(op.outputSchema as Record<string, unknown>, indent + ' ');\n const hasInput = operationHasInput(op);\n\n if (hasInput) {\n lines.push(`${indent}${formatPropertyKey(key)}(data: ${inputType}): Promise<${outputType}>;`);\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}(): Promise<${outputType}>;`);\n }\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}: {`);\n lines.push(generateTypeTree(entry, indent + ' '));\n lines.push(`${indent}};`);\n }\n }\n return lines.join('\\n');\n}\n\ntype RpcActionTypeEntry = {\n channel: string;\n inputType: string;\n outputType: string;\n hasInput: boolean;\n};\n\nfunction buildRpcControllerTree(\n operations: Map<string, OperationDef>,\n): Record<string, Record<string, RpcActionTypeEntry>> {\n const tree: Record<string, Record<string, RpcActionTypeEntry>> = {};\n\n for (const operation of operations.values()) {\n const controller = operation.controller;\n const action = operation.action;\n\n if (!tree[controller]) {\n tree[controller] = {};\n }\n\n if (tree[controller][action]) {\n throw new Error(\n `Type codegen failed: duplicate RPC action \"${controller}.${action}\" found in channel \"${operation.channel}\".`,\n );\n }\n\n tree[controller][action] = {\n channel: operation.channel,\n inputType: jsonSchemaToTS(operation.inputSchema as Record<string, unknown>, ' '),\n outputType: jsonSchemaToTS(operation.outputSchema as Record<string, unknown>, ' '),\n hasInput: operationHasInput(operation),\n };\n }\n\n return tree;\n}\n\nfunction generateRpcTypeTree(operations: Map<string, OperationDef>): string {\n const controllerTree = buildRpcControllerTree(operations);\n const controllerNames = Object.keys(controllerTree).sort((a, b) => a.localeCompare(b));\n const lines: string[] = [];\n\n for (const controllerName of controllerNames) {\n lines.push(` ${formatPropertyKey(controllerName)}: {`);\n const actions = controllerTree[controllerName];\n const actionNames = Object.keys(actions).sort((a, b) => a.localeCompare(b));\n for (const actionName of actionNames) {\n const action = actions[actionName];\n if (action.hasInput) {\n lines.push(` ${formatPropertyKey(actionName)}(data: ${action.inputType}): Promise<${action.outputType}>;`);\n } else {\n lines.push(` ${formatPropertyKey(actionName)}(): Promise<${action.outputType}>;`);\n }\n }\n lines.push(' };');\n }\n\n return lines.join('\\n');\n}\n\nexport function generateTypes(operations: Map<string, OperationDef>): string {\n const tree = buildNestedTypeTree(operations);\n const typesCode = generateTypeTree(tree);\n const rpcTypeCode = generateRpcTypeTree(operations);\n\n return `// AUTO-GENERATED by @noego/wood -- do not edit\nexport interface WoodRpcManifestEntry {\n channel: string;\n controller: string;\n action: string;\n path: string[];\n hasInput: boolean;\n}\n\n/**\n * Project-specific renderer App facade contract.\n *\n * This matches @noego/wood/client getApp() and injected App instances:\n * controller name -> controller action.\n */\nexport interface GeneratedApp {\n${rpcTypeCode}\n}\n\n/** Backward-compatible name for the generated client App facade contract. */\nexport interface WoodRpcApi extends GeneratedApp {}\n\n/**\n * Project-specific raw preload bridge contract.\n *\n * This matches the channel path exposed by preload.generated.ts:\n * operation channel segments -> invoke function.\n */\nexport interface GeneratedWoodBridge {\n${typesCode}\n}\n\nexport interface WoodApi extends GeneratedWoodBridge {\n __rpcManifest: WoodRpcManifestEntry[];\n __load(route: string, params: Record<string, string>): Promise<unknown>;\n __navigate(windowId: string, route: string): Promise<void>;\n __window: {\n current(): Promise<{ ok: boolean; windowId?: string; defaultRoute?: string }>;\n open(windowId: string, options?: Record<string, unknown>): Promise<void>;\n close(windowId?: string): Promise<void>;\n focus(windowId: string): Promise<void>;\n minimize(windowId?: string): Promise<void>;\n maximize(windowId?: string): Promise<void>;\n };\n __debug: {\n current(): Promise<{\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: Array<{\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: 'ready' | 'loading' | 'unresponsive' | 'gone' | 'destroyed';\n }>;\n }>;\n };\n __contextMenu: {\n show(data: {\n items: Array<{ label?: string; action?: string; data?: string; _callbackId?: string; disabled?: boolean; type?: 'separator' }>;\n position: { x: number; y: number };\n }): Promise<void>;\n };\n on(channel: string, callback: (...args: unknown[]) => void): () => void;\n __log(level: string, logger: string, message: string, context?: unknown): Promise<{\n ok: boolean;\n forwarded: boolean;\n configured: boolean;\n reason?: 'unconfigured' | 'callback-error';\n errorMessage?: string;\n }>;\n}\n`;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/type_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.cjs';\nimport { generatedFileNotice } from './generated_file_notice.cjs';\n\nconst TYPE_SOURCE_INSTRUCTIONS = [\n 'To change IPC channels, input schemas, controller/action names, or renderer bridge types,',\n 'edit the operations YAML configured by wood.config.yml main.openapi and the matching controller methods.',\n] as const;\n\nfunction formatPropertyKey(key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return key;\n }\n\n return JSON.stringify(key);\n}\n\nfunction operationHasInput(op: OperationDef): boolean {\n return Boolean(\n op.inputSchema &&\n (op.inputSchema as Record<string, unknown>).type === 'object' &&\n Object.keys((op.inputSchema as Record<string, Record<string, unknown>>).properties ?? {}).length > 0,\n );\n}\n\nfunction jsonSchemaToTS(schema: Record<string, unknown> | undefined, indent: string = ''): string {\n if (!schema) return 'unknown';\n\n const type = schema.type as string | undefined;\n\n if (type === 'string') {\n if (schema.enum) {\n return (schema.enum as string[]).map((v) => `'${v}'`).join(' | ');\n }\n return 'string';\n }\n if (type === 'number' || type === 'integer') return 'number';\n if (type === 'boolean') return 'boolean';\n if (type === 'array') {\n const itemType = jsonSchemaToTS(schema.items as Record<string, unknown>, indent);\n return `Array<${itemType}>`;\n }\n if (type === 'object') {\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[]) ?? []);\n const entries = Object.entries(props);\n if (entries.length === 0) return 'Record<string, unknown>';\n\n const lines = entries.map(([key, val]) => {\n const optional = required.has(key) ? '' : '?';\n const valType = jsonSchemaToTS(val, indent + ' ');\n return `${indent} ${formatPropertyKey(key)}${optional}: ${valType};`;\n });\n return `{\\n${lines.join('\\n')}\\n${indent}}`;\n }\n\n return 'unknown';\n}\n\nfunction buildNestedTypeTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateTypeTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n const op = entry.__operation as OperationDef;\n const inputType = jsonSchemaToTS(op.inputSchema as Record<string, unknown>, indent + ' ');\n const outputType = jsonSchemaToTS(op.outputSchema as Record<string, unknown>, indent + ' ');\n const hasInput = operationHasInput(op);\n\n if (hasInput) {\n lines.push(`${indent}${formatPropertyKey(key)}(data: ${inputType}): Promise<${outputType}>;`);\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}(): Promise<${outputType}>;`);\n }\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}: {`);\n lines.push(generateTypeTree(entry, indent + ' '));\n lines.push(`${indent}};`);\n }\n }\n return lines.join('\\n');\n}\n\ntype RpcActionTypeEntry = {\n channel: string;\n inputType: string;\n outputType: string;\n hasInput: boolean;\n};\n\nfunction buildRpcControllerTree(\n operations: Map<string, OperationDef>,\n): Record<string, Record<string, RpcActionTypeEntry>> {\n const tree: Record<string, Record<string, RpcActionTypeEntry>> = {};\n\n for (const operation of operations.values()) {\n const controller = operation.controller;\n const action = operation.action;\n\n if (!tree[controller]) {\n tree[controller] = {};\n }\n\n if (tree[controller][action]) {\n throw new Error(\n `Type codegen failed: duplicate RPC action \"${controller}.${action}\" found in channel \"${operation.channel}\".`,\n );\n }\n\n tree[controller][action] = {\n channel: operation.channel,\n inputType: jsonSchemaToTS(operation.inputSchema as Record<string, unknown>, ' '),\n outputType: jsonSchemaToTS(operation.outputSchema as Record<string, unknown>, ' '),\n hasInput: operationHasInput(operation),\n };\n }\n\n return tree;\n}\n\nfunction generateRpcTypeTree(operations: Map<string, OperationDef>): string {\n const controllerTree = buildRpcControllerTree(operations);\n const controllerNames = Object.keys(controllerTree).sort((a, b) => a.localeCompare(b));\n const lines: string[] = [];\n\n for (const controllerName of controllerNames) {\n lines.push(` ${formatPropertyKey(controllerName)}: {`);\n const actions = controllerTree[controllerName];\n const actionNames = Object.keys(actions).sort((a, b) => a.localeCompare(b));\n for (const actionName of actionNames) {\n const action = actions[actionName];\n if (action.hasInput) {\n lines.push(` ${formatPropertyKey(actionName)}(data: ${action.inputType}): Promise<${action.outputType}>;`);\n } else {\n lines.push(` ${formatPropertyKey(actionName)}(): Promise<${action.outputType}>;`);\n }\n }\n lines.push(' };');\n }\n\n return lines.join('\\n');\n}\n\nexport function generateTypes(operations: Map<string, OperationDef>): string {\n const tree = buildNestedTypeTree(operations);\n const typesCode = generateTypeTree(tree);\n const rpcTypeCode = generateRpcTypeTree(operations);\n\n return `${generatedFileNotice(TYPE_SOURCE_INSTRUCTIONS)}\nexport interface WoodRpcManifestEntry {\n channel: string;\n controller: string;\n action: string;\n path: string[];\n hasInput: boolean;\n}\n\n/**\n * Project-specific renderer App facade contract.\n *\n * This matches @noego/wood/client getApp() and injected App instances:\n * controller name -> controller action.\n */\nexport interface GeneratedApp {\n${rpcTypeCode}\n}\n\n/** Backward-compatible name for the generated client App facade contract. */\nexport interface WoodRpcApi extends GeneratedApp {}\n\n/**\n * Project-specific raw preload bridge contract.\n *\n * This matches the channel path exposed by preload.generated.ts:\n * operation channel segments -> invoke function.\n */\nexport interface GeneratedWoodBridge {\n${typesCode}\n}\n\nexport interface WoodApi extends GeneratedWoodBridge {\n __rpcManifest: WoodRpcManifestEntry[];\n __load(route: string, params: Record<string, string>): Promise<unknown>;\n __navigate(windowId: string, route: string): Promise<void>;\n __window: {\n current(): Promise<{ ok: boolean; windowId?: string; defaultRoute?: string }>;\n open(windowId: string, options?: Record<string, unknown>): Promise<void>;\n close(windowId?: string): Promise<void>;\n focus(windowId: string): Promise<void>;\n minimize(windowId?: string): Promise<void>;\n maximize(windowId?: string): Promise<void>;\n };\n __debug: {\n current(): Promise<{\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: Array<{\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: 'ready' | 'loading' | 'unresponsive' | 'gone' | 'destroyed';\n }>;\n }>;\n };\n __contextMenu: {\n show(data: {\n items: Array<{ label?: string; action?: string; data?: string; _callbackId?: string; disabled?: boolean; type?: 'separator' }>;\n position: { x: number; y: number };\n }): Promise<void>;\n };\n on(channel: string, callback: (...args: unknown[]) => void): () => void;\n __log(level: string, logger: string, message: string, context?: unknown): Promise<{\n ok: boolean;\n forwarded: boolean;\n configured: boolean;\n reason?: 'unconfigured' | 'callback-error';\n errorMessage?: string;\n }>;\n}\n`;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { generatedFileNotice } from "./generated_file_notice.js";
|
|
2
|
+
const TYPE_SOURCE_INSTRUCTIONS = [
|
|
3
|
+
"To change IPC channels, input schemas, controller/action names, or renderer bridge types,",
|
|
4
|
+
"edit the operations YAML configured by wood.config.yml main.openapi and the matching controller methods."
|
|
5
|
+
];
|
|
1
6
|
function formatPropertyKey(key) {
|
|
2
7
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {
|
|
3
8
|
return key;
|
|
@@ -121,7 +126,7 @@ function generateTypes(operations) {
|
|
|
121
126
|
const tree = buildNestedTypeTree(operations);
|
|
122
127
|
const typesCode = generateTypeTree(tree);
|
|
123
128
|
const rpcTypeCode = generateRpcTypeTree(operations);
|
|
124
|
-
return
|
|
129
|
+
return `${generatedFileNotice(TYPE_SOURCE_INSTRUCTIONS)}
|
|
125
130
|
export interface WoodRpcManifestEntry {
|
|
126
131
|
channel: string;
|
|
127
132
|
controller: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/type_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.js';\n\nfunction formatPropertyKey(key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return key;\n }\n\n return JSON.stringify(key);\n}\n\nfunction operationHasInput(op: OperationDef): boolean {\n return Boolean(\n op.inputSchema &&\n (op.inputSchema as Record<string, unknown>).type === 'object' &&\n Object.keys((op.inputSchema as Record<string, Record<string, unknown>>).properties ?? {}).length > 0,\n );\n}\n\nfunction jsonSchemaToTS(schema: Record<string, unknown> | undefined, indent: string = ''): string {\n if (!schema) return 'unknown';\n\n const type = schema.type as string | undefined;\n\n if (type === 'string') {\n if (schema.enum) {\n return (schema.enum as string[]).map((v) => `'${v}'`).join(' | ');\n }\n return 'string';\n }\n if (type === 'number' || type === 'integer') return 'number';\n if (type === 'boolean') return 'boolean';\n if (type === 'array') {\n const itemType = jsonSchemaToTS(schema.items as Record<string, unknown>, indent);\n return `Array<${itemType}>`;\n }\n if (type === 'object') {\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[]) ?? []);\n const entries = Object.entries(props);\n if (entries.length === 0) return 'Record<string, unknown>';\n\n const lines = entries.map(([key, val]) => {\n const optional = required.has(key) ? '' : '?';\n const valType = jsonSchemaToTS(val, indent + ' ');\n return `${indent} ${formatPropertyKey(key)}${optional}: ${valType};`;\n });\n return `{\\n${lines.join('\\n')}\\n${indent}}`;\n }\n\n return 'unknown';\n}\n\nfunction buildNestedTypeTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateTypeTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n const op = entry.__operation as OperationDef;\n const inputType = jsonSchemaToTS(op.inputSchema as Record<string, unknown>, indent + ' ');\n const outputType = jsonSchemaToTS(op.outputSchema as Record<string, unknown>, indent + ' ');\n const hasInput = operationHasInput(op);\n\n if (hasInput) {\n lines.push(`${indent}${formatPropertyKey(key)}(data: ${inputType}): Promise<${outputType}>;`);\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}(): Promise<${outputType}>;`);\n }\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}: {`);\n lines.push(generateTypeTree(entry, indent + ' '));\n lines.push(`${indent}};`);\n }\n }\n return lines.join('\\n');\n}\n\ntype RpcActionTypeEntry = {\n channel: string;\n inputType: string;\n outputType: string;\n hasInput: boolean;\n};\n\nfunction buildRpcControllerTree(\n operations: Map<string, OperationDef>,\n): Record<string, Record<string, RpcActionTypeEntry>> {\n const tree: Record<string, Record<string, RpcActionTypeEntry>> = {};\n\n for (const operation of operations.values()) {\n const controller = operation.controller;\n const action = operation.action;\n\n if (!tree[controller]) {\n tree[controller] = {};\n }\n\n if (tree[controller][action]) {\n throw new Error(\n `Type codegen failed: duplicate RPC action \"${controller}.${action}\" found in channel \"${operation.channel}\".`,\n );\n }\n\n tree[controller][action] = {\n channel: operation.channel,\n inputType: jsonSchemaToTS(operation.inputSchema as Record<string, unknown>, ' '),\n outputType: jsonSchemaToTS(operation.outputSchema as Record<string, unknown>, ' '),\n hasInput: operationHasInput(operation),\n };\n }\n\n return tree;\n}\n\nfunction generateRpcTypeTree(operations: Map<string, OperationDef>): string {\n const controllerTree = buildRpcControllerTree(operations);\n const controllerNames = Object.keys(controllerTree).sort((a, b) => a.localeCompare(b));\n const lines: string[] = [];\n\n for (const controllerName of controllerNames) {\n lines.push(` ${formatPropertyKey(controllerName)}: {`);\n const actions = controllerTree[controllerName];\n const actionNames = Object.keys(actions).sort((a, b) => a.localeCompare(b));\n for (const actionName of actionNames) {\n const action = actions[actionName];\n if (action.hasInput) {\n lines.push(` ${formatPropertyKey(actionName)}(data: ${action.inputType}): Promise<${action.outputType}>;`);\n } else {\n lines.push(` ${formatPropertyKey(actionName)}(): Promise<${action.outputType}>;`);\n }\n }\n lines.push(' };');\n }\n\n return lines.join('\\n');\n}\n\nexport function generateTypes(operations: Map<string, OperationDef>): string {\n const tree = buildNestedTypeTree(operations);\n const typesCode = generateTypeTree(tree);\n const rpcTypeCode = generateRpcTypeTree(operations);\n\n return `// AUTO-GENERATED by @noego/wood -- do not edit\nexport interface WoodRpcManifestEntry {\n channel: string;\n controller: string;\n action: string;\n path: string[];\n hasInput: boolean;\n}\n\n/**\n * Project-specific renderer App facade contract.\n *\n * This matches @noego/wood/client getApp() and injected App instances:\n * controller name -> controller action.\n */\nexport interface GeneratedApp {\n${rpcTypeCode}\n}\n\n/** Backward-compatible name for the generated client App facade contract. */\nexport interface WoodRpcApi extends GeneratedApp {}\n\n/**\n * Project-specific raw preload bridge contract.\n *\n * This matches the channel path exposed by preload.generated.ts:\n * operation channel segments -> invoke function.\n */\nexport interface GeneratedWoodBridge {\n${typesCode}\n}\n\nexport interface WoodApi extends GeneratedWoodBridge {\n __rpcManifest: WoodRpcManifestEntry[];\n __load(route: string, params: Record<string, string>): Promise<unknown>;\n __navigate(windowId: string, route: string): Promise<void>;\n __window: {\n current(): Promise<{ ok: boolean; windowId?: string; defaultRoute?: string }>;\n open(windowId: string, options?: Record<string, unknown>): Promise<void>;\n close(windowId?: string): Promise<void>;\n focus(windowId: string): Promise<void>;\n minimize(windowId?: string): Promise<void>;\n maximize(windowId?: string): Promise<void>;\n };\n __debug: {\n current(): Promise<{\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: Array<{\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: 'ready' | 'loading' | 'unresponsive' | 'gone' | 'destroyed';\n }>;\n }>;\n };\n __contextMenu: {\n show(data: {\n items: Array<{ label?: string; action?: string; data?: string; _callbackId?: string; disabled?: boolean; type?: 'separator' }>;\n position: { x: number; y: number };\n }): Promise<void>;\n };\n on(channel: string, callback: (...args: unknown[]) => void): () => void;\n __log(level: string, logger: string, message: string, context?: unknown): Promise<{\n ok: boolean;\n forwarded: boolean;\n configured: boolean;\n reason?: 'unconfigured' | 'callback-error';\n errorMessage?: string;\n }>;\n}\n`;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/type_generator.ts"],"sourcesContent":["import type { OperationDef } from '../types/index.js';\nimport { generatedFileNotice } from './generated_file_notice.js';\n\nconst TYPE_SOURCE_INSTRUCTIONS = [\n 'To change IPC channels, input schemas, controller/action names, or renderer bridge types,',\n 'edit the operations YAML configured by wood.config.yml main.openapi and the matching controller methods.',\n] as const;\n\nfunction formatPropertyKey(key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return key;\n }\n\n return JSON.stringify(key);\n}\n\nfunction operationHasInput(op: OperationDef): boolean {\n return Boolean(\n op.inputSchema &&\n (op.inputSchema as Record<string, unknown>).type === 'object' &&\n Object.keys((op.inputSchema as Record<string, Record<string, unknown>>).properties ?? {}).length > 0,\n );\n}\n\nfunction jsonSchemaToTS(schema: Record<string, unknown> | undefined, indent: string = ''): string {\n if (!schema) return 'unknown';\n\n const type = schema.type as string | undefined;\n\n if (type === 'string') {\n if (schema.enum) {\n return (schema.enum as string[]).map((v) => `'${v}'`).join(' | ');\n }\n return 'string';\n }\n if (type === 'number' || type === 'integer') return 'number';\n if (type === 'boolean') return 'boolean';\n if (type === 'array') {\n const itemType = jsonSchemaToTS(schema.items as Record<string, unknown>, indent);\n return `Array<${itemType}>`;\n }\n if (type === 'object') {\n const props = (schema.properties ?? {}) as Record<string, Record<string, unknown>>;\n const required = new Set((schema.required as string[]) ?? []);\n const entries = Object.entries(props);\n if (entries.length === 0) return 'Record<string, unknown>';\n\n const lines = entries.map(([key, val]) => {\n const optional = required.has(key) ? '' : '?';\n const valType = jsonSchemaToTS(val, indent + ' ');\n return `${indent} ${formatPropertyKey(key)}${optional}: ${valType};`;\n });\n return `{\\n${lines.join('\\n')}\\n${indent}}`;\n }\n\n return 'unknown';\n}\n\nfunction buildNestedTypeTree(operations: Map<string, OperationDef>): Record<string, unknown> {\n const tree: Record<string, unknown> = {};\n for (const [channel, op] of operations) {\n const parts = channel.split('.');\n let current: Record<string, unknown> = tree;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {};\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = { __operation: op };\n }\n return tree;\n}\n\nfunction generateTypeTree(node: Record<string, unknown>, indent: string = ' '): string {\n const lines: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n const entry = value as Record<string, unknown>;\n if (entry.__operation) {\n const op = entry.__operation as OperationDef;\n const inputType = jsonSchemaToTS(op.inputSchema as Record<string, unknown>, indent + ' ');\n const outputType = jsonSchemaToTS(op.outputSchema as Record<string, unknown>, indent + ' ');\n const hasInput = operationHasInput(op);\n\n if (hasInput) {\n lines.push(`${indent}${formatPropertyKey(key)}(data: ${inputType}): Promise<${outputType}>;`);\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}(): Promise<${outputType}>;`);\n }\n } else {\n lines.push(`${indent}${formatPropertyKey(key)}: {`);\n lines.push(generateTypeTree(entry, indent + ' '));\n lines.push(`${indent}};`);\n }\n }\n return lines.join('\\n');\n}\n\ntype RpcActionTypeEntry = {\n channel: string;\n inputType: string;\n outputType: string;\n hasInput: boolean;\n};\n\nfunction buildRpcControllerTree(\n operations: Map<string, OperationDef>,\n): Record<string, Record<string, RpcActionTypeEntry>> {\n const tree: Record<string, Record<string, RpcActionTypeEntry>> = {};\n\n for (const operation of operations.values()) {\n const controller = operation.controller;\n const action = operation.action;\n\n if (!tree[controller]) {\n tree[controller] = {};\n }\n\n if (tree[controller][action]) {\n throw new Error(\n `Type codegen failed: duplicate RPC action \"${controller}.${action}\" found in channel \"${operation.channel}\".`,\n );\n }\n\n tree[controller][action] = {\n channel: operation.channel,\n inputType: jsonSchemaToTS(operation.inputSchema as Record<string, unknown>, ' '),\n outputType: jsonSchemaToTS(operation.outputSchema as Record<string, unknown>, ' '),\n hasInput: operationHasInput(operation),\n };\n }\n\n return tree;\n}\n\nfunction generateRpcTypeTree(operations: Map<string, OperationDef>): string {\n const controllerTree = buildRpcControllerTree(operations);\n const controllerNames = Object.keys(controllerTree).sort((a, b) => a.localeCompare(b));\n const lines: string[] = [];\n\n for (const controllerName of controllerNames) {\n lines.push(` ${formatPropertyKey(controllerName)}: {`);\n const actions = controllerTree[controllerName];\n const actionNames = Object.keys(actions).sort((a, b) => a.localeCompare(b));\n for (const actionName of actionNames) {\n const action = actions[actionName];\n if (action.hasInput) {\n lines.push(` ${formatPropertyKey(actionName)}(data: ${action.inputType}): Promise<${action.outputType}>;`);\n } else {\n lines.push(` ${formatPropertyKey(actionName)}(): Promise<${action.outputType}>;`);\n }\n }\n lines.push(' };');\n }\n\n return lines.join('\\n');\n}\n\nexport function generateTypes(operations: Map<string, OperationDef>): string {\n const tree = buildNestedTypeTree(operations);\n const typesCode = generateTypeTree(tree);\n const rpcTypeCode = generateRpcTypeTree(operations);\n\n return `${generatedFileNotice(TYPE_SOURCE_INSTRUCTIONS)}\nexport interface WoodRpcManifestEntry {\n channel: string;\n controller: string;\n action: string;\n path: string[];\n hasInput: boolean;\n}\n\n/**\n * Project-specific renderer App facade contract.\n *\n * This matches @noego/wood/client getApp() and injected App instances:\n * controller name -> controller action.\n */\nexport interface GeneratedApp {\n${rpcTypeCode}\n}\n\n/** Backward-compatible name for the generated client App facade contract. */\nexport interface WoodRpcApi extends GeneratedApp {}\n\n/**\n * Project-specific raw preload bridge contract.\n *\n * This matches the channel path exposed by preload.generated.ts:\n * operation channel segments -> invoke function.\n */\nexport interface GeneratedWoodBridge {\n${typesCode}\n}\n\nexport interface WoodApi extends GeneratedWoodBridge {\n __rpcManifest: WoodRpcManifestEntry[];\n __load(route: string, params: Record<string, string>): Promise<unknown>;\n __navigate(windowId: string, route: string): Promise<void>;\n __window: {\n current(): Promise<{ ok: boolean; windowId?: string; defaultRoute?: string }>;\n open(windowId: string, options?: Record<string, unknown>): Promise<void>;\n close(windowId?: string): Promise<void>;\n focus(windowId: string): Promise<void>;\n minimize(windowId?: string): Promise<void>;\n maximize(windowId?: string): Promise<void>;\n };\n __debug: {\n current(): Promise<{\n ok: boolean;\n enabled: boolean;\n mode: 'development' | 'production';\n port?: number;\n windows: Array<{\n windowId: string;\n title: string;\n webContentsId: number;\n url: string;\n focused: boolean;\n rendererHealth?: 'ready' | 'loading' | 'unresponsive' | 'gone' | 'destroyed';\n }>;\n }>;\n };\n __contextMenu: {\n show(data: {\n items: Array<{ label?: string; action?: string; data?: string; _callbackId?: string; disabled?: boolean; type?: 'separator' }>;\n position: { x: number; y: number };\n }): Promise<void>;\n };\n on(channel: string, callback: (...args: unknown[]) => void): () => void;\n __log(level: string, logger: string, message: string, context?: unknown): Promise<{\n ok: boolean;\n forwarded: boolean;\n configured: boolean;\n reason?: 'unconfigured' | 'callback-error';\n errorMessage?: string;\n }>;\n}\n`;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ __export(index_exports, {
|
|
|
31
31
|
RendererTracer: () => import_tracing.RendererTracer,
|
|
32
32
|
SchemaValidator: () => import_validation.SchemaValidator,
|
|
33
33
|
TestTracer: () => import_tracing.TestTracer,
|
|
34
|
+
TraceCommitWriter: () => import_tracing.TraceCommitWriter,
|
|
34
35
|
TraceProvider: () => import_tracing.TraceProvider,
|
|
35
36
|
TraceProviderConfiguration: () => import_tracing.TraceProviderConfiguration,
|
|
36
37
|
WOOD_DEV_DIRECTORY: () => import_dev_metadata.WOOD_DEV_DIRECTORY,
|
|
@@ -44,21 +45,24 @@ __export(index_exports, {
|
|
|
44
45
|
buildMiddlewareContext: () => import_middleware.buildMiddlewareContext,
|
|
45
46
|
clearApplicationRootForTests: () => import_runtime.clearApplicationRootForTests,
|
|
46
47
|
clearContainerRegistryForTests: () => import_runtime.clearContainerRegistryForTests,
|
|
48
|
+
clearRendererTraceBatchReceiverForTests: () => import_runtime.clearRendererTraceBatchReceiverForTests,
|
|
47
49
|
clearTraceHubForTests: () => import_tracing.clearTraceHubForTests,
|
|
48
50
|
disposeControllerLifecycle: () => import_controller.disposeControllerLifecycle,
|
|
49
51
|
executeMiddleware: () => import_middleware.executeMiddleware,
|
|
50
|
-
|
|
52
|
+
generateChannelMap: () => import_codegen3.generateChannelMap,
|
|
53
|
+
generateControllerRegistration: () => import_codegen5.generateControllerRegistration,
|
|
51
54
|
generatePreload: () => import_codegen.generatePreload,
|
|
52
|
-
generateRendererApp: () =>
|
|
53
|
-
generateRendererControllerRegistration: () =>
|
|
54
|
-
generateRendererViewManifest: () =>
|
|
55
|
-
generateRuntime: () =>
|
|
56
|
-
generateTestMock: () =>
|
|
55
|
+
generateRendererApp: () => import_codegen9.generateRendererApp,
|
|
56
|
+
generateRendererControllerRegistration: () => import_codegen8.generateRendererControllerRegistration,
|
|
57
|
+
generateRendererViewManifest: () => import_codegen7.generateRendererViewManifest,
|
|
58
|
+
generateRuntime: () => import_codegen6.generateRuntime,
|
|
59
|
+
generateTestMock: () => import_codegen4.generateTestMock,
|
|
57
60
|
generateTypes: () => import_codegen2.generateTypes,
|
|
58
61
|
getApplicationRoot: () => import_runtime.getApplicationRoot,
|
|
59
62
|
getContainer: () => import_runtime.getContainer,
|
|
60
63
|
getIpc: () => import_ipc.getIpc,
|
|
61
64
|
getNavigation: () => import_navigation.getNavigation,
|
|
65
|
+
getRendererTraceBatchReceiver: () => import_runtime.getRendererTraceBatchReceiver,
|
|
62
66
|
getTraceEvents$: () => import_tracing.getTraceEvents$,
|
|
63
67
|
go: () => import_navigation.go,
|
|
64
68
|
goback: () => import_navigation.goback,
|
|
@@ -70,12 +74,14 @@ __export(index_exports, {
|
|
|
70
74
|
parseViewsFile: () => import_parser2.parseViewsFile,
|
|
71
75
|
pushEvent: () => import_bridge.pushEvent,
|
|
72
76
|
readWoodDevMetadata: () => import_dev_metadata.readWoodDevMetadata,
|
|
77
|
+
registerTraceSink: () => import_tracing.registerTraceSink,
|
|
73
78
|
removeWoodDevMetadata: () => import_dev_metadata.removeWoodDevMetadata,
|
|
74
79
|
resolveWoodDevDirectory: () => import_dev_metadata.resolveWoodDevDirectory,
|
|
75
80
|
resolveWoodDevMetadataPath: () => import_dev_metadata.resolveWoodDevMetadataPath,
|
|
76
81
|
resolveWoodRemoteDebuggingPort: () => import_dev_metadata.resolveWoodRemoteDebuggingPort,
|
|
77
82
|
runtime: () => import_runtime.runtime,
|
|
78
83
|
setApplicationRoot: () => import_runtime.setApplicationRoot,
|
|
84
|
+
setRendererTraceBatchReceiver: () => import_runtime.setRendererTraceBatchReceiver,
|
|
79
85
|
setRendererTraceEnabled: () => import_tracing.setRendererTraceEnabled,
|
|
80
86
|
setRendererTraceTransport: () => import_tracing.setRendererTraceTransport,
|
|
81
87
|
startBackendLoop: () => import_bridge.startBackendLoop,
|
|
@@ -98,6 +104,7 @@ var import_codegen5 = require("./codegen/index.cjs");
|
|
|
98
104
|
var import_codegen6 = require("./codegen/index.cjs");
|
|
99
105
|
var import_codegen7 = require("./codegen/index.cjs");
|
|
100
106
|
var import_codegen8 = require("./codegen/index.cjs");
|
|
107
|
+
var import_codegen9 = require("./codegen/index.cjs");
|
|
101
108
|
var import_window = require("./window/index.cjs");
|
|
102
109
|
var import_loader = require("./loader/index.cjs");
|
|
103
110
|
var import_bridge = require("./bridge/index.cjs");
|
|
@@ -121,6 +128,7 @@ var import_tracing = require("./tracing/index.js");
|
|
|
121
128
|
RendererTracer,
|
|
122
129
|
SchemaValidator,
|
|
123
130
|
TestTracer,
|
|
131
|
+
TraceCommitWriter,
|
|
124
132
|
TraceProvider,
|
|
125
133
|
TraceProviderConfiguration,
|
|
126
134
|
WOOD_DEV_DIRECTORY,
|
|
@@ -134,9 +142,11 @@ var import_tracing = require("./tracing/index.js");
|
|
|
134
142
|
buildMiddlewareContext,
|
|
135
143
|
clearApplicationRootForTests,
|
|
136
144
|
clearContainerRegistryForTests,
|
|
145
|
+
clearRendererTraceBatchReceiverForTests,
|
|
137
146
|
clearTraceHubForTests,
|
|
138
147
|
disposeControllerLifecycle,
|
|
139
148
|
executeMiddleware,
|
|
149
|
+
generateChannelMap,
|
|
140
150
|
generateControllerRegistration,
|
|
141
151
|
generatePreload,
|
|
142
152
|
generateRendererApp,
|
|
@@ -149,6 +159,7 @@ var import_tracing = require("./tracing/index.js");
|
|
|
149
159
|
getContainer,
|
|
150
160
|
getIpc,
|
|
151
161
|
getNavigation,
|
|
162
|
+
getRendererTraceBatchReceiver,
|
|
152
163
|
getTraceEvents$,
|
|
153
164
|
go,
|
|
154
165
|
goback,
|
|
@@ -160,12 +171,14 @@ var import_tracing = require("./tracing/index.js");
|
|
|
160
171
|
parseViewsFile,
|
|
161
172
|
pushEvent,
|
|
162
173
|
readWoodDevMetadata,
|
|
174
|
+
registerTraceSink,
|
|
163
175
|
removeWoodDevMetadata,
|
|
164
176
|
resolveWoodDevDirectory,
|
|
165
177
|
resolveWoodDevMetadataPath,
|
|
166
178
|
resolveWoodRemoteDebuggingPort,
|
|
167
179
|
runtime,
|
|
168
180
|
setApplicationRoot,
|
|
181
|
+
setRendererTraceBatchReceiver,
|
|
169
182
|
setRendererTraceEnabled,
|
|
170
183
|
setRendererTraceTransport,
|
|
171
184
|
startBackendLoop,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// @noego/wood — Declarative Electron desktop apps using the noego ecosystem\n\n// Types\nexport type {\n WoodConfig,\n WindowDef,\n DevConfig,\n ElectronBuilderConfig,\n OperationDef,\n RawOperationsDocument,\n RawModuleDef,\n RawOperationEntry,\n RawModuleOperationEntry,\n ViewDef,\n RawViewsDocument,\n RawViewEntry,\n ParameterDef,\n IpcContext,\n WoodMiddlewareContext,\n WoodMiddlewareFn,\n RequestData,\n ControllerArgs,\n LoaderResult,\n BridgeMessage,\n BridgeRequest,\n BridgeResponse,\n BridgeReady,\n BridgePush,\n BridgeElectronApi,\n SerializedError,\n ContextMenuContext,\n ContextMenuItem,\n ContextMenuEvent,\n} from './types';\n\n// Errors\nexport { WoodAuthError, WoodValidationError, BackendRestartingError } from './types/index.cjs';\n\n// Config\nexport { parseConfig } from './config/index.cjs';\n\n// Parsers\nexport { parseOperations, parseOperationsFile } from './parser/index.cjs';\nexport { parseViews, parseViewsFile } from './parser/index.cjs';\n\n// Router\nexport { WoodRouter } from './router/index.cjs';\n\n// Validation\nexport { SchemaValidator } from './validation/index.cjs';\n\n// Middleware\nexport { MiddlewareResolver, buildMiddlewareContext, executeMiddleware } from './middleware/index.cjs';\n\n// Controller\nexport { ControllerResolver, buildControllerArgs, disposeControllerLifecycle } from './controller/index.cjs';\nexport type { ControllerLifecycle } from './controller/index.cjs';\n\n// Codegen\nexport { generatePreload } from './codegen/index.cjs';\nexport { generateTypes } from './codegen/index.cjs';\nexport { generateTestMock } from './codegen/index.cjs';\nexport { generateControllerRegistration } from './codegen/index.cjs';\nexport type { ControllerRegistrationOptions } from './codegen/index.cjs';\nexport { generateRuntime } from './codegen/index.cjs';\nexport type { RuntimeGeneratorOptions } from './codegen/index.cjs';\nexport { generateRendererViewManifest } from './codegen/index.cjs';\nexport type { RendererViewManifestGeneratorOptions } from './codegen/index.cjs';\nexport { generateRendererControllerRegistration } from './codegen/index.cjs';\nexport type { RendererControllerRegistrationOptions } from './codegen/index.cjs';\nexport { generateRendererApp } from './codegen/index.cjs';\nexport type { RendererAppGeneratorOptions } from './codegen/index.cjs';\n\n// Window\nexport { WindowManager, WindowStateStore } from './window/index.cjs';\nexport type { ScreenLike, WindowBounds } from './window/index.cjs';\n\n// Loader\nexport { LoaderRunner } from './loader/index.cjs';\n\n// Bridge\nexport { BackendBridge, startBackendLoop, pushEvent } from './bridge/index.cjs';\n\n// Dev metadata (lightweight; safe at runtime)\n// Heavy dev tooling (WoodDevServer, BackendWatcher, YamlWatcher,\n// EsbuildBackend) is available via the '@noego/wood/dev' subpath only,\n// so production consumers never load esbuild/chokidar.\nexport {\n DEFAULT_WOOD_REMOTE_DEBUGGING_PORT,\n WOOD_DEV_DIRECTORY,\n WOOD_DEV_METADATA_BASENAME,\n resolveWoodRemoteDebuggingPort,\n resolveWoodDevDirectory,\n resolveWoodDevMetadataPath,\n writeWoodDevMetadata,\n readWoodDevMetadata,\n removeWoodDevMetadata,\n} from './dev/dev_metadata.js';\nexport type { WoodDevMetadata } from './dev/dev_metadata.js';\n\n// Runtime\nexport {\n getContainer,\n clearContainerRegistryForTests,\n getApplicationRoot,\n setApplicationRoot,\n clearApplicationRootForTests,\n runtime,\n} from './runtime/index.js';\nexport type {\n GetContainerOptions,\n RuntimeOptions,\n RuntimeResult,\n RegisterRuntimeRouter,\n} from './runtime';\n\n// Navigation\nexport { Navigation, getNavigation, go, goto, goback } from './navigation/index.cjs';\nexport type { NavigationEntry, NavigationOptions } from './navigation/index.cjs';\n\n// Isomorphic IPC API\nexport { Ipc, getIpc } from './ipc/index.cjs';\nexport type { IpcPushOptions } from './ipc/index.cjs';\n\n// Tracing\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n clearTraceHubForTests,\n getTraceEvents$,\n setRendererTraceEnabled,\n setRendererTraceTransport,\n} from './tracing/index.js';\nexport type {\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceLevel,\n TraceProcess,\n TraceProviderMode,\n TraceRuntimeContext,\n TraceRuntime,\n TraceWaitOptions,\n} from './tracing/index.js';\n\n// Testing — available via '@noego/wood/testing' subpath export.\n// Not re-exported here to avoid pulling vitest into production builds.\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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCA,mBAA2E;AAG3E,oBAA4B;AAG5B,oBAAqD;AACrD,IAAAA,iBAA2C;AAG3C,oBAA2B;AAG3B,wBAAgC;AAGhC,wBAA8E;AAG9E,wBAAoF;AAIpF,qBAAgC;AAChC,IAAAC,kBAA8B;AAC9B,IAAAA,kBAAiC;AACjC,IAAAA,kBAA+C;AAE/C,IAAAA,kBAAgC;AAEhC,IAAAA,kBAA6C;AAE7C,IAAAA,kBAAuD;AAEvD,IAAAA,kBAAoC;AAIpC,oBAAgD;AAIhD,oBAA6B;AAG7B,oBAA2D;AAM3D,0BAUO;AAIP,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// @noego/wood — Declarative Electron desktop apps using the noego ecosystem\n\n// Types\nexport type {\n WoodConfig,\n WindowDef,\n DevConfig,\n ElectronBuilderConfig,\n OperationDef,\n RawOperationsDocument,\n RawModuleDef,\n RawOperationEntry,\n RawModuleOperationEntry,\n ViewDef,\n RawViewsDocument,\n RawViewEntry,\n ParameterDef,\n IpcContext,\n WoodMiddlewareContext,\n WoodMiddlewareFn,\n RequestData,\n ControllerArgs,\n LoaderResult,\n BridgeMessage,\n BridgeRequest,\n BridgeResponse,\n BridgeReady,\n BridgePush,\n BridgeElectronApi,\n SerializedError,\n ContextMenuContext,\n ContextMenuItem,\n ContextMenuEvent,\n} from './types';\n\n// Errors\nexport { WoodAuthError, WoodValidationError, BackendRestartingError } from './types/index.cjs';\n\n// Config\nexport { parseConfig } from './config/index.cjs';\n\n// Parsers\nexport { parseOperations, parseOperationsFile } from './parser/index.cjs';\nexport { parseViews, parseViewsFile } from './parser/index.cjs';\n\n// Router\nexport { WoodRouter } from './router/index.cjs';\n\n// Validation\nexport { SchemaValidator } from './validation/index.cjs';\n\n// Middleware\nexport { MiddlewareResolver, buildMiddlewareContext, executeMiddleware } from './middleware/index.cjs';\n\n// Controller\nexport { ControllerResolver, buildControllerArgs, disposeControllerLifecycle } from './controller/index.cjs';\nexport type { ControllerLifecycle } from './controller/index.cjs';\n\n// Codegen\nexport { generatePreload } from './codegen/index.cjs';\nexport { generateTypes } from './codegen/index.cjs';\nexport { generateChannelMap } from './codegen/index.cjs';\nexport { generateTestMock } from './codegen/index.cjs';\nexport { generateControllerRegistration } from './codegen/index.cjs';\nexport type { ControllerRegistrationOptions } from './codegen/index.cjs';\nexport { generateRuntime } from './codegen/index.cjs';\nexport type { RuntimeGeneratorOptions } from './codegen/index.cjs';\nexport { generateRendererViewManifest } from './codegen/index.cjs';\nexport type { RendererViewManifestGeneratorOptions } from './codegen/index.cjs';\nexport { generateRendererControllerRegistration } from './codegen/index.cjs';\nexport type { RendererControllerRegistrationOptions } from './codegen/index.cjs';\nexport { generateRendererApp } from './codegen/index.cjs';\nexport type { RendererAppGeneratorOptions } from './codegen/index.cjs';\n\n// Window\nexport { WindowManager, WindowStateStore } from './window/index.cjs';\nexport type { ScreenLike, WindowBounds } from './window/index.cjs';\n\n// Loader\nexport { LoaderRunner } from './loader/index.cjs';\n\n// Bridge\nexport { BackendBridge, startBackendLoop, pushEvent } from './bridge/index.cjs';\n\n// Dev metadata (lightweight; safe at runtime)\n// Heavy dev tooling (WoodDevServer, BackendWatcher, YamlWatcher,\n// EsbuildBackend) is available via the '@noego/wood/dev' subpath only,\n// so production consumers never load esbuild/chokidar.\nexport {\n DEFAULT_WOOD_REMOTE_DEBUGGING_PORT,\n WOOD_DEV_DIRECTORY,\n WOOD_DEV_METADATA_BASENAME,\n resolveWoodRemoteDebuggingPort,\n resolveWoodDevDirectory,\n resolveWoodDevMetadataPath,\n writeWoodDevMetadata,\n readWoodDevMetadata,\n removeWoodDevMetadata,\n} from './dev/dev_metadata.js';\nexport type { WoodDevMetadata } from './dev/dev_metadata.js';\n\n// Runtime\nexport {\n getContainer,\n clearContainerRegistryForTests,\n getApplicationRoot,\n setApplicationRoot,\n clearApplicationRootForTests,\n clearRendererTraceBatchReceiverForTests,\n getRendererTraceBatchReceiver,\n runtime,\n setRendererTraceBatchReceiver,\n} from './runtime/index.js';\nexport type {\n GetContainerOptions,\n RuntimeOptions,\n RuntimeResult,\n RegisterRuntimeRouter,\n} from './runtime';\n\n// Navigation\nexport { Navigation, getNavigation, go, goto, goback } from './navigation/index.cjs';\nexport type { NavigationEntry, NavigationOptions } from './navigation/index.cjs';\n\n// Isomorphic IPC API\nexport { Ipc, getIpc } from './ipc/index.cjs';\nexport type { IpcPushOptions } from './ipc/index.cjs';\n\n// Tracing\nexport {\n FrameworkTracer,\n MainTracer,\n RendererTracer,\n TestTracer,\n TraceProvider,\n TraceProviderConfiguration,\n TraceCommitWriter,\n clearTraceHubForTests,\n getTraceEvents$,\n registerTraceSink,\n setRendererTraceEnabled,\n setRendererTraceTransport,\n} from './tracing/index.js';\nexport type {\n TraceCommitRow,\n TraceCommitWriterOptions,\n TraceFlushOptions,\n TraceFlushResult,\n WoodTracePersistencePort,\n TraceDispatchResult,\n TraceEvent,\n TraceInput,\n TraceLevel,\n TraceProcess,\n TraceProviderMode,\n TraceRuntimeContext,\n TraceRuntime,\n TraceWaitOptions,\n WoodRendererTraceEvent,\n WoodRendererTraceInput,\n WoodTraceBatch,\n WoodTraceBatchAcknowledgement,\n WoodTraceBatchReceiver,\n WoodTraceBatchRuntimeContext,\n WoodTraceEventSink,\n WoodTraceEventSnapshot,\n WoodTraceSinkDisposer,\n} from './tracing/index.js';\n\n// Testing — available via '@noego/wood/testing' subpath export.\n// Not re-exported here to avoid pulling vitest into production builds.\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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCA,mBAA2E;AAG3E,oBAA4B;AAG5B,oBAAqD;AACrD,IAAAA,iBAA2C;AAG3C,oBAA2B;AAG3B,wBAAgC;AAGhC,wBAA8E;AAG9E,wBAAoF;AAIpF,qBAAgC;AAChC,IAAAC,kBAA8B;AAC9B,IAAAA,kBAAmC;AACnC,IAAAA,kBAAiC;AACjC,IAAAA,kBAA+C;AAE/C,IAAAA,kBAAgC;AAEhC,IAAAA,kBAA6C;AAE7C,IAAAA,kBAAuD;AAEvD,IAAAA,kBAAoC;AAIpC,oBAAgD;AAIhD,oBAA6B;AAG7B,oBAA2D;AAM3D,0BAUO;AAIP,qBAUO;AASP,wBAA4D;AAI5D,iBAA4B;AAI5B,qBAaO;","names":["import_parser","import_codegen"]}
|