@inspecto-dev/plugin 0.3.3 → 0.3.5

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 (39) hide show
  1. package/dist/index.cjs +180 -45
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +179 -44
  4. package/dist/index.js.map +1 -1
  5. package/dist/legacy/rspack/index.cjs +109 -19
  6. package/dist/legacy/rspack/index.cjs.map +1 -1
  7. package/dist/legacy/rspack/index.js +109 -19
  8. package/dist/legacy/rspack/index.js.map +1 -1
  9. package/dist/legacy/rspack/loader.cjs +49 -4
  10. package/dist/legacy/rspack/loader.cjs.map +1 -1
  11. package/dist/legacy/rspack/loader.js +49 -4
  12. package/dist/legacy/rspack/loader.js.map +1 -1
  13. package/dist/legacy/webpack4/index.cjs +121 -21
  14. package/dist/legacy/webpack4/index.cjs.map +1 -1
  15. package/dist/legacy/webpack4/index.d.cts +2 -0
  16. package/dist/legacy/webpack4/index.d.ts +2 -0
  17. package/dist/legacy/webpack4/index.js +121 -21
  18. package/dist/legacy/webpack4/index.js.map +1 -1
  19. package/dist/legacy/webpack4/loader.cjs +49 -4
  20. package/dist/legacy/webpack4/loader.cjs.map +1 -1
  21. package/dist/legacy/webpack4/loader.js +49 -4
  22. package/dist/legacy/webpack4/loader.js.map +1 -1
  23. package/dist/rollup.cjs +180 -45
  24. package/dist/rollup.cjs.map +1 -1
  25. package/dist/rollup.js +179 -44
  26. package/dist/rollup.js.map +1 -1
  27. package/dist/rspack.cjs +180 -45
  28. package/dist/rspack.cjs.map +1 -1
  29. package/dist/rspack.js +179 -44
  30. package/dist/rspack.js.map +1 -1
  31. package/dist/vite.cjs +180 -45
  32. package/dist/vite.cjs.map +1 -1
  33. package/dist/vite.js +179 -44
  34. package/dist/vite.js.map +1 -1
  35. package/dist/webpack.cjs +180 -45
  36. package/dist/webpack.cjs.map +1 -1
  37. package/dist/webpack.js +179 -44
  38. package/dist/webpack.js.map +1 -1
  39. package/package.json +6 -6
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
- // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.8_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js
8
+ // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.9_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/esm_shims.js
9
9
  import path from "path";
10
10
  import { fileURLToPath } from "url";
11
11
  var getFilename = () => fileURLToPath(import.meta.url);
