@nuvio/vite-plugin 0.5.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,17 +1,99 @@
1
1
  import {
2
+ __toESM,
2
3
  buildSourceIndex,
4
+ detectProjectLibraries,
3
5
  extractIdsFromSource,
6
+ handleTagElementMessage,
4
7
  pathnameFromUpgradeUrl,
5
8
  pickBestSourceIndex,
6
- readRuntimeVersions
7
- } from "./chunk-KTNIIC2D.js";
9
+ readRuntimeVersions,
10
+ require_lib,
11
+ resolvePatchClassNameMode
12
+ } from "./chunk-QAQAJG7B.js";
8
13
 
9
14
  // src/index.ts
10
15
  import fs from "fs";
11
- import path from "path";
16
+ import path2 from "path";
12
17
  import { WebSocket } from "ws";
13
18
  import { WebSocketServer } from "ws";
14
19
  import { applyPatchToSource } from "@nuvio/ast-engine";
20
+
21
+ // src/jsx-loc-transform.ts
22
+ var t = __toESM(require_lib(), 1);
23
+ import { createRequire } from "module";
24
+ import { parse } from "@babel/parser";
25
+ import traverseImport from "@babel/traverse";
26
+ import path from "path";
27
+ var require2 = createRequire(import.meta.url);
28
+ var generate = require2("@babel/generator").default;
29
+ var LOC_ATTR = "data-nuvio-loc";
30
+ function getTraverseFn() {
31
+ if (typeof traverseImport === "function") {
32
+ return traverseImport;
33
+ }
34
+ const d = traverseImport.default;
35
+ if (typeof d === "function") {
36
+ return d;
37
+ }
38
+ throw new Error("[Nuvio] @babel/traverse did not resolve to a callable export");
39
+ }
40
+ function hasNuvioId(opening) {
41
+ return opening.attributes.some(
42
+ (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && (attr.name.name === "data-nuvio-id" || attr.name.name === LOC_ATTR)
43
+ );
44
+ }
45
+ function hasLocAttr(opening) {
46
+ return opening.attributes.some(
47
+ (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name, { name: LOC_ATTR })
48
+ );
49
+ }
50
+ function injectJsxLocAttributes(code, fileAbs, projectRoot) {
51
+ if (!/\.(tsx|jsx)$/.test(fileAbs)) {
52
+ return { code, changed: false };
53
+ }
54
+ let ast;
55
+ try {
56
+ ast = parse(code, {
57
+ sourceType: "module",
58
+ plugins: ["typescript", "jsx"],
59
+ sourceFilename: fileAbs
60
+ });
61
+ } catch {
62
+ return { code, changed: false };
63
+ }
64
+ const rel = path.relative(projectRoot, fileAbs).split(path.sep).join("/");
65
+ let changed = false;
66
+ const traverseFn = getTraverseFn();
67
+ traverseFn(ast, {
68
+ JSXOpeningElement(p) {
69
+ const opening = p.node;
70
+ if (opening.name.type !== "JSXIdentifier") {
71
+ return;
72
+ }
73
+ if (hasNuvioId(opening)) {
74
+ return;
75
+ }
76
+ if (hasLocAttr(opening)) {
77
+ return;
78
+ }
79
+ const loc = opening.loc?.start;
80
+ if (!loc) {
81
+ return;
82
+ }
83
+ const value = `${rel}:${loc.line}:${loc.column}`;
84
+ opening.attributes.push(
85
+ t.jsxAttribute(t.jsxIdentifier(LOC_ATTR), t.stringLiteral(value))
86
+ );
87
+ changed = true;
88
+ }
89
+ });
90
+ if (!changed) {
91
+ return { code, changed: false };
92
+ }
93
+ return { code: generate(ast, { retainLines: true }).code, changed: true };
94
+ }
95
+
96
+ // src/index.ts
15
97
  import {
16
98
  NUVIO_WS_PATH,
17
99
  PROTOCOL_VERSION,
@@ -41,7 +123,7 @@ function supplementIndexFromAppTsx(serverRoot, built, classNameMode, emitWarn =
41
123
  return built;
42
124
  }
43
125
  for (const rel of APP_ENTRY_CANDIDATES) {
44
- const appTsx = path.resolve(serverRoot, rel);
126
+ const appTsx = path2.resolve(serverRoot, rel);
45
127
  if (!fs.existsSync(appTsx)) {
46
128
  continue;
47
129
  }
@@ -90,9 +172,25 @@ function nuvio(options) {
90
172
  let cachedIndexPayload = null;
91
173
  let runtimeDiagnostics = { overlayCssMode: "self-contained" };
92
174
  const idToEntry = /* @__PURE__ */ new Map();
175
+ let lastDuplicateErrors = [];
176
+ let projectRoot = process.cwd();
93
177
  return {
94
178
  name: "nuvio",
95
179
  apply: "serve",
180
+ transform(code, id) {
181
+ if (!enabled) {
182
+ return null;
183
+ }
184
+ if (!id || id.includes("node_modules") || !/\.(tsx|jsx)$/.test(id)) {
185
+ return null;
186
+ }
187
+ const fileAbs = path2.isAbsolute(id) ? id : path2.resolve(projectRoot, id);
188
+ const { code: next, changed } = injectJsxLocAttributes(code, fileAbs, projectRoot);
189
+ if (!changed) {
190
+ return null;
191
+ }
192
+ return { code: next, map: null };
193
+ },
96
194
  configureServer(server) {
97
195
  if (!enabled) {
98
196
  server.config.logger.info(
@@ -101,10 +199,11 @@ function nuvio(options) {
101
199
  return;
102
200
  }
103
201
  const log = server.config.logger;
104
- const fromConfigFile = typeof server.config.configFile === "string" ? path.dirname(server.config.configFile) : "";
105
- const serverRoot = path.resolve(server.config.root);
202
+ const fromConfigFile = typeof server.config.configFile === "string" ? path2.dirname(server.config.configFile) : "";
203
+ const serverRoot = path2.resolve(server.config.root);
204
+ projectRoot = path2.resolve(fromConfigFile || serverRoot);
106
205
  const rootCandidates = [
107
- path.resolve(fromConfigFile || serverRoot),
206
+ path2.resolve(fromConfigFile || serverRoot),
108
207
  serverRoot,
109
208
  process.cwd()
110
209
  ];
@@ -119,12 +218,12 @@ function nuvio(options) {
119
218
  }
120
219
  };
121
220
  const rebuildIndex = () => {
122
- let built = pickBestSourceIndex(rootCandidates, scanGlobs, { classNameMode });
221
+ const detectedLibraries = detectProjectLibraries(serverRoot);
222
+ const indexOptions = { classNameMode, detectedLibraries };
223
+ let built = pickBestSourceIndex(rootCandidates, scanGlobs, indexOptions);
123
224
  built = supplementIndexFromAppTsx(serverRoot, built, classNameMode, log.warn);
124
225
  if (built.entries.length === 0) {
125
- const fallback = buildSourceIndex(serverRoot, ["src/**/*.{tsx,jsx}"], {
126
- classNameMode
127
- });
226
+ const fallback = buildSourceIndex(serverRoot, ["src/**/*.{tsx,jsx}"], indexOptions);
128
227
  if (fallback.entries.length > 0) {
129
228
  log.warn(
130
229
  `[Nuvio] Multi-root scan yielded 0 ids; using serverRoot-only index (${fallback.entries.length} id(s)) from ${serverRoot}.`
@@ -137,10 +236,12 @@ function nuvio(options) {
137
236
  for (const e of built.entries) {
138
237
  idToEntry.set(e.id, e);
139
238
  }
239
+ lastDuplicateErrors = built.duplicateErrors;
140
240
  const versions = readRuntimeVersions(serverRoot);
141
241
  runtimeDiagnostics = {
142
242
  ...versions,
143
- overlayCssMode: "self-contained"
243
+ overlayCssMode: "self-contained",
244
+ detectedLibraries: detectedLibraries.length > 0 ? detectedLibraries : void 0
144
245
  };
145
246
  cachedIndexPayload = serializeServerMessage({
146
247
  type: "indexReady",
@@ -194,14 +295,14 @@ function nuvio(options) {
194
295
  }
195
296
  };
196
297
  const debouncedRebuild = /* @__PURE__ */ (() => {
197
- let t;
298
+ let t2;
198
299
  return () => {
199
- if (t) {
200
- clearTimeout(t);
300
+ if (t2) {
301
+ clearTimeout(t2);
201
302
  }
202
- t = setTimeout(() => {
303
+ t2 = setTimeout(() => {
203
304
  rebuildIndex();
204
- t = void 0;
305
+ t2 = void 0;
205
306
  }, 120);
206
307
  };
207
308
  })();
@@ -300,8 +401,19 @@ function nuvio(options) {
300
401
  );
301
402
  return;
302
403
  }
404
+ if (msg.type === "tagElement") {
405
+ const writeGuardRoot = path2.resolve(fromConfigFile || serverRoot);
406
+ await handleTagElementMessage(ws, msg, {
407
+ writeGuardRoot,
408
+ projectRoot,
409
+ idToEntry,
410
+ duplicateIds: lastDuplicateErrors,
411
+ onIndexRebuilt: debouncedRebuild
412
+ });
413
+ return;
414
+ }
303
415
  if (msg.type === "patchUndo") {
304
- const writeGuardRoot = path.resolve(fromConfigFile || serverRoot);
416
+ const writeGuardRoot = path2.resolve(fromConfigFile || serverRoot);
305
417
  const last = undoStack.pop();
306
418
  if (!last) {
307
419
  ws.send(
@@ -348,7 +460,7 @@ function nuvio(options) {
348
460
  }
349
461
  if (msg.type === "patchApply") {
350
462
  const entry = idToEntry.get(msg.id);
351
- const writeGuardRoot = path.resolve(fromConfigFile || serverRoot);
463
+ const writeGuardRoot = path2.resolve(fromConfigFile || serverRoot);
352
464
  const dryRun = msg.dryRun === true;
353
465
  const patchAckExtras = dryRun ? { dryRun: true } : {};
354
466
  if (!entry) {
@@ -403,7 +515,7 @@ function nuvio(options) {
403
515
  return;
404
516
  }
405
517
  const result = await applyPatchToSource(source, entry.file, msg.id, msg.ops, {
406
- classNameMode,
518
+ classNameMode: resolvePatchClassNameMode(entry, classNameMode),
407
519
  activeBreakpoint: msg.activeBreakpoint
408
520
  });
409
521
  if (!result.ok) {
@@ -1,461 +1,8 @@
1
1
  import {
2
- buildSourceIndex,
3
- extractIdsFromSource,
4
- pathnameFromUpgradeUrl,
5
- pickBestSourceIndex,
6
- readRuntimeVersions
7
- } from "./chunk-KTNIIC2D.js";
8
-
9
- // src/nuvio-dev-session.ts
10
- import fs from "fs";
11
- import path from "path";
12
- import { watch } from "fs";
13
- import { WebSocket, WebSocketServer } from "ws";
14
- import { applyPatchToSource } from "@nuvio/ast-engine";
15
- import {
16
- NUVIO_WS_PATH,
17
- PROTOCOL_VERSION,
18
- parseClientMessage,
19
- serializeServerMessage
20
- } from "@nuvio/shared";
21
- import { assertPathWithinRoot } from "@nuvio/shared/secure-path";
22
- var APP_ENTRY_CANDIDATES = ["src/App.tsx", "src/app.tsx", "App.tsx"];
23
- var DEFAULT_GLOBS = [
24
- "src/**/*.{tsx,jsx}",
25
- "apps/**/src/**/*.{tsx,jsx}",
26
- "packages/**/src/**/*.{tsx,jsx}"
27
- ];
28
- function nuvioWsMessageToText(data) {
29
- if (typeof data === "string") {
30
- return data;
31
- }
32
- if (Buffer.isBuffer(data)) {
33
- return data.toString("utf8");
34
- }
35
- if (data instanceof ArrayBuffer) {
36
- return Buffer.from(data).toString("utf8");
37
- }
38
- if (ArrayBuffer.isView(data)) {
39
- const v = data;
40
- return Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("utf8");
41
- }
42
- return String(data);
43
- }
44
- function isAllowedOrigin(origin) {
45
- if (origin === void 0 || origin === "") {
46
- return true;
47
- }
48
- try {
49
- const u = new URL(origin);
50
- return (u.hostname === "localhost" || u.hostname === "127.0.0.1") && (u.protocol === "http:" || u.protocol === "https:");
51
- } catch {
52
- return false;
53
- }
54
- }
55
- function supplementIndexFromAppTsx(serverRoot, built, classNameMode, emitWarn) {
56
- if (built.entries.length > 0) {
57
- return built;
58
- }
59
- for (const rel of APP_ENTRY_CANDIDATES) {
60
- const appTsx = path.resolve(serverRoot, rel);
61
- if (!fs.existsSync(appTsx)) {
62
- continue;
63
- }
64
- try {
65
- const code = fs.readFileSync(appTsx, "utf8");
66
- const hits = extractIdsFromSource(appTsx, code, { classNameMode });
67
- if (hits.length === 0) {
68
- continue;
69
- }
70
- emitWarn(
71
- `[Nuvio] Source index had 0 ids; supplemented from ${appTsx} (${hits.length} id(s)).`
72
- );
73
- return {
74
- ...built,
75
- entries: hits,
76
- scannedFileCount: Math.max(built.scannedFileCount, 1)
77
- };
78
- } catch {
79
- }
80
- }
81
- return built;
82
- }
83
- function attachNuvioDevSession(httpServer, options) {
84
- const log = options.log ?? console;
85
- const enabled = options.enabled ?? process.env.NUVIO !== "0";
86
- const scanGlobs = options.scanGlobs ?? DEFAULT_GLOBS;
87
- const verbose = options.verbose ?? false;
88
- const classNameMode = options.classNameMode ?? "literal-only";
89
- const serverRoot = path.resolve(options.root);
90
- const fromConfigFile = options.configDir ?? "";
91
- const rootCandidates = [path.resolve(fromConfigFile || serverRoot), serverRoot, process.cwd()];
92
- const rootsLabel = [...new Set(rootCandidates)].join(" | ");
93
- let indexVersion = 0;
94
- let cachedIndexPayload = null;
95
- let runtimeDiagnostics = { overlayCssMode: "self-contained" };
96
- const idToEntry = /* @__PURE__ */ new Map();
97
- const wss = new WebSocketServer({ noServer: true });
98
- const undoStack = [];
99
- const UNDO_MAX = 32;
100
- const pushUndoSnapshot = (file, contents) => {
101
- undoStack.push({ file, contents });
102
- while (undoStack.length > UNDO_MAX) {
103
- undoStack.shift();
104
- }
105
- };
106
- const rebuildIndex = () => {
107
- if (!enabled) {
108
- return;
109
- }
110
- let built = pickBestSourceIndex(rootCandidates, scanGlobs, { classNameMode });
111
- built = supplementIndexFromAppTsx(serverRoot, built, classNameMode, log.warn);
112
- if (built.entries.length === 0) {
113
- const fallback = buildSourceIndex(serverRoot, ["src/**/*.{tsx,jsx}"], { classNameMode });
114
- if (fallback.entries.length > 0) {
115
- log.warn(
116
- `[Nuvio] Multi-root scan yielded 0 ids; using serverRoot-only index (${fallback.entries.length} id(s)).`
117
- );
118
- built = fallback;
119
- }
120
- }
121
- indexVersion += 1;
122
- idToEntry.clear();
123
- for (const e of built.entries) {
124
- idToEntry.set(e.id, e);
125
- }
126
- runtimeDiagnostics = {
127
- ...readRuntimeVersions(serverRoot),
128
- overlayCssMode: "self-contained"
129
- };
130
- cachedIndexPayload = serializeServerMessage({
131
- type: "indexReady",
132
- protocolVersion: PROTOCOL_VERSION,
133
- indexVersion,
134
- entries: built.entries,
135
- duplicateErrors: built.duplicateErrors,
136
- diagnostics: runtimeDiagnostics
137
- });
138
- if (verbose) {
139
- log.info(
140
- `[Nuvio] index roots=${rootsLabel} matchedFiles=${built.scannedFileCount} uniqueIds=${built.entries.length}`
141
- );
142
- } else {
143
- log.info(`[Nuvio] index \u2014 ${built.entries.length} id(s), ${built.scannedFileCount} file(s)`);
144
- }
145
- if (cachedIndexPayload && wss.clients.size > 0) {
146
- for (const client of wss.clients) {
147
- if (client.readyState === WebSocket.OPEN) {
148
- client.send(cachedIndexPayload);
149
- }
150
- }
151
- }
152
- };
153
- const debouncedRebuild = /* @__PURE__ */ (() => {
154
- let t;
155
- return () => {
156
- if (t) {
157
- clearTimeout(t);
158
- }
159
- t = setTimeout(() => {
160
- rebuildIndex();
161
- t = void 0;
162
- }, 120);
163
- };
164
- })();
165
- const srcDir = path.join(serverRoot, "src");
166
- let fileWatcher = null;
167
- if (enabled && fs.existsSync(srcDir)) {
168
- try {
169
- fileWatcher = watch(srcDir, { recursive: true }, (_event, filename) => {
170
- if (filename && /\.(tsx|jsx)$/.test(filename)) {
171
- debouncedRebuild();
172
- }
173
- });
174
- } catch {
175
- }
176
- }
177
- wss.on("connection", (ws) => {
178
- if (cachedIndexPayload && ws.readyState === WebSocket.OPEN) {
179
- ws.send(cachedIndexPayload);
180
- }
181
- ws.on("message", async (data) => {
182
- const text = nuvioWsMessageToText(data);
183
- const msg = parseClientMessage(text);
184
- if (!msg) {
185
- ws.send(
186
- serializeServerMessage({
187
- type: "error",
188
- code: "bad_message",
189
- message: "Invalid client message"
190
- })
191
- );
192
- return;
193
- }
194
- if (msg.protocolVersion !== PROTOCOL_VERSION) {
195
- ws.send(
196
- serializeServerMessage({
197
- type: "error",
198
- code: "bad_version",
199
- message: `Expected protocolVersion ${PROTOCOL_VERSION}`,
200
- requestId: "requestId" in msg ? msg.requestId : void 0
201
- })
202
- );
203
- return;
204
- }
205
- if (msg.type === "ping") {
206
- ws.send(
207
- serializeServerMessage({
208
- type: "pong",
209
- protocolVersion: PROTOCOL_VERSION,
210
- requestId: msg.requestId,
211
- diagnostics: runtimeDiagnostics
212
- })
213
- );
214
- if (cachedIndexPayload) {
215
- ws.send(cachedIndexPayload);
216
- }
217
- return;
218
- }
219
- if (msg.type === "select") {
220
- const entry = idToEntry.get(msg.id);
221
- if (!entry) {
222
- ws.send(
223
- serializeServerMessage({
224
- type: "selectAck",
225
- protocolVersion: PROTOCOL_VERSION,
226
- requestId: msg.requestId,
227
- id: msg.id,
228
- ok: false,
229
- errorCode: "unknown_id",
230
- errorMessage: "Id not found in dev source index"
231
- })
232
- );
233
- return;
234
- }
235
- ws.send(
236
- serializeServerMessage({
237
- type: "selectAck",
238
- protocolVersion: PROTOCOL_VERSION,
239
- requestId: msg.requestId,
240
- id: msg.id,
241
- ok: true,
242
- file: entry.file,
243
- line: entry.line,
244
- column: entry.column,
245
- patchHostId: entry.patchHostId,
246
- primaryTextTargetKey: entry.primaryTextTargetKey,
247
- textTargets: entry.textTargets,
248
- styleTargets: entry.styleTargets,
249
- hierarchyRole: entry.hierarchyRole,
250
- parentHostId: entry.parentHostId,
251
- childTargetIds: entry.childTargetIds,
252
- rowTargets: entry.rowTargets,
253
- tableMeta: entry.tableMeta,
254
- tableDataField: entry.tableDataField
255
- })
256
- );
257
- return;
258
- }
259
- if (msg.type === "patchUndo") {
260
- const writeGuardRoot = path.resolve(fromConfigFile || serverRoot);
261
- const last = undoStack.pop();
262
- if (!last) {
263
- ws.send(
264
- serializeServerMessage({
265
- type: "patchUndoAck",
266
- protocolVersion: PROTOCOL_VERSION,
267
- requestId: msg.requestId,
268
- ok: false,
269
- errorCode: "empty_stack",
270
- errorMessage: "Nothing to undo"
271
- })
272
- );
273
- return;
274
- }
275
- try {
276
- assertPathWithinRoot(writeGuardRoot, last.file);
277
- fs.writeFileSync(last.file, last.contents, "utf8");
278
- } catch (e) {
279
- undoStack.push(last);
280
- ws.send(
281
- serializeServerMessage({
282
- type: "patchUndoAck",
283
- protocolVersion: PROTOCOL_VERSION,
284
- requestId: msg.requestId,
285
- ok: false,
286
- errorCode: "undo_write_error",
287
- errorMessage: String(e)
288
- })
289
- );
290
- return;
291
- }
292
- ws.send(
293
- serializeServerMessage({
294
- type: "patchUndoAck",
295
- protocolVersion: PROTOCOL_VERSION,
296
- requestId: msg.requestId,
297
- ok: true,
298
- file: last.file,
299
- undoStackDepth: undoStack.length
300
- })
301
- );
302
- return;
303
- }
304
- if (msg.type === "patchApply") {
305
- const entry = idToEntry.get(msg.id);
306
- const writeGuardRoot = path.resolve(fromConfigFile || serverRoot);
307
- const dryRun = msg.dryRun === true;
308
- const patchAckExtras = dryRun ? { dryRun: true } : {};
309
- if (!entry) {
310
- ws.send(
311
- serializeServerMessage({
312
- type: "patchAck",
313
- protocolVersion: PROTOCOL_VERSION,
314
- requestId: msg.requestId,
315
- id: msg.id,
316
- ok: false,
317
- errorCode: "unknown_id",
318
- errorMessage: "Id not found in dev source index",
319
- ...patchAckExtras
320
- })
321
- );
322
- return;
323
- }
324
- try {
325
- assertPathWithinRoot(writeGuardRoot, entry.file);
326
- } catch (e) {
327
- ws.send(
328
- serializeServerMessage({
329
- type: "patchAck",
330
- protocolVersion: PROTOCOL_VERSION,
331
- requestId: msg.requestId,
332
- id: msg.id,
333
- ok: false,
334
- errorCode: "path_escape",
335
- errorMessage: String(e),
336
- ...patchAckExtras
337
- })
338
- );
339
- return;
340
- }
341
- let source;
342
- try {
343
- source = fs.readFileSync(entry.file, "utf8");
344
- } catch (e) {
345
- ws.send(
346
- serializeServerMessage({
347
- type: "patchAck",
348
- protocolVersion: PROTOCOL_VERSION,
349
- requestId: msg.requestId,
350
- id: msg.id,
351
- ok: false,
352
- errorCode: "read_error",
353
- errorMessage: String(e),
354
- ...patchAckExtras
355
- })
356
- );
357
- return;
358
- }
359
- const result = await applyPatchToSource(source, entry.file, msg.id, msg.ops, {
360
- classNameMode,
361
- activeBreakpoint: msg.activeBreakpoint
362
- });
363
- if (!result.ok) {
364
- ws.send(
365
- serializeServerMessage({
366
- type: "patchAck",
367
- protocolVersion: PROTOCOL_VERSION,
368
- requestId: msg.requestId,
369
- id: msg.id,
370
- ok: false,
371
- errorCode: result.code,
372
- errorMessage: result.message,
373
- ...patchAckExtras
374
- })
375
- );
376
- return;
377
- }
378
- if (dryRun) {
379
- ws.send(
380
- serializeServerMessage({
381
- type: "patchAck",
382
- protocolVersion: PROTOCOL_VERSION,
383
- requestId: msg.requestId,
384
- id: msg.id,
385
- ok: true,
386
- diffSummary: result.diffSummary,
387
- dryRun: true
388
- })
389
- );
390
- return;
391
- }
392
- try {
393
- fs.writeFileSync(entry.file, result.source, "utf8");
394
- } catch (e) {
395
- ws.send(
396
- serializeServerMessage({
397
- type: "patchAck",
398
- protocolVersion: PROTOCOL_VERSION,
399
- requestId: msg.requestId,
400
- id: msg.id,
401
- ok: false,
402
- errorCode: "write_error",
403
- errorMessage: String(e)
404
- })
405
- );
406
- return;
407
- }
408
- pushUndoSnapshot(entry.file, source);
409
- ws.send(
410
- serializeServerMessage({
411
- type: "patchAck",
412
- protocolVersion: PROTOCOL_VERSION,
413
- requestId: msg.requestId,
414
- id: msg.id,
415
- ok: true,
416
- diffSummary: result.diffSummary,
417
- writtenFile: entry.file,
418
- undoStackDepth: undoStack.length
419
- })
420
- );
421
- }
422
- });
423
- });
424
- const onUpgrade = (request, socket, head) => {
425
- if (!enabled) {
426
- return;
427
- }
428
- const pathname = pathnameFromUpgradeUrl(request.url);
429
- if (pathname !== NUVIO_WS_PATH) {
430
- return;
431
- }
432
- if (!isAllowedOrigin(request.headers.origin)) {
433
- socket.destroy();
434
- return;
435
- }
436
- wss.handleUpgrade(request, socket, head, (ws) => {
437
- wss.emit("connection", ws, request);
438
- });
439
- };
440
- httpServer.on("upgrade", onUpgrade);
441
- if (enabled) {
442
- log.info("[Nuvio] dev session attached (App Router / custom server mode)");
443
- rebuildIndex();
444
- } else {
445
- log.info("[Nuvio] disabled (set NUVIO=1 to enable)");
446
- }
447
- return {
448
- rebuildIndex,
449
- close: () => {
450
- httpServer.off("upgrade", onUpgrade);
451
- fileWatcher?.close();
452
- for (const client of wss.clients) {
453
- client.close();
454
- }
455
- wss.close();
456
- }
457
- };
458
- }
2
+ DEFAULT_GLOBS,
3
+ attachNuvioDevSession
4
+ } from "./chunk-EZGH3CUW.js";
5
+ import "./chunk-QAQAJG7B.js";
459
6
  export {
460
7
  DEFAULT_GLOBS as NUVIO_DEFAULT_SCAN_GLOBS,
461
8
  attachNuvioDevSession