@unlockable/vite-plugin-unlock 0.1.4 → 0.1.6

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,10 +1,10 @@
1
1
  // src/plugin.ts
2
- import path5 from "path";
3
- import fs4 from "fs";
2
+ import path6 from "path";
3
+ import fs5 from "fs";
4
4
 
5
5
  // src/config.ts
6
- import path from "path";
7
- import fs from "fs";
6
+ import path2 from "path";
7
+ import fs2 from "fs";
8
8
  import { createRequire } from "module";
9
9
 
10
10
  // src/constants.ts
@@ -24,6 +24,8 @@ var MAX_SCAN_DEPTH = 20;
24
24
  var PLUGIN_NAME = "vite-plugin-unlock";
25
25
 
26
26
  // src/utils.ts
27
+ import path from "path";
28
+ import fs from "fs";
27
29
  var PREFIX = `[${PLUGIN_NAME}]`;
28
30
  function createLogger(debug) {
29
31
  return {
@@ -49,33 +51,85 @@ function generateAlias(packageName) {
49
51
  const lastPart = parts[parts.length - 1];
50
52
  return `~${lastPart}`;
51
53
  }
54
+ function collectCjsDeps(packageDir) {
55
+ const pkgJsonPath = path.join(packageDir, "package.json");
56
+ if (!fs.existsSync(pkgJsonPath)) return [];
57
+ let pkgJson;
58
+ try {
59
+ pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
60
+ } catch {
61
+ return [];
62
+ }
63
+ const deps = pkgJson.dependencies;
64
+ if (!deps) return [];
65
+ const cjsDeps = [];
66
+ for (const depName of Object.keys(deps)) {
67
+ if (depName.startsWith("@types/")) continue;
68
+ const depParts = depName.startsWith("@") ? depName.split("/") : [depName];
69
+ const candidates = [
70
+ path.join(packageDir, "node_modules", ...depParts, "package.json"),
71
+ path.join(process.cwd(), "node_modules", ...depParts, "package.json")
72
+ ];
73
+ let depPkgJson = null;
74
+ for (const candidate of candidates) {
75
+ if (fs.existsSync(candidate)) {
76
+ try {
77
+ depPkgJson = JSON.parse(fs.readFileSync(candidate, "utf-8"));
78
+ } catch {
79
+ continue;
80
+ }
81
+ break;
82
+ }
83
+ }
84
+ if (!depPkgJson) continue;
85
+ if (depPkgJson.type === "module") continue;
86
+ if (!hasRootEntry(depPkgJson)) continue;
87
+ cjsDeps.push(depName);
88
+ }
89
+ return cjsDeps;
90
+ }
91
+ function hasRootEntry(pkgJson) {
92
+ const exports = pkgJson.exports;
93
+ if (exports !== void 0) {
94
+ if (exports === null) return false;
95
+ if (typeof exports === "string") return true;
96
+ if (typeof exports === "object" && !Array.isArray(exports)) {
97
+ return "." in exports;
98
+ }
99
+ return Array.isArray(exports);
100
+ }
101
+ if (pkgJson.main || pkgJson.module) return true;
102
+ return false;
103
+ }
52
104
 
53
105
  // src/config.ts
54
106
  function findPackageSrcPath(packageName, srcDir) {
55
107
  const cwd = process.cwd();
56
108
  try {
57
- const req = createRequire(path.join(cwd, "package.json"));
58
- const pkgJsonPath = req.resolve(`${packageName}/package.json`);
59
- const pkgRoot = path.dirname(pkgJsonPath);
60
- const srcPath = path.join(pkgRoot, srcDir);
61
- if (fs.existsSync(srcPath)) return srcPath;
109
+ const req = createRequire(path2.join(cwd, "package.json"));
110
+ const pkgJsonPath = fs2.realpathSync(
111
+ req.resolve(`${packageName}/package.json`)
112
+ );
113
+ const pkgRoot = path2.dirname(pkgJsonPath);
114
+ const srcPath = path2.join(pkgRoot, srcDir);
115
+ if (fs2.existsSync(srcPath)) return srcPath;
62
116
  return pkgRoot;
63
117
  } catch {
64
118
  }
65
119
  const parts = packageName.startsWith("@") ? packageName.split("/") : [packageName];
66
120
  const candidates = [
67
- path.join(cwd, "node_modules", ...parts, srcDir),
68
- path.join(cwd, ".yalc", ...parts, srcDir)
121
+ path2.join(cwd, "node_modules", ...parts, srcDir),
122
+ path2.join(cwd, ".yalc", ...parts, srcDir)
69
123
  ];
70
124
  for (const dir of candidates) {
71
- if (fs.existsSync(dir)) return dir;
125
+ if (fs2.existsSync(dir)) return fs2.realpathSync(dir);
72
126
  }
73
127
  const rootCandidates = [
74
- path.join(cwd, "node_modules", ...parts),
75
- path.join(cwd, ".yalc", ...parts)
128
+ path2.join(cwd, "node_modules", ...parts),
129
+ path2.join(cwd, ".yalc", ...parts)
76
130
  ];
77
131
  for (const dir of rootCandidates) {
78
- if (fs.existsSync(dir)) return dir;
132
+ if (fs2.existsSync(dir)) return fs2.realpathSync(dir);
79
133
  }
80
134
  return null;
81
135
  }
@@ -84,22 +138,24 @@ function resolveTarget(input) {
84
138
  package: input,
85
139
  alias: generateAlias(input),
86
140
  srcDir: DEFAULT_SRC_DIR,
87
- srcPath: ""
141
+ srcPath: "",
142
+ packageDir: ""
88
143
  } : {
89
144
  package: input.package,
90
145
  alias: input.alias ?? generateAlias(input.package),
91
146
  srcDir: input.srcDir ?? DEFAULT_SRC_DIR,
92
147
  srcPath: "",
148
+ packageDir: "",
93
149
  entryRedirect: input.entryRedirect,
94
150
  hmr: input.hmr
95
151
  };
96
152
  const srcPath = findPackageSrcPath(target.package, target.srcDir);
97
153
  if (!srcPath) return null;
98
154
  target.srcPath = srcPath;
155
+ target.packageDir = srcPath.endsWith(path2.sep + target.srcDir) ? path2.resolve(srcPath, "..") : srcPath;
99
156
  if (target.entryRedirect && target.hmr) {
100
- const pkgDir = path.dirname(srcPath);
101
- const entryFile = path.resolve(pkgDir, target.entryRedirect.to);
102
- if (fs.existsSync(entryFile)) {
157
+ const entryFile = path2.resolve(target.packageDir, target.entryRedirect.to);
158
+ if (fs2.existsSync(entryFile)) {
103
159
  target.entryFilePath = entryFile;
104
160
  }
105
161
  }
@@ -109,8 +165,8 @@ var CONFIG_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
109
165
  function findConfigFile(basename, overrideDirs) {
110
166
  for (const dir of overrideDirs) {
111
167
  for (const ext of CONFIG_EXTENSIONS) {
112
- const p = path.resolve(dir, `${basename}${ext}`);
113
- if (fs.existsSync(p)) return p;
168
+ const p = path2.resolve(dir, `${basename}${ext}`);
169
+ if (fs2.existsSync(p)) return p;
114
170
  }
115
171
  }
116
172
  return null;
@@ -118,7 +174,7 @@ function findConfigFile(basename, overrideDirs) {
118
174
  function resolveOptions(options) {
119
175
  const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
120
176
  const overrideInput = options.overrides ?? DEFAULT_OVERRIDE_DIR;
121
- const overrideDirs = (Array.isArray(overrideInput) ? overrideInput : [overrideInput]).map((dir) => path.resolve(process.cwd(), dir));
177
+ const overrideDirs = (Array.isArray(overrideInput) ? overrideInput : [overrideInput]).map((dir) => path2.resolve(process.cwd(), dir));
122
178
  const targets = [];
123
179
  for (const input of options.targets) {
124
180
  const resolved = resolveTarget(input);
@@ -141,29 +197,33 @@ function resolveOptions(options) {
141
197
  extensions,
142
198
  extensionSet: new Set(extensions),
143
199
  patches,
144
- hmrBoundaries: options.hmrBoundaries ?? []
200
+ hmrBoundaries: options.hmrBoundaries ?? [],
201
+ optimizeDeps: {
202
+ include: options.optimizeDeps?.include ?? []
203
+ },
204
+ autoOptimizeDeps: options.autoOptimizeDeps ?? true
145
205
  };
146
206
  }
147
207
 
148
208
  // src/scanner.ts
149
- import path2 from "path";
150
- import fs2 from "fs";
209
+ import path3 from "path";
210
+ import fs3 from "fs";
151
211
  function collectFiles(dir, extensionSet, depth = 0) {
152
212
  if (depth > MAX_SCAN_DEPTH) return [];
153
213
  const results = [];
154
214
  let entries;
155
215
  try {
156
- entries = fs2.readdirSync(dir, { withFileTypes: true });
216
+ entries = fs3.readdirSync(dir, { withFileTypes: true });
157
217
  } catch {
158
218
  return results;
159
219
  }
160
220
  for (const entry of entries) {
161
221
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
162
- const fullPath = path2.resolve(dir, entry.name);
222
+ const fullPath = path3.resolve(dir, entry.name);
163
223
  if (entry.isDirectory()) {
164
224
  results.push(...collectFiles(fullPath, extensionSet, depth + 1));
165
225
  } else if (entry.isFile()) {
166
- const ext = path2.extname(entry.name);
226
+ const ext = path3.extname(entry.name);
167
227
  if (extensionSet.has(ext)) {
168
228
  results.push(fullPath);
169
229
  }
@@ -181,7 +241,7 @@ function getOverrideKey(filePath, baseDir, match) {
181
241
  if (match === "path") {
182
242
  const normalizedBase = normalizePath(baseDir);
183
243
  const relative = normalizePath(
184
- path2.relative(normalizedBase, normalized)
244
+ path3.relative(normalizedBase, normalized)
185
245
  );
186
246
  return stripExtension(relative);
187
247
  }
@@ -212,7 +272,7 @@ function scanAllTargets(opts, logger) {
212
272
  return combined;
213
273
  }
214
274
  function detectNamespace(filePath, overrideDir) {
215
- const relative = normalizePath(path2.relative(overrideDir, filePath));
275
+ const relative = normalizePath(path3.relative(overrideDir, filePath));
216
276
  const scopedMatch = relative.match(/^(@[^/]+\/[^/]+)\//);
217
277
  if (scopedMatch) return scopedMatch[1];
218
278
  return null;
@@ -222,13 +282,13 @@ function scanOverrides(opts, logger) {
222
282
  const namespaced = /* @__PURE__ */ new Map();
223
283
  const targetPackages = new Set(opts.targets.map((t) => t.package));
224
284
  for (const dir of opts.overrideDirs) {
225
- if (!fs2.existsSync(dir)) continue;
285
+ if (!fs3.existsSync(dir)) continue;
226
286
  for (const fullPath of collectFiles(dir, opts.extensionSet).sort()) {
227
- const relative = normalizePath(path2.relative(dir, fullPath));
287
+ const relative = normalizePath(path3.relative(dir, fullPath));
228
288
  if (relative.split("/").some((part) => part.startsWith("_"))) continue;
229
289
  const ns = detectNamespace(fullPath, dir);
230
290
  if (ns && targetPackages.has(ns)) {
231
- const nsDir = path2.join(dir, ns);
291
+ const nsDir = path3.join(dir, ns);
232
292
  const key = getOverrideKey(fullPath, nsDir, opts.match);
233
293
  if (key && key !== "index") {
234
294
  if (!namespaced.has(ns)) namespaced.set(ns, /* @__PURE__ */ new Map());
@@ -248,8 +308,8 @@ function scanOverrides(opts, logger) {
248
308
  }
249
309
 
250
310
  // src/resolver.ts
251
- import path3 from "path";
252
- import fs3 from "fs";
311
+ import path4 from "path";
312
+ import fs4 from "fs";
253
313
  function findImporterTarget(importer, opts) {
254
314
  const norm = normalizePath(importer);
255
315
  for (const target of opts.targets) {
@@ -257,7 +317,7 @@ function findImporterTarget(importer, opts) {
257
317
  if (norm.startsWith(normSrc + "/") || norm === normSrc) {
258
318
  return target;
259
319
  }
260
- const pkgDir = normalizePath(path3.dirname(target.srcPath));
320
+ const pkgDir = normalizePath(path4.dirname(target.srcPath));
261
321
  if (norm.startsWith(pkgDir + "/")) {
262
322
  return target;
263
323
  }
@@ -270,11 +330,11 @@ function resolveEntryRedirect(resolvedId, opts, logger) {
270
330
  if (target.entryRedirect) {
271
331
  const fromPattern = normalizePath(target.entryRedirect.from);
272
332
  if (norm.endsWith(`/${fromPattern}`) || norm.includes(`/${fromPattern}`)) {
273
- const pkgDir = path3.dirname(target.srcPath);
274
- const srcEntry = path3.join(pkgDir, target.entryRedirect.to);
275
- if (fs3.existsSync(srcEntry)) {
333
+ const pkgDir = path4.dirname(target.srcPath);
334
+ const srcEntry = path4.join(pkgDir, target.entryRedirect.to);
335
+ if (fs4.existsSync(srcEntry)) {
276
336
  logger.info(
277
- `Entry redirect: ${path3.basename(resolvedId)} -> ${target.entryRedirect.to}`
337
+ `Entry redirect: ${path4.basename(resolvedId)} -> ${target.entryRedirect.to}`
278
338
  );
279
339
  return srcEntry;
280
340
  }
@@ -288,7 +348,7 @@ function resolveEntryRedirect(resolvedId, opts, logger) {
288
348
  /\/dist\/app\.(mjs|js)$/,
289
349
  "/src/app.tsx"
290
350
  );
291
- if (fs3.existsSync(srcEntry)) {
351
+ if (fs4.existsSync(srcEntry)) {
292
352
  logger.info(`Entry redirect (auto): dist/app -> src/app.tsx`);
293
353
  return srcEntry;
294
354
  }
@@ -299,11 +359,11 @@ function resolveEntryRedirect(resolvedId, opts, logger) {
299
359
  }
300
360
 
301
361
  // src/watcher.ts
302
- import path4 from "path";
362
+ import path5 from "path";
303
363
  function setupWatcher(server, state, opts, logger) {
304
364
  let debounceTimer = null;
305
365
  const handleStructuralChange = (filePath) => {
306
- const ext = path4.extname(filePath);
366
+ const ext = path5.extname(filePath);
307
367
  if (!opts.extensionSet.has(ext)) return;
308
368
  const normFile = normalizePath(filePath);
309
369
  const isOverrideFile = opts.overrideDirs.some(
@@ -369,14 +429,14 @@ function setupWatcher(server, state, opts, logger) {
369
429
  server.watcher.on("add", handleStructuralChange);
370
430
  server.watcher.on("unlink", handleStructuralChange);
371
431
  server.watcher.on("change", (filePath) => {
372
- const ext = path4.extname(filePath);
432
+ const ext = path5.extname(filePath);
373
433
  if (!opts.extensionSet.has(ext)) return;
374
434
  const normFile = normalizePath(filePath);
375
435
  const isOverrideFile = opts.overrideDirs.some(
376
436
  (dir) => normFile.startsWith(normalizePath(dir) + "/")
377
437
  );
378
438
  if (!isOverrideFile) return;
379
- const basename = stripExtension(path4.basename(filePath));
439
+ const basename = stripExtension(path5.basename(filePath));
380
440
  if (!basename) return;
381
441
  const isTrackedOverride = state.flatOverrides.has(basename) || [...state.namespacedOverrides.values()].some((m) => m.has(basename));
382
442
  if (!isTrackedOverride) return;
@@ -398,7 +458,7 @@ function setupWatcher(server, state, opts, logger) {
398
458
  });
399
459
  if (opts.patches.length > 0) {
400
460
  const handlePatchConfigStructural = (filePath) => {
401
- const basename = stripExtension(path4.basename(filePath));
461
+ const basename = stripExtension(path5.basename(filePath));
402
462
  if (!basename) return;
403
463
  const normFile = normalizePath(filePath);
404
464
  const isOverrideFile = opts.overrideDirs.some(
@@ -446,7 +506,7 @@ function invalidatePatchTarget(patch, server, logger) {
446
506
  if (mod.file && patch.target.test(normalizePath(mod.file))) {
447
507
  moduleGraph.invalidateModule(mod, /* @__PURE__ */ new Set(), timestamp, true);
448
508
  roots.add(mod);
449
- logger.info(`Invalidated patch target: ${path4.basename(mod.file)}`);
509
+ logger.info(`Invalidated patch target: ${path5.basename(mod.file)}`);
450
510
  }
451
511
  }
452
512
  const seen = /* @__PURE__ */ new Set();
@@ -555,6 +615,7 @@ function unlock(userOptions) {
555
615
  logger.info(`Patch: ${patch.configFile} (no config file found)`);
556
616
  }
557
617
  }
618
+ let hasExternalReactPlugin = false;
558
619
  return {
559
620
  name: PLUGIN_NAME,
560
621
  enforce: "pre",
@@ -563,7 +624,7 @@ function unlock(userOptions) {
563
624
  config.server.fs = config.server.fs || {};
564
625
  config.server.fs.allow = config.server.fs.allow || [];
565
626
  for (const dir of opts.overrideDirs) {
566
- config.server.fs.allow.push(path5.resolve(dir));
627
+ config.server.fs.allow.push(path6.resolve(dir));
567
628
  }
568
629
  config.optimizeDeps = config.optimizeDeps || {};
569
630
  config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
@@ -575,6 +636,30 @@ function unlock(userOptions) {
575
636
  );
576
637
  }
577
638
  }
639
+ if (opts.autoOptimizeDeps) {
640
+ const autoDeps = [];
641
+ for (const target of opts.targets) {
642
+ const cjsDeps = collectCjsDeps(target.packageDir);
643
+ for (const dep of cjsDeps) {
644
+ if (opts.targets.some((t) => t.package === dep)) continue;
645
+ if (!autoDeps.includes(dep)) autoDeps.push(dep);
646
+ }
647
+ }
648
+ if (autoDeps.length > 0) {
649
+ config.optimizeDeps.include = config.optimizeDeps.include || [];
650
+ config.optimizeDeps.include.push(...autoDeps);
651
+ logger.info(
652
+ `Auto-included ${autoDeps.length} CJS deps for pre-bundling`
653
+ );
654
+ }
655
+ }
656
+ if (opts.optimizeDeps.include.length > 0) {
657
+ config.optimizeDeps.include = config.optimizeDeps.include || [];
658
+ config.optimizeDeps.include.push(...opts.optimizeDeps.include);
659
+ }
660
+ if (config.optimizeDeps.include) {
661
+ config.optimizeDeps.include = [...new Set(config.optimizeDeps.include)];
662
+ }
578
663
  config.resolve = config.resolve || {};
579
664
  config.resolve.alias = config.resolve.alias || {};
580
665
  for (const target of opts.targets) {
@@ -589,8 +674,8 @@ function unlock(userOptions) {
589
674
  }
590
675
  }
591
676
  for (const target of opts.targets) {
592
- const entryFile = path5.join(target.srcPath, "app.tsx");
593
- if (fs4.existsSync(entryFile)) {
677
+ const entryFile = path6.join(target.srcPath, "app.tsx");
678
+ if (fs5.existsSync(entryFile)) {
594
679
  const existing = config.optimizeDeps.entries;
595
680
  if (Array.isArray(existing)) {
596
681
  existing.push(entryFile);
@@ -602,24 +687,34 @@ function unlock(userOptions) {
602
687
  }
603
688
  }
604
689
  },
690
+ configResolved(resolvedConfig) {
691
+ hasExternalReactPlugin = resolvedConfig.plugins.some(
692
+ (p) => p.name === "vite:react-babel" || p.name === "vite:react-swc" || p.name === "vite:react-refresh"
693
+ );
694
+ if (hasExternalReactPlugin) {
695
+ logger.info(
696
+ "React plugin detected \u2014 handing over HMR to React Fast Refresh"
697
+ );
698
+ }
699
+ },
605
700
  async resolveId(source, importer) {
606
701
  if (source.startsWith("\0") || !importer || importer.startsWith("\0"))
607
702
  return null;
608
703
  const target = findImporterTarget(importer, opts);
609
704
  if (target) {
610
- const basename = stripExtension(path5.basename(source));
705
+ const basename = stripExtension(path6.basename(source));
611
706
  if (basename && basename !== "index") {
612
707
  const nsOverrides = state.namespacedOverrides.get(target.package);
613
708
  if (nsOverrides?.has(basename)) {
614
709
  const p = nsOverrides.get(basename);
615
710
  logger.info(
616
- `Override [${target.package}]: ${basename} -> ${path5.basename(p)}`
711
+ `Override [${target.package}]: ${basename} -> ${path6.basename(p)}`
617
712
  );
618
713
  return p;
619
714
  }
620
715
  if (state.flatOverrides.has(basename)) {
621
716
  const p = state.flatOverrides.get(basename);
622
- logger.info(`Override: ${basename} -> ${path5.basename(p)}`);
717
+ logger.info(`Override: ${basename} -> ${path6.basename(p)}`);
623
718
  return p;
624
719
  }
625
720
  }
@@ -654,15 +749,15 @@ function unlock(userOptions) {
654
749
  load(id) {
655
750
  const target = findImporterTarget(id, opts);
656
751
  if (!target) return null;
657
- const basename = stripExtension(path5.basename(id));
752
+ const basename = stripExtension(path6.basename(id));
658
753
  if (!basename || basename === "index") return null;
659
754
  const nsOverrides = state.namespacedOverrides.get(target.package);
660
755
  const overridePath = nsOverrides?.get(basename) ?? state.flatOverrides.get(basename);
661
- if (overridePath && fs4.existsSync(overridePath)) {
756
+ if (overridePath && fs5.existsSync(overridePath)) {
662
757
  this.addWatchFile(overridePath);
663
758
  const normalizedPath = normalizePath(overridePath).replace(/"/g, '\\"');
664
759
  logger.info(
665
- `Load override: ${basename} -> ${path5.basename(overridePath)}`
760
+ `Load override: ${basename} -> ${path6.basename(overridePath)}`
666
761
  );
667
762
  return `export { default } from "${normalizedPath}"
668
763
  export * from "${normalizedPath}"`;
@@ -670,18 +765,18 @@ export * from "${normalizedPath}"`;
670
765
  const normalizedId = normalizePath(id);
671
766
  for (const patch of opts.patches) {
672
767
  if (!patch.target.test(normalizedId)) continue;
673
- if (!patch.configPath || !fs4.existsSync(patch.configPath)) continue;
768
+ if (!patch.configPath || !fs5.existsSync(patch.configPath)) continue;
674
769
  this.addWatchFile(patch.configPath);
675
770
  let original;
676
771
  try {
677
- original = fs4.readFileSync(id, "utf-8");
772
+ original = fs5.readFileSync(id, "utf-8");
678
773
  } catch (err) {
679
774
  logger.error(`Failed to read file for patching: ${id}`);
680
775
  return null;
681
776
  }
682
777
  const patched = patch.apply(original, patch.configPath);
683
778
  logger.info(
684
- `Patch applied: ${path5.basename(id)} via ${patch.configFile}`
779
+ `Patch applied: ${path6.basename(id)} via ${patch.configFile}`
685
780
  );
686
781
  return { code: patched, map: null };
687
782
  }
@@ -712,7 +807,7 @@ export * from "${normalizedPath}"`;
712
807
  }
713
808
  if (modified) return { code, map: null };
714
809
  }
715
- if (opts.hmrBoundaries.length > 0) {
810
+ if (!hasExternalReactPlugin && opts.hmrBoundaries.length > 0) {
716
811
  const normId = normalizePath(id);
717
812
  if (!normId.includes("/node_modules/")) {
718
813
  const needsBoundary = opts.hmrBoundaries.some(
@@ -720,7 +815,7 @@ export * from "${normalizedPath}"`;
720
815
  );
721
816
  if (needsBoundary) {
722
817
  logger.info(
723
- `HMR boundary injected: ${path5.basename(id)}`
818
+ `HMR boundary injected: ${path6.basename(id)}`
724
819
  );
725
820
  return {
726
821
  code: code + "\nif (import.meta.hot) { import.meta.hot.accept() }",
@@ -735,7 +830,7 @@ export * from "${normalizedPath}"`;
735
830
  const fsConfig = server.config.server?.fs;
736
831
  if (fsConfig && Array.isArray(fsConfig.allow)) {
737
832
  for (const dir of opts.overrideDirs) {
738
- const resolved = path5.resolve(dir);
833
+ const resolved = path6.resolve(dir);
739
834
  if (!fsConfig.allow.includes(resolved)) {
740
835
  fsConfig.allow.push(resolved);
741
836
  }