@@ -45,7 +45,7 @@ var resolveClientModule = () => {
45
45
 
46
46
  // src/server/index.ts
47
47
  import http from "http";
48
- import fs4 from "fs";
48
+ import fs5 from "fs";
49
49
  import path6 from "path";
50
50
  import os2 from "os";
51
51
  import crypto2 from "crypto";
@@ -569,6 +569,7 @@ function hasOverrides(overrides) {
569
569
 
570
570
  // src/server/path-guards.ts
571
571
  import path4 from "path";
572
+ import fs3 from "fs";
572
573
  function isWindowsAbsolutePath(file) {
573
574
  return /^[a-zA-Z]:[\\/]/.test(file) || /^\\\\[^\\]+\\[^\\]+/.test(file);
574
575
  }
@@ -579,9 +580,94 @@ function resolveWorkspacePath(file, cwd) {
579
580
  return path4.isAbsolute(file) ? path4.resolve(file) : path4.resolve(cwd, file);
580
581
  }
581
582
  function assertPathWithinProject(file, projectRoot) {
582
- const relativeToRoot = isWindowsAbsolutePath(file) || isWindowsAbsolutePath(projectRoot) ? path4.win32.relative(path4.win32.normalize(projectRoot), path4.win32.normalize(file)) : path4.relative(projectRoot, file);
583
- if (relativeToRoot.startsWith("..") || path4.isAbsolute(relativeToRoot)) {
584
- throw new Error("Access denied: File is outside of project workspace");
583
+ let realFile = file;
584
+ let realProjectRoot = projectRoot;
585
+ try {
586
+ if (fs3.existsSync(file)) {
587
+ realFile = fs3.realpathSync(file);
588
+ }
589
+ } catch {
590
+ }
591
+ try {
592
+ if (fs3.existsSync(projectRoot)) {
593
+ realProjectRoot = fs3.realpathSync(projectRoot);
594
+ }
595
+ } catch {
596
+ }
597
+ if (isWithinPath(file, projectRoot) || isWithinPath(realFile, realProjectRoot)) {
598
+ return;
599
+ }
600
+ throw new Error(
601
+ `Access denied: File ${normalizeForComparison(realFile)} is outside of project workspace ${normalizeForComparison(realProjectRoot)}`
602
+ );
603
+ }
604
+ function tryReadPackageName(packageRoot) {
605
+ try {
606
+ const packageJsonPath = path4.join(packageRoot, "package.json");
607
+ if (!fs3.existsSync(packageJsonPath)) return void 0;
608
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
609
+ return typeof packageJson.name === "string" ? packageJson.name : void 0;
610
+ } catch {
611
+ return void 0;
612
+ }
613
+ }
614
+ function findNearestPackageRoot(file) {
615
+ let current = path4.dirname(file);
616
+ while (true) {
617
+ if (fs3.existsSync(path4.join(current, "package.json"))) {
618
+ return current;
619
+ }
620
+ const parent = path4.dirname(current);
621
+ if (parent === current) {
622
+ return void 0;
623
+ }
624
+ current = parent;
625
+ }
626
+ }
627
+ function normalizeForComparison(file) {
628
+ return isWindowsAbsolutePath(file) ? path4.win32.normalize(file) : path4.normalize(file);
629
+ }
630
+ function pathSeparatorFor(file) {
631
+ return isWindowsAbsolutePath(file) ? path4.win32.sep : path4.sep;
632
+ }
633
+ function isWithinPath(file, root) {
634
+ const normalizedFile = normalizeForComparison(file);
635
+ const normalizedRoot = normalizeForComparison(root);
636
+ const separator = pathSeparatorFor(normalizedRoot);
637
+ const rootWithSep = normalizedRoot.endsWith(separator) ? normalizedRoot : normalizedRoot + separator;
638
+ return normalizedFile === normalizedRoot || normalizedFile.startsWith(rootWithSep);
639
+ }
640
+ function resolveLinkedDependencyEntry(projectRoot, packageName) {
641
+ const packageSegments = packageName.split("/");
642
+ const dependencyPath = path4.join(projectRoot, "node_modules", ...packageSegments);
643
+ if (!fs3.existsSync(dependencyPath)) return void 0;
644
+ try {
645
+ return fs3.realpathSync(dependencyPath);
646
+ } catch {
647
+ return dependencyPath;
648
+ }
649
+ }
650
+ function isLinkedDependencyPath(file, projectRoot, packageName) {
651
+ const linkedDependencyRoot = resolveLinkedDependencyEntry(projectRoot, packageName);
652
+ if (!linkedDependencyRoot) return false;
653
+ return isWithinPath(file, linkedDependencyRoot);
654
+ }
655
+ function isLinkedDependencySourcePath(file, projectRoot) {
656
+ const packageRoot = findNearestPackageRoot(file);
657
+ if (!packageRoot) return false;
658
+ const packageName = tryReadPackageName(packageRoot);
659
+ if (!packageName) return false;
660
+ return isLinkedDependencyPath(file, projectRoot, packageName);
661
+ }
662
+ function assertPathWithinIdeOpenScope(file, projectRoot) {
663
+ try {
664
+ assertPathWithinProject(file, projectRoot);
665
+ return;
666
+ } catch {
667
+ if (isLinkedDependencySourcePath(file, projectRoot)) {
668
+ return;
669
+ }
670
+ throw new Error(`Access denied: File is outside of project workspace`);
585
671
  }
586
672
  }
587
673
 
@@ -786,7 +872,7 @@ var VSCODE_FAMILY_SCHEMES = [
786
872
  ];
787
873
  function handleOpenFileRequest(body, serverState2) {
788
874
  const absolutePath = resolveWorkspacePath(body.file, serverState2.cwd);
789
- assertPathWithinProject(absolutePath, serverState2.projectRoot);
875
+ assertPathWithinIdeOpenScope(absolutePath, serverState2.projectRoot);
790
876
  const userConfig = loadUserConfigSync(false, serverState2.cwd, serverState2.configRoot);
791
877
  const configuredIde = userConfig.ide;
792
878
  const activeIde = serverState2.ideInfo?.ide;
@@ -844,7 +930,7 @@ function handleOpenFileRequest(body, serverState2) {
844
930
  }
845
931
 
846
932
  // src/server/project-root.ts
847
- import fs3 from "fs";
933
+ import fs4 from "fs";
848
934
  import path5 from "path";
849
935
  import { execSync } from "child_process";
850
936
  var serverLogger3 = createLogger("inspecto:server", { logLevel: getGlobalLogLevel() });
@@ -862,7 +948,7 @@ function resolveProjectRoot() {
862
948
  let current = start;
863
949
  while (!visited.has(current)) {
864
950
  visited.add(current);
865
- if (fs3.existsSync(path5.join(current, ".inspecto"))) return current;
951
+ if (fs4.existsSync(path5.join(current, ".inspecto"))) return current;
866
952
  if (current === stop) break;
867
953
  const parent = path5.dirname(current);
868
954
  if (parent === current) break;
@@ -934,28 +1020,28 @@ async function startServer() {
934
1020
  const portFile = path6.join(os2.tmpdir(), "inspecto.port.json");
935
1021
  try {
936
1022
  let portData = {};
937
- if (fs4.existsSync(portFile)) {
1023
+ if (fs5.existsSync(portFile)) {
938
1024
  try {
939
- portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
1025
+ portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
940
1026
  } catch (e) {
941
1027
  }
942
1028
  }
943
1029
  const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
944
1030
  portData[rootHash] = port;
945
- fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1031
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
946
1032
  } catch (e) {
947
1033
  serverLogger4.warn("Failed to write port file:", e);
948
1034
  }
949
1035
  process.once("exit", () => {
950
1036
  try {
951
- if (fs4.existsSync(portFile)) {
952
- const portData = JSON.parse(fs4.readFileSync(portFile, "utf-8"));
1037
+ if (fs5.existsSync(portFile)) {
1038
+ const portData = JSON.parse(fs5.readFileSync(portFile, "utf-8"));
953
1039
  const rootHash = crypto2.createHash("md5").update(serverState.projectRoot).digest("hex");
954
1040
  delete portData[rootHash];
955
1041
  if (Object.keys(portData).length === 0) {
956
- fs4.unlinkSync(portFile);
1042
+ fs5.unlinkSync(portFile);
957
1043
  } else {
958
- fs4.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
1044
+ fs5.writeFileSync(portFile, JSON.stringify(portData, null, 2), "utf-8");
959
1045
  }
960
1046
  }
961
1047
  } catch {
@@ -1024,8 +1110,10 @@ async function handleRequest(url, req, res) {
1024
1110
  }
1025
1111
  try {
1026
1112
  handleOpenFileRequest(body, serverState);
1027
- } catch {
1028
- serverLogger4.warn(`Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}`);
1113
+ } catch (err) {
1114
+ serverLogger4.warn(
1115
+ `Security: Blocked path traversal attempt in IDE_OPEN: ${body.file}. Reason: ${err.message}`
1116
+ );
1029
1117
  res.writeHead(403, { "Content-Type": "application/json" });
1030
1118
  res.end(JSON.stringify({ error: "Access denied: File is outside of project workspace" }));
1031
1119
  return;
@@ -1043,8 +1131,10 @@ async function handleRequest(url, req, res) {
1043
1131
  const absolutePath = resolveWorkspacePath(file, serverState.cwd);
1044
1132
  try {
1045
1133
  assertPathWithinProject(absolutePath, serverState.projectRoot);
1046
- } catch {
1047
- serverLogger4.warn(`Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}`);
1134
+ } catch (err) {
1135
+ serverLogger4.warn(
1136
+ `Security: Blocked path traversal attempt in PROJECT_SNIPPET: ${file}. Reason: ${err.message}`
1137
+ );
1048
1138
  res.writeHead(403, { "Content-Type": "application/json" });
1049
1139
  res.end(
1050
1140
  JSON.stringify({
@@ -1140,10 +1230,20 @@ function getBatchDispatchStatusCode(errorCode, success) {
1140
1230
  import path7 from "path";
1141
1231
  var InspectoWebpack4Plugin = class {
1142
1232
  constructor(options = {}) {
1233
+ this.serverPort = null;
1143
1234
  this.options = options;
1144
1235
  }
1236
+ async ensureServer() {
1237
+ if (this.serverPort === null) {
1238
+ this.serverPort = await startServer();
1239
+ }
1240
+ return this.serverPort;
1241
+ }
1145
1242
  apply(compiler) {
1146
1243
  const clientPath = resolveClientModule();
1244
+ compiler.hooks.beforeCompile.tapPromise("InspectoWebpack4Plugin", async () => {
1245
+ await this.ensureServer();
1246
+ });
1147
1247
  compiler.hooks.afterEnvironment.tap("InspectoWebpack4Plugin", () => {
1148
1248
  const inspectoLoader = path7.resolve(__dirname, "loader.cjs");
1149
1249
  compiler.options.module.rules.push({
@@ -1170,7 +1270,7 @@ var InspectoWebpack4Plugin = class {
1170
1270
  HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(
1171
1271
  "InspectoWebpack4Plugin",
1172
1272
  async (data, cb) => {
1173
- const port = await startServer();
1273
+ const port = await this.ensureServer();
1174
1274
  data.headTags.unshift({
1175
1275
  tagName: "script",
1176
1276
  voidTag: false,
@@ -1184,7 +1284,7 @@ var InspectoWebpack4Plugin = class {
1184
1284
  compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(
1185
1285
  "InspectoWebpack4Plugin",
1186
1286
  async (data, cb) => {
1187
- const port = await startServer();
1287
+ const port = await this.ensureServer();
1188
1288
  data.head.unshift({
1189
1289
  tagName: "script",
1190
1290
  voidTag: false,