@nwire/scan 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/manifest.js +25 -1
  2. package/package.json +6 -6
package/dist/manifest.js CHANGED
@@ -80,12 +80,36 @@ export function readEmittedTopology(root) {
80
80
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
81
  export function buildManifest(root, app = "", instance) {
82
82
  const ast = extractFromFiles(collectSourceFiles(root), app);
83
- const topology = instance ? captureTopology(instance) : readEmittedTopology(root);
83
+ const topology = dedupeTopologyHooks(instance ? captureTopology(instance) : readEmittedTopology(root));
84
84
  const model = buildGraph(ast, topology);
85
85
  return topology
86
86
  ? { version: MANIFEST_VERSION, ...ast, topology, model }
87
87
  : { version: MANIFEST_VERSION, ...ast, model };
88
88
  }
89
+ /**
90
+ * Collapse hooks that share a name to a single logical entry.
91
+ *
92
+ * The hook registry is process-wide (pinned to globalThis). Under the
93
+ * `nwire dev` one-Vite host there are two module graphs — the cli's own Node
94
+ * import chain and the app's Vite SSR graph — that each evaluate the
95
+ * framework's module-level hooks, so the emitted topology lists every
96
+ * framework hook twice (with distinct ids but identical names). A hook name is
97
+ * a logical identifier, so dedupe by it; prefer the entry that carries a source
98
+ * location so Studio can still link to source. In production (single graph)
99
+ * there are no duplicates, so this is a no-op.
100
+ */
101
+ function dedupeTopologyHooks(topology) {
102
+ if (!topology)
103
+ return topology;
104
+ const byName = new Map();
105
+ for (const h of topology.hooks) {
106
+ const existing = byName.get(h.name);
107
+ if (!existing || (existing.source === undefined && h.source !== undefined)) {
108
+ byName.set(h.name, h);
109
+ }
110
+ }
111
+ return { ...topology, hooks: [...byName.values()] };
112
+ }
89
113
  /** Write the manifest to `<outDir>/manifest.json` (default `.nwire`). */
90
114
  export async function writeManifest(manifest, outDir = ".nwire") {
91
115
  await mkdir(outDir, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nwire/scan",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "Nwire — system registry scanner. Walks AppDefinition[] manifests and writes the .nwire/ cache (actions, events, actors, projections, queries, routes, event graph). Vite plugin + standalone function.",
5
5
  "keywords": [
6
6
  "cache",
@@ -34,17 +34,17 @@
34
34
  "dependencies": {
35
35
  "typescript": "^5.9.3",
36
36
  "zod": "^4.4.3",
37
- "@nwire/forge": "0.13.0",
38
- "@nwire/messages": "0.13.0",
39
- "@nwire/telemetry": "0.13.0",
40
- "@nwire/hooks": "0.13.0"
37
+ "@nwire/forge": "0.13.2",
38
+ "@nwire/messages": "0.13.2",
39
+ "@nwire/telemetry": "0.13.2",
40
+ "@nwire/hooks": "0.13.2"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.19.9",
44
44
  "typescript": "^5.9.3",
45
45
  "vite": "npm:rolldown-vite@latest",
46
46
  "vitest": "^4.0.18",
47
- "@nwire/container": "0.13.0"
47
+ "@nwire/container": "0.13.2"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsc && node ../../scripts/fix-dist-extensions.mjs dist",