pathprobe 0.5.4 → 0.6.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/README.md CHANGED
@@ -13,14 +13,14 @@ npm install pathprobe
13
13
  ```ts
14
14
  import { findExistingPaths } from "pathprobe";
15
15
 
16
- const matches = await findExistingPaths(
17
- `
16
+ const matches = await findExistingPaths({
17
+ text: `
18
18
  请检查 src/index.ts:12
19
19
  以及 "./config/settings.json"
20
20
  `,
21
- 2,
22
- [process.cwd()],
23
- );
21
+ level: 2,
22
+ directories: [process.cwd()],
23
+ });
24
24
 
25
25
  console.log(matches);
26
26
  ```
@@ -46,14 +46,14 @@ console.log(matches);
46
46
  ## API
47
47
 
48
48
  ```ts
49
- findExistingPaths(
49
+ findExistingPaths({
50
50
  text,
51
51
  level,
52
52
  directories,
53
53
  variables?,
54
54
  respectIgnore?,
55
55
  searchHidden?,
56
- ): Promise<PathMatch[]>
56
+ }): Promise<PathMatch[]>
57
57
  ```
58
58
 
59
59
  参数说明:
@@ -117,8 +117,13 @@ ${{ env.HOME }}/project/file.txt
117
117
  也可以自行提供变量:
118
118
 
119
119
  ```ts
120
- await findExistingPaths("$PROJECT_ROOT/src/index.ts", 2, [process.cwd()], {
121
- PROJECT_ROOT: "/projects/demo",
120
+ await findExistingPaths({
121
+ text: "$PROJECT_ROOT/src/index.ts",
122
+ level: 2,
123
+ directories: [process.cwd()],
124
+ variables: {
125
+ PROJECT_ROOT: "/projects/demo",
126
+ },
122
127
  });
123
128
  ```
124
129
 
package/dist/index.mjs CHANGED
@@ -6,6 +6,8 @@ import fastGlob from "fast-glob";
6
6
  import { convertPathToPattern, globby } from "globby";
7
7
  import { isIP } from "node:net";
8
8
  import { hostname, networkInterfaces } from "node:os";
9
+ import nativeBridge from "./native/windows-bridge.cjs";
10
+ import { AhoCorasick } from "@monyone/aho-corasick";
9
11
  //#region config/settings.ts
10
12
  const settings = {
11
13
  batchValidationThreshold: 48,
@@ -19,7 +21,7 @@ const settings = {
19
21
  validationConcurrency: 32
20
22
  };
21
23
  //#endregion
22
- //#region src/variables/index.ts
24
+ //#region src/variables.ts
23
25
  const nameSource = String.raw`[A-Za-z_][A-Za-z0-9_.-]*`;
24
26
  const variableReferenceSource = String.raw`(?:\$\{\{\s*(?:(?:env|vars|variables)[.:])?${nameSource}\s*\}\}|\{\{\s*${nameSource}\s*\}\}|\$\{(?:env[.:])?${nameSource}\}|\$env:${nameSource}|\$[A-Za-z_][A-Za-z0-9_]*|%${nameSource}%|!${nameSource}!|\$\(\s*${nameSource}\s*\)|@${nameSource}@)`;
25
27
  const expressionPatterns = [
@@ -127,7 +129,7 @@ function extractCandidates(text, level) {
127
129
  return result;
128
130
  }
129
131
  //#endregion
130
- //#region src/existence.ts
132
+ //#region src/validation/existence.ts
131
133
  const knownFileErrors = /* @__PURE__ */ new Set([
132
134
  "EACCES",
133
135
  "ELOOP",
@@ -209,9 +211,31 @@ async function classifyExistingPaths(paths, roots) {
209
211
  return found;
210
212
  }
211
213
  //#endregion
214
+ //#region src/validation/containment.ts
215
+ function removeContainedMatches(matches) {
216
+ const ordered = matches.map((match, index) => ({
217
+ index,
218
+ match
219
+ })).toSorted(({ match: left }, { match: right }) => left.position.start - right.position.start || right.position.end - left.position.end);
220
+ const kept = /* @__PURE__ */ new Set();
221
+ let maxEndBeforeStart = -1;
222
+ let groupStart = -1;
223
+ let maxEndInGroup = -1;
224
+ for (const { index, match } of ordered) {
225
+ const { start, end } = match.position;
226
+ if (start !== groupStart) {
227
+ maxEndBeforeStart = Math.max(maxEndBeforeStart, maxEndInGroup);
228
+ groupStart = start;
229
+ maxEndInGroup = -1;
230
+ }
231
+ if (maxEndBeforeStart < end && maxEndInGroup <= end) kept.add(index);
232
+ maxEndInGroup = Math.max(maxEndInGroup, end);
233
+ }
234
+ return matches.filter((_, index) => kept.has(index));
235
+ }
236
+ //#endregion
212
237
  //#region src/native/unc.ts
213
- const runtimeRequire = globalThis.process.getBuiltinModule("node:module").createRequire(import.meta.url);
214
- const native = process.platform === "win32" ? runtimeRequire("pathprobe/native-loader") : void 0;
238
+ const native = process.platform === "win32" ? nativeBridge : void 0;
215
239
  const uncServerSegmentPattern = /^[^\\/:*?"<>|]+$/u;
216
240
  const unmappedDriveErrors = /* @__PURE__ */ new Set([
217
241
  1200,
@@ -322,7 +346,7 @@ function resolveUncPath(value) {
322
346
  return resolveMappedUncPath(path) ?? resolveLocalAdministrativeShare(path);
323
347
  }
324
348
  //#endregion
325
- //#region src/policy.ts
349
+ //#region src/search/policy.ts
326
350
  function pathKey$1(value) {
327
351
  return process.platform === "win32" ? value.toLowerCase() : value;
328
352
  }
@@ -369,8 +393,16 @@ async function resolveSearchDirectories(directories) {
369
393
  return [...unique.values()];
370
394
  }
371
395
  async function listSearchEntries(root, respectIgnore, searchHidden) {
372
- if (!respectIgnore) return fastGlob("**/*", traversalOptions(root, searchHidden));
373
- return globby("**/*", globbyOptions(root, respectIgnore, searchHidden));
396
+ return (!respectIgnore ? await fastGlob("**/*", {
397
+ ...traversalOptions(root, searchHidden),
398
+ objectMode: true
399
+ }) : await globby("**/*", {
400
+ ...globbyOptions(root, respectIgnore, searchHidden),
401
+ objectMode: true
402
+ })).map((entry) => ({
403
+ directory: entry.dirent.isDirectory(),
404
+ path: entry.path
405
+ }));
374
406
  }
375
407
  async function filterSearchablePaths(paths, roots, respectIgnore, searchHidden) {
376
408
  const allowed = /* @__PURE__ */ new Set();
@@ -404,7 +436,7 @@ async function filterSearchablePaths(paths, roots, respectIgnore, searchHidden)
404
436
  return allowed;
405
437
  }
406
438
  //#endregion
407
- //#region src/filesystem.ts
439
+ //#region src/validation/filesystem.ts
408
440
  function pathKey(value) {
409
441
  return process.platform === "win32" ? value.toLowerCase() : value;
410
442
  }
@@ -509,6 +541,7 @@ async function validateCandidates(candidates, roots, variables, respectIgnore, s
509
541
  const paths = toPaths(prepared.value, roots, variables);
510
542
  for (const filePath of paths) {
511
543
  resolvedCandidates.push({
544
+ ...candidate.expectedKind === void 0 ? {} : { expectedKind: candidate.expectedKind },
512
545
  ...prepared.location === void 0 ? {} : { location: prepared.location },
513
546
  path: filePath,
514
547
  position: prepared.position
@@ -521,9 +554,9 @@ async function validateCandidates(candidates, roots, variables, respectIgnore, s
521
554
  const classifiedPaths = await classifyExistingPaths(searchablePaths, roots);
522
555
  const kindsByPath = new Map([...classifiedPaths].map(([filePath, kind]) => [pathKey(filePath), kind]));
523
556
  const matches = /* @__PURE__ */ new Map();
524
- for (const { location, path, position } of resolvedCandidates) {
557
+ for (const { expectedKind, location, path, position } of resolvedCandidates) {
525
558
  const kind = kindsByPath.get(pathKey(path));
526
- if (kind === void 0) continue;
559
+ if (kind === void 0 || expectedKind !== void 0 && kind !== expectedKind) continue;
527
560
  const key = `${pathKey(path)}\0${position.start}\0${position.end}`;
528
561
  const existing = matches.get(key);
529
562
  if (existing !== void 0) {
@@ -537,69 +570,131 @@ async function validateCandidates(candidates, roots, variables, respectIgnore, s
537
570
  position
538
571
  });
539
572
  }
540
- return [...matches.values()];
573
+ return removeContainedMatches([...matches.values()]);
541
574
  }
542
575
  //#endregion
543
- //#region src/inventory.ts
544
- function isBoundary(value, following) {
576
+ //#region src/search/inventory.ts
577
+ let inventoryMatcherCache;
578
+ function isBoundary(value, following, directoryEnd = false) {
579
+ if (directoryEnd && value !== ".") return value === void 0 || /[\s"'`<>)\]},;:!?,。;:!?、]/u.test(value);
545
580
  if (value === ".") return following === void 0 || !/[\p{L}\p{N}_-]/u.test(following);
546
581
  return value === void 0 || !/[\p{L}\p{N}_/\\-]/u.test(value);
547
582
  }
548
- function addOccurrences(result, seen, source, text, value) {
549
- const target = process.platform === "win32" ? value.toLowerCase() : value;
550
- let offset = source.indexOf(target);
551
- while (offset !== -1) {
552
- const end = offset + target.length;
553
- if (isBoundary(text[offset - 1], text[offset]) && isBoundary(text[end], text[end + 1])) {
554
- const key = `${offset}:${end}:${text.slice(offset, end)}`;
555
- if (!seen.has(key)) {
556
- seen.add(key);
557
- result.push({
558
- end,
559
- kind: "inventory",
560
- start: offset,
561
- value
562
- });
563
- }
583
+ function addMatch(result, seen, text, value, start, end, expectedKind) {
584
+ if (!isBoundary(text[start - 1], text[start]) || !isBoundary(text[end], text[end + 1], expectedKind === "directory")) return;
585
+ const key = `${start}:${end}:${text.slice(start, end)}`;
586
+ if (!seen.has(key)) {
587
+ seen.add(key);
588
+ result.push({
589
+ end,
590
+ expectedKind,
591
+ kind: "inventory",
592
+ start,
593
+ value
594
+ });
595
+ }
596
+ }
597
+ function addVariant(patterns, entry, value) {
598
+ const key = process.platform === "win32" ? value.toLowerCase() : value;
599
+ if (!patterns.has(key)) patterns.set(key, {
600
+ expectedKind: entry.directory ? "directory" : "file",
601
+ relative: entry.path,
602
+ value
603
+ });
604
+ }
605
+ function addEntryVariants(patterns, entry) {
606
+ const native = entry.path.replaceAll("/", nodePath.sep);
607
+ if (entry.directory) {
608
+ addVariant(patterns, entry, `${entry.path}/`);
609
+ addVariant(patterns, entry, `${native}${nodePath.sep}`);
610
+ return;
611
+ }
612
+ addVariant(patterns, entry, entry.path);
613
+ addVariant(patterns, entry, native);
614
+ }
615
+ function createRootPrefixes(roots) {
616
+ const prefixes = /* @__PURE__ */ new Map();
617
+ for (const root of roots) {
618
+ const native = root.endsWith(nodePath.sep) ? root : `${root}${nodePath.sep}`;
619
+ const slashRoot = root.replaceAll(nodePath.sep, "/");
620
+ const slash = slashRoot.endsWith("/") ? slashRoot : `${slashRoot}/`;
621
+ for (const value of [native, slash]) {
622
+ const key = process.platform === "win32" ? value.toLowerCase() : value;
623
+ prefixes.set(key, {
624
+ root,
625
+ value: key
626
+ });
627
+ }
628
+ }
629
+ return [...prefixes.values()];
630
+ }
631
+ function addAbsoluteMatch(result, seen, source, text, pattern, prefixes, end, relativeStart) {
632
+ for (const prefix of prefixes) {
633
+ const start = relativeStart - prefix.value.length;
634
+ if (start >= 0 && source.startsWith(prefix.value, start)) {
635
+ addMatch(result, seen, text, nodePath.resolve(prefix.root, pattern.relative), start, end, pattern.expectedKind);
636
+ return true;
564
637
  }
565
- offset = source.indexOf(target, offset + 1);
566
638
  }
639
+ return false;
640
+ }
641
+ function hasSameEntries(cached, entries) {
642
+ if (cached.entries.length !== entries.length) return false;
643
+ for (let index = 0; index < entries.length; index += 1) {
644
+ const cachedEntries = cached.entries[index];
645
+ const currentEntries = entries[index];
646
+ if (cachedEntries === void 0 || currentEntries === void 0) return false;
647
+ if (cachedEntries.length !== currentEntries.length) return false;
648
+ for (let entryIndex = 0; entryIndex < currentEntries.length; entryIndex += 1) {
649
+ const cachedEntry = cachedEntries[entryIndex];
650
+ const currentEntry = currentEntries[entryIndex];
651
+ if (cachedEntry === void 0 || currentEntry === void 0 || cachedEntry.directory !== currentEntry.directory || cachedEntry.path !== currentEntry.path) return false;
652
+ }
653
+ }
654
+ return true;
655
+ }
656
+ function canReuseMatcher(cached, entries, roots, respectIgnore, searchHidden) {
657
+ return cached !== void 0 && cached.respectIgnore === respectIgnore && cached.searchHidden === searchHidden && cached.roots.length === roots.length && cached.roots.every((root, index) => root === roots[index]) && hasSameEntries(cached, entries);
567
658
  }
568
659
  async function inventoryCandidates(text, roots, respectIgnore, searchHidden) {
569
660
  const entries = await Promise.all(roots.map((root) => listSearchEntries(root, respectIgnore, searchHidden)));
570
661
  const result = [];
571
662
  const seen = /* @__PURE__ */ new Set();
572
- const scanned = /* @__PURE__ */ new Set();
573
663
  const source = process.platform === "win32" ? text.toLowerCase() : text;
574
- for (const [rootIndex, relativeEntries] of entries.entries()) {
575
- const root = roots[rootIndex];
576
- if (root === void 0) continue;
577
- for (const relativeEntry of relativeEntries) {
578
- const absoluteEntry = nodePath.resolve(root, relativeEntry);
579
- const variants = [
580
- relativeEntry,
581
- relativeEntry.replaceAll("/", nodePath.sep),
582
- absoluteEntry,
583
- absoluteEntry.replaceAll(nodePath.sep, "/")
584
- ];
585
- for (const value of variants) {
586
- const key = process.platform === "win32" ? value.toLowerCase() : value;
587
- if (!scanned.has(key)) {
588
- scanned.add(key);
589
- addOccurrences(result, seen, source, text, value);
590
- }
591
- }
592
- }
664
+ let inventoryMatcher = inventoryMatcherCache;
665
+ if (!canReuseMatcher(inventoryMatcher, entries, roots, respectIgnore, searchHidden)) {
666
+ const patterns = /* @__PURE__ */ new Map();
667
+ for (const relativeEntries of entries) for (const entry of relativeEntries) addEntryVariants(patterns, entry);
668
+ inventoryMatcher = {
669
+ entries,
670
+ matcher: new AhoCorasick([...patterns.keys()]),
671
+ patterns,
672
+ prefixes: createRootPrefixes(roots),
673
+ respectIgnore,
674
+ roots: [...roots],
675
+ searchHidden
676
+ };
677
+ inventoryMatcherCache = inventoryMatcher;
678
+ }
679
+ for (const { begin, end, keyword } of inventoryMatcher.matcher.matchInText(source)) {
680
+ const pattern = inventoryMatcher.patterns.get(keyword);
681
+ if (pattern === void 0) throw new Error("Inventory matcher returned an unknown path");
682
+ if (!addAbsoluteMatch(result, seen, source, text, pattern, inventoryMatcher.prefixes, end, begin)) addMatch(result, seen, text, pattern.value, begin, end, pattern.expectedKind);
593
683
  }
594
684
  return result;
595
685
  }
596
686
  //#endregion
597
687
  //#region src/index.ts
598
688
  const MAX_LEVEL = settings.spanWordLimits.length + 3;
689
+ function validateOptions(value) {
690
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("options must be an object");
691
+ }
599
692
  function validateVariables(value) {
600
693
  if (typeof value !== "object" || value === null || Array.isArray(value) || Object.values(value).some((item) => typeof item !== "string")) throw new TypeError("variables must be an object of string values");
601
694
  }
602
- async function findExistingPaths(text, level, directories, variables = {}, respectIgnore = settings.respectIgnoreByDefault, searchHidden = settings.searchHiddenByDefault) {
695
+ async function findExistingPaths(options) {
696
+ validateOptions(options);
697
+ const { directories, level, respectIgnore = settings.respectIgnoreByDefault, searchHidden = settings.searchHiddenByDefault, text, variables = {} } = options;
603
698
  if (typeof text !== "string") throw new TypeError("text must be a string");
604
699
  if (!Number.isInteger(level) || level < 1 || level > MAX_LEVEL) throw new RangeError(`level must be an integer from 1 to ${MAX_LEVEL}`);
605
700
  validateVariables(variables);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["pathKey","pathKey"],"sources":["../config/settings.ts","../src/variables/index.ts","../src/candidates.ts","../src/existence.ts","../src/native/unc.ts","../src/policy.ts","../src/filesystem.ts","../src/inventory.ts","../src/index.ts"],"sourcesContent":["import type { SearchSettings } from \"../src/types.js\";\n\nexport const settings: SearchSettings = {\n batchValidationThreshold: 48,\n directoryScanThreshold: 2,\n ignoreFilePatterns: [\"**/.ignore\", \"**/.rgignore\"],\n locationSuffixPattern: /:(?<line>\\d+)(?::(?<column>\\d+))?$/u,\n respectIgnoreByDefault: true,\n searchHiddenByDefault: false,\n spanWordLimits: [3, 24],\n trailingPunctuation: \".,;:!?,。;:!?、\",\n validationConcurrency: 32,\n};\n","import type { Variables } from \"../types.js\";\n\nconst nameSource = String.raw`[A-Za-z_][A-Za-z0-9_.-]*`;\nexport const variableReferenceSource = String.raw`(?:\\$\\{\\{\\s*(?:(?:env|vars|variables)[.:])?${nameSource}\\s*\\}\\}|\\{\\{\\s*${nameSource}\\s*\\}\\}|\\$\\{(?:env[.:])?${nameSource}\\}|\\$env:${nameSource}|\\$[A-Za-z_][A-Za-z0-9_]*|%${nameSource}%|!${nameSource}!|\\$\\(\\s*${nameSource}\\s*\\)|@${nameSource}@)`;\nconst expressionPatterns = [\n new RegExp(String.raw`\\$\\{\\{\\s*(?:(?:env|vars|variables)[.:])?(${nameSource})\\s*\\}\\}`, \"giu\"),\n new RegExp(String.raw`\\{\\{\\s*(${nameSource})\\s*\\}\\}`, \"gu\"),\n new RegExp(String.raw`\\$\\{(?:env[.:])?(${nameSource})\\}`, \"giu\"),\n new RegExp(String.raw`\\$env:(${nameSource})`, \"giu\"),\n new RegExp(String.raw`\\$(?!env:)([A-Za-z_][A-Za-z0-9_]*)`, \"giu\"),\n new RegExp(String.raw`%(${nameSource})%`, \"gu\"),\n new RegExp(String.raw`!(${nameSource})!`, \"gu\"),\n new RegExp(String.raw`\\$\\(\\s*(${nameSource})\\s*\\)`, \"gu\"),\n new RegExp(String.raw`@(${nameSource})@`, \"gu\"),\n];\nfunction resolveVariable(name: string, variables: Variables): string | undefined {\n const direct = variables[name] ?? process.env[name];\n if (direct !== undefined) {\n return direct;\n }\n const unscoped = /^(?:env|vars|variables)[.:](.+)$/iu.exec(name)?.[1];\n return unscoped === undefined ? undefined : (variables[unscoped] ?? process.env[unscoped]);\n}\nexport function expandVariables(value: string, variables: Variables): string {\n let result = value;\n for (const pattern of expressionPatterns) {\n result = result.replace(pattern, (match, name: string) => {\n const replacement = resolveVariable(name, variables);\n return replacement === undefined ? match : replacement;\n });\n }\n return result;\n}\n","import type { Candidate, SearchLevel } from \"./types.js\";\nimport { settings } from \"../config/settings.js\";\nimport { variableReferenceSource } from \"./variables/index.js\";\n\nconst explicitPattern =\n /(?:file:\\/\\/\\/?|[A-Za-z]:[\\\\/]|\\\\\\\\|\\/|(?:\\.{1,2}|~)[\\\\/])[^\"'`<>()[\\]{}\\s]+/gu;\nconst quotedPattern = /([\"'`])(?<value>[^\"'`\\r\\n]+)\\1/gu;\nconst tokenPattern = /[^\\s]+/gu;\nconst pathTokenPattern =\n /(?:(?:[\\p{L}\\p{N}_@%$+~.#[\\],-]+[\\\\/])+(?:[\\p{L}\\p{N}_@%$+~.#[\\],-]+)|[\\p{L}\\p{N}_@%$+~.#[\\],-]+\\.[\\p{L}\\p{N}_@%$-]{1,16})(?::\\d+){0,2}/gu;\nconst unquotedPathCharacterSource = \"[^\\\"'`<>()[\\\\]{}\\\\s]\";\nconst variablePathPattern = new RegExp(\n `${variableReferenceSource}(?:[\\\\\\\\/]${unquotedPathCharacterSource}+)+`,\n \"giu\",\n);\nconst clausePattern = /[^\\r\\n!?!?;;。]+/gu;\nconst pathHintPattern =\n /[\\\\/]|(?:^|[\\s\"'`])(?:\\.{1,2}|~|%[A-Za-z_][A-Za-z0-9_]*%|\\$\\{?[A-Za-z_][A-Za-z0-9_]*\\}?)(?:[\\\\/]|$)|\\.[\\p{L}\\p{N}]{1,16}(?::\\d+){0,2}(?:$|[\\s,.;:!?,。;:!?、])/u;\nconst variableHintPattern = new RegExp(String.raw`${variableReferenceSource}(?:[\\\\/]|$)`, \"iu\");\nfunction add(\n result: Candidate[],\n seen: Set<string>,\n value: string,\n start: number,\n end: number,\n kind: Candidate[\"kind\"],\n): void {\n if (value.length === 0) {\n return;\n }\n const key = `${start}:${end}:${value}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push({ end, kind, start, value });\n }\n}\nfunction addMatches(\n result: Candidate[],\n seen: Set<string>,\n text: string,\n pattern: RegExp,\n kind: Candidate[\"kind\"],\n): void {\n for (const match of text.matchAll(pattern)) {\n const value = match[0];\n const start = match.index ?? 0;\n add(result, seen, value, start, start + value.length, kind);\n }\n}\nfunction addQuotedMatches(result: Candidate[], seen: Set<string>, text: string): void {\n for (const match of text.matchAll(quotedPattern)) {\n const value = match.groups?.value;\n if (value === undefined) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].indexOf(value);\n add(result, seen, value, start, start + value.length, \"quoted\");\n }\n}\nfunction addSpanMatches(\n result: Candidate[],\n seen: Set<string>,\n text: string,\n maximumWords: number,\n): void {\n for (const clause of text.matchAll(clausePattern)) {\n const clauseStart = clause.index ?? 0;\n const clauseText = clause[0];\n const tokens = [...clauseText.matchAll(tokenPattern)].map((token) => ({\n end: clauseStart + (token.index ?? 0) + token[0].length,\n hint: Number(pathHintPattern.test(token[0]) || variableHintPattern.test(token[0])),\n start: clauseStart + (token.index ?? 0),\n value: token[0],\n }));\n const hintCounts = [0];\n for (const token of tokens) {\n hintCounts.push((hintCounts.at(-1) ?? 0) + token.hint);\n }\n for (let start = 0; start < tokens.length; start += 1) {\n const last = Math.min(tokens.length, start + maximumWords);\n for (let end = start + 1; end <= last; end += 1) {\n const firstToken = tokens[start];\n const lastToken = tokens[end - 1];\n const hintsBefore = hintCounts[start];\n const hintsAfter = hintCounts[end];\n if (\n firstToken === undefined ||\n lastToken === undefined ||\n hintsBefore === undefined ||\n hintsAfter === undefined ||\n hintsBefore === hintsAfter\n ) {\n continue;\n }\n const value = text.slice(firstToken.start, lastToken.end);\n if (pathHintPattern.test(value)) {\n add(result, seen, value, firstToken.start, lastToken.end, \"span\");\n }\n }\n }\n }\n}\nexport function extractCandidates(text: string, level: SearchLevel): Candidate[] {\n const result: Candidate[] = [];\n const seen = new Set<string>();\n addQuotedMatches(result, seen, text);\n addMatches(result, seen, text, explicitPattern, \"explicit\");\n if (level >= 2) {\n addMatches(result, seen, text, variablePathPattern, \"heuristic\");\n addMatches(result, seen, text, pathTokenPattern, \"heuristic\");\n }\n if (level >= 3) {\n const maximumWords =\n settings.spanWordLimits[Math.min(level - 3, settings.spanWordLimits.length - 1)];\n if (maximumWords === undefined) {\n throw new RangeError(\"No text-span level is configured\");\n }\n addSpanMatches(result, seen, text, maximumWords);\n }\n return result;\n}\n","import { readdir, stat } from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport pLimit from \"p-limit\";\nimport { settings } from \"../config/settings.js\";\nimport type { PathKind } from \"./types.js\";\n\nconst knownFileErrors = new Set([\n \"EACCES\",\n \"ELOOP\",\n \"ENAMETOOLONG\",\n \"ENOTDIR\",\n \"ENOENT\",\n \"EPERM\",\n \"EINVAL\",\n]);\nconst unverifiableUncErrors = new Set([\"UNKNOWN\", \"EUNKNOWN\"]);\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction fileErrorCode(error: unknown): string | undefined {\n if (error instanceof Error && \"code\" in error && typeof error.code === \"string\") {\n return error.code;\n }\n return undefined;\n}\nfunction isKnownFileError(error: unknown, filePath?: string): boolean {\n const code = fileErrorCode(error);\n return (\n code !== undefined &&\n (knownFileErrors.has(code) ||\n (filePath?.startsWith(\"\\\\\\\\\") === true && unverifiableUncErrors.has(code)))\n );\n}\nasync function classifyPath(filePath: string): Promise<PathKind | undefined> {\n try {\n const pathStats = await stat(filePath);\n if (pathStats.isFile()) {\n return \"file\";\n }\n return pathStats.isDirectory() ? \"directory\" : undefined;\n } catch (error) {\n if (isKnownFileError(error, filePath)) {\n return undefined;\n }\n throw error;\n }\n}\nasync function classifyAndAdd(found: Map<string, PathKind>, filePath: string): Promise<void> {\n const kind = await classifyPath(filePath);\n if (kind !== undefined) {\n found.set(filePath, kind);\n }\n}\nexport async function classifyExistingPaths(\n paths: readonly string[],\n roots: readonly string[],\n): Promise<Map<string, PathKind>> {\n const found = new Map<string, PathKind>();\n const limit = pLimit(settings.validationConcurrency);\n if (paths.length < settings.batchValidationThreshold) {\n await Promise.all(paths.map((filePath) => limit(() => classifyAndAdd(found, filePath))));\n return found;\n }\n const rootKeys = new Set(roots.map(pathKey));\n const pathsByParent = new Map<string, { parent: string; paths: string[] }>();\n for (const filePath of paths) {\n if (rootKeys.has(pathKey(filePath))) {\n found.set(filePath, \"directory\");\n continue;\n }\n const parent = nodePath.dirname(filePath);\n const key = pathKey(parent);\n const group = pathsByParent.get(key) ?? { parent, paths: [] };\n group.paths.push(filePath);\n pathsByParent.set(key, group);\n }\n const directPaths: string[] = [];\n const scannedGroups: { parent: string; paths: string[] }[] = [];\n for (const group of pathsByParent.values()) {\n if (group.paths.length < settings.directoryScanThreshold) {\n directPaths.push(...group.paths);\n } else {\n scannedGroups.push(group);\n }\n }\n await Promise.all([\n ...directPaths.map((filePath) => limit(() => classifyAndAdd(found, filePath))),\n ...scannedGroups.map(({ parent, paths: groupPaths }) =>\n limit(async () => {\n let entries;\n try {\n entries = await readdir(parent, { withFileTypes: true });\n } catch (error) {\n if (isKnownFileError(error, parent)) {\n return;\n }\n throw error;\n }\n const entriesByName = new Map(entries.map((entry) => [pathKey(entry.name), entry]));\n await Promise.all(\n groupPaths.map(async (filePath) => {\n const name = nodePath.basename(filePath);\n const entry = entriesByName.get(pathKey(name));\n if (entry?.isFile()) {\n found.set(filePath, \"file\");\n } else if (entry?.isDirectory()) {\n found.set(filePath, \"directory\");\n } else if (\n entry !== undefined ||\n (process.platform === \"win32\" && name.includes(\":\"))\n ) {\n await classifyAndAdd(found, filePath);\n }\n }),\n );\n }),\n ),\n ]);\n return found;\n}\n","import { isIP } from \"node:net\";\nimport { hostname, networkInterfaces } from \"node:os\";\nimport nodePath from \"node:path\";\n\ninterface DriveConnection {\n remote: unknown;\n status: number;\n}\ninterface NativeBridge {\n getDriveConnection(drive: string, bufferChars: number): DriveConnection;\n}\nconst moduleApi = globalThis.process.getBuiltinModule(\"node:module\");\nconst runtimeRequire = moduleApi.createRequire(import.meta.url);\nconst native =\n process.platform === \"win32\"\n ? (runtimeRequire(\"pathprobe/native-loader\") as NativeBridge)\n : undefined;\nconst uncServerSegmentPattern = /^[^\\\\/:*?\"<>|]+$/u;\nconst unmappedDriveErrors = new Set([1200, 1201, 1203, 1222, 2250]);\nconst errorMoreData = 234;\nconst mappingBufferChars = 32_768;\ninterface UncPath {\n canonical: string;\n server: string;\n share: string;\n suffix: string;\n}\ninterface DriveMapping {\n drive: string;\n remote: string;\n}\nfunction normalizeServerName(value: string): string {\n return value.replace(/\\.+$/u, \"\").toLowerCase();\n}\nfunction addLocalServerName(names: Set<string>, value: string | undefined): void {\n if (value !== undefined && uncServerSegmentPattern.test(value)) {\n names.add(normalizeServerName(value));\n }\n}\nfunction addIpv6LiteralName(names: Set<string>, value: string): void {\n const zoneIndex = value.indexOf(\"%\");\n const address = zoneIndex === -1 ? value : value.slice(0, zoneIndex);\n const zone = zoneIndex === -1 ? \"\" : `s${value.slice(zoneIndex + 1)}`;\n addLocalServerName(names, `${address.replaceAll(\":\", \"-\")}${zone}.ipv6-literal.net`);\n}\nfunction collectLocalServerNames(): Set<string> {\n const names = new Set<string>([\"localhost\"]);\n const computerName = process.env.COMPUTERNAME;\n addLocalServerName(names, hostname());\n addLocalServerName(names, computerName);\n if (computerName !== undefined && process.env.USERDNSDOMAIN !== undefined) {\n addLocalServerName(names, `${computerName}.${process.env.USERDNSDOMAIN}`);\n }\n for (const addresses of Object.values(networkInterfaces())) {\n for (const address of addresses ?? []) {\n if (isIP(address.address) === 4) {\n addLocalServerName(names, address.address);\n } else if (isIP(address.address) === 6) {\n addIpv6LiteralName(names, address.address);\n }\n }\n }\n addLocalServerName(names, \"--1.ipv6-literal.net\");\n return names;\n}\nconst localServerNames =\n process.platform === \"win32\" ? collectLocalServerNames() : new Set<string>();\nlet driveMappings: DriveMapping[] | undefined;\nfunction containsControlCharacter(value: string): boolean {\n return [...value].some((character) => character.charCodeAt(0) < 32);\n}\nfunction normalizeUncRoot(value: string): string {\n return value.replaceAll(\"/\", \"\\\\\").replace(/\\\\+$/u, \"\").toLowerCase();\n}\nfunction parseUncPath(value: string): UncPath | undefined {\n const normalized = value.replaceAll(\"/\", \"\\\\\");\n const extended = normalized.slice(0, 8).toLowerCase() === \"\\\\\\\\?\\\\unc\\\\\";\n if (normalized.startsWith(\"\\\\\\\\.\\\\\") || (normalized.startsWith(\"\\\\\\\\?\\\\\") && !extended)) {\n return undefined;\n }\n const serverStart = extended ? 8 : 2;\n const serverSeparator = normalized.slice(serverStart).indexOf(\"\\\\\");\n if (serverSeparator <= 0) {\n return undefined;\n }\n const serverEnd = serverStart + serverSeparator;\n const shareStart = serverEnd + 1;\n const shareSeparator = normalized.slice(shareStart).indexOf(\"\\\\\");\n const shareEnd = shareSeparator === -1 ? normalized.length : shareStart + shareSeparator;\n const server = normalized.slice(serverStart, serverEnd);\n const share = normalized.slice(shareStart, shareEnd);\n if (\n share.length === 0 ||\n !uncServerSegmentPattern.test(server) ||\n !uncServerSegmentPattern.test(share)\n ) {\n return undefined;\n }\n const suffix = normalized.slice(shareEnd);\n return {\n canonical: `\\\\\\\\${server}\\\\${share}${suffix}`,\n server,\n share,\n suffix,\n };\n}\nfunction queryDriveMapping(drive: string): string | undefined {\n if (native === undefined) {\n return undefined;\n }\n const { remote, status } = native.getDriveConnection(drive, mappingBufferChars);\n if (status === errorMoreData) {\n throw new Error(`WNetGetConnectionW returned an oversized mapping for ${drive}`);\n }\n if (unmappedDriveErrors.has(status)) {\n return undefined;\n }\n if (status !== 0) {\n throw new Error(`WNetGetConnectionW failed for ${drive} with error ${status}`);\n }\n if (typeof remote !== \"string\" || !remote.startsWith(\"\\\\\\\\\")) {\n throw new TypeError(`WNetGetConnectionW returned an invalid mapping for ${drive}`);\n }\n return normalizeUncRoot(remote);\n}\nfunction queryDriveMappings(): DriveMapping[] {\n if (driveMappings !== undefined) {\n return driveMappings;\n }\n const result: DriveMapping[] = [];\n for (let code = \"A\".charCodeAt(0); code <= \"Z\".charCodeAt(0); code += 1) {\n const drive = `${String.fromCharCode(code)}:`;\n const remote = queryDriveMapping(drive);\n if (remote !== undefined) {\n result.push({ drive, remote });\n }\n }\n driveMappings = result.toSorted((left, right) => right.remote.length - left.remote.length);\n return driveMappings;\n}\nfunction resolveMappedUncPath(path: UncPath): string | undefined {\n const canonical = normalizeUncRoot(path.canonical);\n const mapping = queryDriveMappings().find(\n ({ remote }) => canonical === remote || canonical.startsWith(`${remote}\\\\`),\n );\n if (mapping === undefined) {\n return undefined;\n }\n const relative = path.canonical.slice(mapping.remote.length);\n return nodePath.win32.normalize(`${mapping.drive}${relative}`);\n}\nfunction isLocalServer(value: string): boolean {\n const normalized = normalizeServerName(value);\n return (\n localServerNames.has(normalized) ||\n (isIP(value) === 4 && value.split(\".\")[0] === \"127\") ||\n normalized === \"--1.ipv6-literal.net\"\n );\n}\nfunction resolveLocalAdministrativeShare(path: UncPath): string | undefined {\n const match = /^([A-Za-z])\\$$/u.exec(path.share);\n if (match === null || !isLocalServer(path.server)) {\n return undefined;\n }\n return nodePath.win32.normalize(`${match[1]}:${path.suffix || \"\\\\\"}`);\n}\nexport function resolveUncPath(value: string): string | undefined {\n if (process.platform !== \"win32\" || (!value.startsWith(\"\\\\\\\\\") && !value.startsWith(\"//\"))) {\n return value;\n }\n if (containsControlCharacter(value)) {\n return undefined;\n }\n const path = parseUncPath(value);\n if (path === undefined) {\n return undefined;\n }\n return resolveMappedUncPath(path) ?? resolveLocalAdministrativeShare(path);\n}\n","import { stat } from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport fastGlob from \"fast-glob\";\nimport { convertPathToPattern, globby } from \"globby\";\nimport { settings } from \"../config/settings.js\";\nimport { resolveUncPath } from \"./native/unc.js\";\n\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction isWithinRoot(filePath: string, root: string): boolean {\n const relative = nodePath.relative(root, filePath);\n return (\n relative === \"\" ||\n (relative !== \"..\" &&\n !relative.startsWith(`..${nodePath.sep}`) &&\n !nodePath.isAbsolute(relative))\n );\n}\nfunction isHidden(relativePath: string): boolean {\n return relativePath.split(/[\\\\/]/u).some((part) => part.length > 1 && part.startsWith(\".\"));\n}\nfunction traversalOptions(root: string, searchHidden: boolean) {\n return {\n caseSensitiveMatch: process.platform !== \"win32\",\n cwd: root,\n dot: searchHidden,\n followSymbolicLinks: false,\n onlyFiles: false,\n unique: true,\n } as const;\n}\nfunction globbyOptions(root: string, respectIgnore: boolean, searchHidden: boolean) {\n return {\n ...traversalOptions(root, searchHidden),\n expandDirectories: false,\n gitignore: respectIgnore,\n globalGitignore: respectIgnore,\n ...(respectIgnore ? { ignoreFiles: settings.ignoreFilePatterns } : {}),\n } as const;\n}\nexport async function resolveSearchDirectories(directories: readonly string[]): Promise<string[]> {\n if (!Array.isArray(directories)) {\n throw new TypeError(\"directories must be an array\");\n }\n if (directories.length === 0) {\n throw new RangeError(\"directories must not be empty\");\n }\n const unique = new Map<string, string>();\n for (const directory of directories) {\n if (typeof directory !== \"string\" || directory.length === 0) {\n throw new TypeError(\"every directory must be a non-empty string\");\n }\n const resolvedUnc = resolveUncPath(directory);\n if (resolvedUnc === undefined || resolvedUnc.length === 0) {\n throw new TypeError(`${directory} cannot be represented as a drive-based path`);\n }\n const resolved = nodePath.resolve(resolvedUnc);\n unique.set(pathKey(resolved), resolved);\n }\n await Promise.all(\n [...unique.values()].map(async (directory) => {\n if (!(await stat(directory)).isDirectory()) {\n throw new TypeError(`${directory} is not a directory`);\n }\n }),\n );\n return [...unique.values()];\n}\nexport async function listSearchEntries(\n root: string,\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<string[]> {\n if (!respectIgnore) {\n return fastGlob(\"**/*\", traversalOptions(root, searchHidden));\n }\n return globby(\"**/*\", globbyOptions(root, respectIgnore, searchHidden));\n}\nexport async function filterSearchablePaths(\n paths: readonly string[],\n roots: readonly string[],\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<Set<string>> {\n const allowed = new Set<string>();\n const pathsByRoot = new Map<string, string[]>();\n for (const filePath of paths) {\n let hasSearchRoot = false;\n for (const root of roots) {\n if (!isWithinRoot(filePath, root)) {\n continue;\n }\n hasSearchRoot = true;\n const relative = nodePath.relative(root, filePath);\n if (!searchHidden && isHidden(relative)) {\n continue;\n }\n if (relative === \"\" || !respectIgnore) {\n allowed.add(filePath);\n } else {\n const grouped = pathsByRoot.get(root) ?? [];\n grouped.push(relative);\n pathsByRoot.set(root, grouped);\n }\n }\n if (hasSearchRoot) {\n continue;\n }\n const filesystemRelative = nodePath.relative(nodePath.parse(filePath).root, filePath);\n if (searchHidden || !isHidden(filesystemRelative)) {\n allowed.add(filePath);\n }\n }\n await Promise.all(\n [...pathsByRoot].map(async ([root, relativePaths]) => {\n const patterns = relativePaths.map(convertPathToPattern);\n const matches = await globby(patterns, {\n ...globbyOptions(root, true, true),\n absolute: true,\n });\n for (const match of matches) {\n allowed.add(nodePath.normalize(match));\n }\n }),\n );\n return allowed;\n}\n","import { fileURLToPath } from \"node:url\";\nimport nodePath from \"node:path\";\nimport { classifyExistingPaths } from \"./existence.js\";\nimport { filterSearchablePaths } from \"./policy.js\";\nimport { expandVariables } from \"./variables/index.js\";\nimport { resolveUncPath } from \"./native/unc.js\";\nimport { settings } from \"../config/settings.js\";\nimport type { Candidate, PathLocation, PathMatch, PathPosition, Variables } from \"./types.js\";\n\ninterface ResolvedCandidate {\n location?: PathLocation;\n path: string;\n position: PathPosition;\n}\ninterface PreparedCandidate {\n location?: PathLocation;\n position: PathPosition;\n value: string;\n}\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction uniquePaths(values: Iterable<string>): string[] {\n const paths = new Map<string, string>();\n for (const value of values) {\n paths.set(pathKey(value), value);\n }\n return [...paths.values()];\n}\nfunction parseLocationPart(value: string, name: string): number {\n const result = Number(value);\n if (!Number.isSafeInteger(result)) {\n throw new RangeError(`${name} must be a safe integer`);\n }\n return result;\n}\nfunction prepareCandidate(candidate: Candidate): PreparedCandidate {\n let end = candidate.end;\n let start = candidate.start;\n let value = candidate.value;\n if (candidate.kind !== \"inventory\" && candidate.kind !== \"quoted\") {\n const startTrimmed = value.trimStart();\n start += value.length - startTrimmed.length;\n value = startTrimmed;\n const endTrimmed = value.trimEnd();\n end -= value.length - endTrimmed.length;\n value = endTrimmed;\n if (\n value.length >= 2 &&\n ((value[0] === '\"' && value.at(-1) === '\"') ||\n (value[0] === \"'\" && value.at(-1) === \"'\") ||\n (value[0] === \"`\" && value.at(-1) === \"`\"))\n ) {\n start += 1;\n end -= 1;\n value = value.slice(1, -1);\n }\n while (value.length > 0 && settings.trailingPunctuation.includes(value.at(-1) ?? \"\")) {\n end -= 1;\n value = value.slice(0, -1);\n }\n }\n if (candidate.kind === \"inventory\") {\n return { position: { end, start }, value };\n }\n const match = settings.locationSuffixPattern.exec(value);\n if (match === null) {\n return { position: { end, start }, value };\n }\n const lineValue = match.groups?.line;\n if (lineValue === undefined) {\n throw new TypeError(\"locationSuffixPattern must capture a line\");\n }\n const columnValue = match.groups?.column;\n const location: PathLocation =\n columnValue === undefined\n ? { line: parseLocationPart(lineValue, \"line\") }\n : {\n column: parseLocationPart(columnValue, \"column\"),\n line: parseLocationPart(lineValue, \"line\"),\n };\n end -= match[0].length;\n return {\n location,\n position: { end, start },\n value: value.slice(0, match.index),\n };\n}\nfunction unescape(value: string): string {\n if (value.startsWith(\"\\\\\\\\\") && !value.startsWith(\"\\\\\\\\\\\\\\\\\")) {\n return value;\n }\n return value.replace(/\\\\([\"'`\\\\])/gu, \"$1\").replace(/\\\\\\\\/gu, \"\\\\\");\n}\nfunction toPaths(value: string, roots: readonly string[], variables: Variables): string[] {\n let expanded = expandVariables(value, variables);\n if (expanded.startsWith(\"file://\")) {\n try {\n expanded = fileURLToPath(expanded);\n } catch (error) {\n if (error instanceof TypeError) {\n return [];\n }\n throw error;\n }\n } else {\n expanded = unescape(expanded);\n if (expanded === \"~\" || /^~[\\\\/]/u.test(expanded)) {\n expanded = nodePath.join(\n variables.HOME ??\n variables.USERPROFILE ??\n process.env.HOME ??\n process.env.USERPROFILE ??\n \"\",\n expanded.slice(2),\n );\n }\n }\n const resolvedPath = resolveUncPath(expanded);\n if (resolvedPath === undefined || resolvedPath.length === 0) {\n return [];\n }\n expanded = resolvedPath;\n if (nodePath.isAbsolute(expanded)) {\n return [nodePath.normalize(expanded)];\n }\n return uniquePaths(roots.map((root) => nodePath.resolve(root, expanded)));\n}\nfunction mergeLocation(match: PathMatch, location: PathLocation | undefined): void {\n if (location === undefined) {\n return;\n }\n if (match.location === undefined) {\n match.location = location;\n return;\n }\n if (match.location.line !== location.line || match.location.column !== location.column) {\n throw new Error(\"Candidates for the same path and position have conflicting locations\");\n }\n}\nexport async function validateCandidates(\n candidates: Candidate[],\n roots: readonly string[],\n variables: Variables,\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<PathMatch[]> {\n const resolvedCandidates: ResolvedCandidate[] = [];\n const validationPaths = new Map<string, string>();\n for (const candidate of candidates) {\n const prepared = prepareCandidate(candidate);\n const paths = toPaths(prepared.value, roots, variables);\n for (const filePath of paths) {\n resolvedCandidates.push({\n ...(prepared.location === undefined ? {} : { location: prepared.location }),\n path: filePath,\n position: prepared.position,\n });\n validationPaths.set(pathKey(filePath), filePath);\n }\n }\n let searchablePaths = [...validationPaths.values()];\n if (respectIgnore || !searchHidden) {\n searchablePaths = [\n ...(await filterSearchablePaths(searchablePaths, roots, respectIgnore, searchHidden)),\n ];\n }\n const classifiedPaths = await classifyExistingPaths(searchablePaths, roots);\n const kindsByPath = new Map(\n [...classifiedPaths].map(([filePath, kind]) => [pathKey(filePath), kind]),\n );\n const matches = new Map<string, PathMatch>();\n for (const { location, path, position } of resolvedCandidates) {\n const kind = kindsByPath.get(pathKey(path));\n if (kind === undefined) {\n continue;\n }\n const key = `${pathKey(path)}\\0${position.start}\\0${position.end}`;\n const existing = matches.get(key);\n if (existing !== undefined) {\n mergeLocation(existing, location);\n continue;\n }\n matches.set(key, {\n kind,\n ...(location === undefined ? {} : { location }),\n path,\n position,\n });\n }\n return [...matches.values()];\n}\n","import nodePath from \"node:path\";\nimport { listSearchEntries } from \"./policy.js\";\nimport type { Candidate } from \"./types.js\";\n\nfunction isBoundary(value: string | undefined, following: string | undefined): boolean {\n if (value === \".\") {\n return following === undefined || !/[\\p{L}\\p{N}_-]/u.test(following);\n }\n return value === undefined || !/[\\p{L}\\p{N}_/\\\\-]/u.test(value);\n}\nfunction addOccurrences(\n result: Candidate[],\n seen: Set<string>,\n source: string,\n text: string,\n value: string,\n): void {\n const target = process.platform === \"win32\" ? value.toLowerCase() : value;\n let offset = source.indexOf(target);\n while (offset !== -1) {\n const end = offset + target.length;\n if (isBoundary(text[offset - 1], text[offset]) && isBoundary(text[end], text[end + 1])) {\n const key = `${offset}:${end}:${text.slice(offset, end)}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push({\n end,\n kind: \"inventory\",\n start: offset,\n value,\n });\n }\n }\n offset = source.indexOf(target, offset + 1);\n }\n}\nexport async function inventoryCandidates(\n text: string,\n roots: readonly string[],\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<Candidate[]> {\n const entries = await Promise.all(\n roots.map((root) => listSearchEntries(root, respectIgnore, searchHidden)),\n );\n const result: Candidate[] = [];\n const seen = new Set<string>();\n const scanned = new Set<string>();\n const source = process.platform === \"win32\" ? text.toLowerCase() : text;\n for (const [rootIndex, relativeEntries] of entries.entries()) {\n const root = roots[rootIndex];\n if (root === undefined) {\n continue;\n }\n for (const relativeEntry of relativeEntries) {\n const absoluteEntry = nodePath.resolve(root, relativeEntry);\n const variants = [\n relativeEntry,\n relativeEntry.replaceAll(\"/\", nodePath.sep),\n absoluteEntry,\n absoluteEntry.replaceAll(nodePath.sep, \"/\"),\n ];\n for (const value of variants) {\n const key = process.platform === \"win32\" ? value.toLowerCase() : value;\n if (!scanned.has(key)) {\n scanned.add(key);\n addOccurrences(result, seen, source, text, value);\n }\n }\n }\n }\n return result;\n}\n","import { extractCandidates } from \"./candidates.js\";\nimport { validateCandidates } from \"./filesystem.js\";\nimport { inventoryCandidates } from \"./inventory.js\";\nimport { resolveSearchDirectories } from \"./policy.js\";\nimport { settings } from \"../config/settings.js\";\nimport type { PathMatch, SearchLevel, Variables } from \"./types.js\";\n\nexport const MAX_LEVEL = settings.spanWordLimits.length + 3;\nfunction validateVariables(value: unknown): asserts value is Variables {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n Object.values(value).some((item) => typeof item !== \"string\")\n ) {\n throw new TypeError(\"variables must be an object of string values\");\n }\n}\nexport async function findExistingPaths(\n text: string,\n level: SearchLevel,\n directories: readonly string[],\n variables: Variables = {},\n respectIgnore: boolean = settings.respectIgnoreByDefault,\n searchHidden: boolean = settings.searchHiddenByDefault,\n): Promise<PathMatch[]> {\n if (typeof text !== \"string\") {\n throw new TypeError(\"text must be a string\");\n }\n if (!Number.isInteger(level) || level < 1 || level > MAX_LEVEL) {\n throw new RangeError(`level must be an integer from 1 to ${MAX_LEVEL}`);\n }\n validateVariables(variables);\n if (typeof respectIgnore !== \"boolean\") {\n throw new TypeError(\"respectIgnore must be a boolean\");\n }\n if (typeof searchHidden !== \"boolean\") {\n throw new TypeError(\"searchHidden must be a boolean\");\n }\n const roots = await resolveSearchDirectories(directories);\n const candidates = extractCandidates(text, level);\n if (level === MAX_LEVEL) {\n candidates.push(...(await inventoryCandidates(text, roots, respectIgnore, searchHidden)));\n }\n return validateCandidates(candidates, roots, variables, respectIgnore, searchHidden);\n}\nexport type {\n PathKind,\n PathLocation,\n PathMatch,\n PathPosition,\n SearchLevel,\n Variables,\n} from \"./types.js\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["pathKey","pathKey"],"sources":["../config/settings.ts","../src/variables.ts","../src/candidates.ts","../src/validation/existence.ts","../src/validation/containment.ts","../src/native/unc.ts","../src/search/policy.ts","../src/validation/filesystem.ts","../src/search/inventory.ts","../src/index.ts"],"sourcesContent":["import type { SearchSettings } from \"../src/types.js\";\n\nexport const settings: SearchSettings = {\n batchValidationThreshold: 48,\n directoryScanThreshold: 2,\n ignoreFilePatterns: [\"**/.ignore\", \"**/.rgignore\"],\n locationSuffixPattern: /:(?<line>\\d+)(?::(?<column>\\d+))?$/u,\n respectIgnoreByDefault: true,\n searchHiddenByDefault: false,\n spanWordLimits: [3, 24],\n trailingPunctuation: \".,;:!?,。;:!?、\",\n validationConcurrency: 32,\n};\n","import type { Variables } from \"./types.js\";\n\nconst nameSource = String.raw`[A-Za-z_][A-Za-z0-9_.-]*`;\nexport const variableReferenceSource = String.raw`(?:\\$\\{\\{\\s*(?:(?:env|vars|variables)[.:])?${nameSource}\\s*\\}\\}|\\{\\{\\s*${nameSource}\\s*\\}\\}|\\$\\{(?:env[.:])?${nameSource}\\}|\\$env:${nameSource}|\\$[A-Za-z_][A-Za-z0-9_]*|%${nameSource}%|!${nameSource}!|\\$\\(\\s*${nameSource}\\s*\\)|@${nameSource}@)`;\nconst expressionPatterns = [\n new RegExp(String.raw`\\$\\{\\{\\s*(?:(?:env|vars|variables)[.:])?(${nameSource})\\s*\\}\\}`, \"giu\"),\n new RegExp(String.raw`\\{\\{\\s*(${nameSource})\\s*\\}\\}`, \"gu\"),\n new RegExp(String.raw`\\$\\{(?:env[.:])?(${nameSource})\\}`, \"giu\"),\n new RegExp(String.raw`\\$env:(${nameSource})`, \"giu\"),\n new RegExp(String.raw`\\$(?!env:)([A-Za-z_][A-Za-z0-9_]*)`, \"giu\"),\n new RegExp(String.raw`%(${nameSource})%`, \"gu\"),\n new RegExp(String.raw`!(${nameSource})!`, \"gu\"),\n new RegExp(String.raw`\\$\\(\\s*(${nameSource})\\s*\\)`, \"gu\"),\n new RegExp(String.raw`@(${nameSource})@`, \"gu\"),\n];\nfunction resolveVariable(name: string, variables: Variables): string | undefined {\n const direct = variables[name] ?? process.env[name];\n if (direct !== undefined) {\n return direct;\n }\n const unscoped = /^(?:env|vars|variables)[.:](.+)$/iu.exec(name)?.[1];\n return unscoped === undefined ? undefined : (variables[unscoped] ?? process.env[unscoped]);\n}\nexport function expandVariables(value: string, variables: Variables): string {\n let result = value;\n for (const pattern of expressionPatterns) {\n result = result.replace(pattern, (match, name: string) => {\n const replacement = resolveVariable(name, variables);\n return replacement === undefined ? match : replacement;\n });\n }\n return result;\n}\n","import type { Candidate, SearchLevel } from \"./types.js\";\nimport { settings } from \"../config/settings.js\";\nimport { variableReferenceSource } from \"./variables.js\";\n\nconst explicitPattern =\n /(?:file:\\/\\/\\/?|[A-Za-z]:[\\\\/]|\\\\\\\\|\\/|(?:\\.{1,2}|~)[\\\\/])[^\"'`<>()[\\]{}\\s]+/gu;\nconst quotedPattern = /([\"'`])(?<value>[^\"'`\\r\\n]+)\\1/gu;\nconst tokenPattern = /[^\\s]+/gu;\nconst pathTokenPattern =\n /(?:(?:[\\p{L}\\p{N}_@%$+~.#[\\],-]+[\\\\/])+(?:[\\p{L}\\p{N}_@%$+~.#[\\],-]+)|[\\p{L}\\p{N}_@%$+~.#[\\],-]+\\.[\\p{L}\\p{N}_@%$-]{1,16})(?::\\d+){0,2}/gu;\nconst unquotedPathCharacterSource = \"[^\\\"'`<>()[\\\\]{}\\\\s]\";\nconst variablePathPattern = new RegExp(\n `${variableReferenceSource}(?:[\\\\\\\\/]${unquotedPathCharacterSource}+)+`,\n \"giu\",\n);\nconst clausePattern = /[^\\r\\n!?!?;;。]+/gu;\nconst pathHintPattern =\n /[\\\\/]|(?:^|[\\s\"'`])(?:\\.{1,2}|~|%[A-Za-z_][A-Za-z0-9_]*%|\\$\\{?[A-Za-z_][A-Za-z0-9_]*\\}?)(?:[\\\\/]|$)|\\.[\\p{L}\\p{N}]{1,16}(?::\\d+){0,2}(?:$|[\\s,.;:!?,。;:!?、])/u;\nconst variableHintPattern = new RegExp(String.raw`${variableReferenceSource}(?:[\\\\/]|$)`, \"iu\");\nfunction add(\n result: Candidate[],\n seen: Set<string>,\n value: string,\n start: number,\n end: number,\n kind: Candidate[\"kind\"],\n): void {\n if (value.length === 0) {\n return;\n }\n const key = `${start}:${end}:${value}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push({ end, kind, start, value });\n }\n}\nfunction addMatches(\n result: Candidate[],\n seen: Set<string>,\n text: string,\n pattern: RegExp,\n kind: Candidate[\"kind\"],\n): void {\n for (const match of text.matchAll(pattern)) {\n const value = match[0];\n const start = match.index ?? 0;\n add(result, seen, value, start, start + value.length, kind);\n }\n}\nfunction addQuotedMatches(result: Candidate[], seen: Set<string>, text: string): void {\n for (const match of text.matchAll(quotedPattern)) {\n const value = match.groups?.value;\n if (value === undefined) {\n continue;\n }\n const start = (match.index ?? 0) + match[0].indexOf(value);\n add(result, seen, value, start, start + value.length, \"quoted\");\n }\n}\nfunction addSpanMatches(\n result: Candidate[],\n seen: Set<string>,\n text: string,\n maximumWords: number,\n): void {\n for (const clause of text.matchAll(clausePattern)) {\n const clauseStart = clause.index ?? 0;\n const clauseText = clause[0];\n const tokens = [...clauseText.matchAll(tokenPattern)].map((token) => ({\n end: clauseStart + (token.index ?? 0) + token[0].length,\n hint: Number(pathHintPattern.test(token[0]) || variableHintPattern.test(token[0])),\n start: clauseStart + (token.index ?? 0),\n value: token[0],\n }));\n const hintCounts = [0];\n for (const token of tokens) {\n hintCounts.push((hintCounts.at(-1) ?? 0) + token.hint);\n }\n for (let start = 0; start < tokens.length; start += 1) {\n const last = Math.min(tokens.length, start + maximumWords);\n for (let end = start + 1; end <= last; end += 1) {\n const firstToken = tokens[start];\n const lastToken = tokens[end - 1];\n const hintsBefore = hintCounts[start];\n const hintsAfter = hintCounts[end];\n if (\n firstToken === undefined ||\n lastToken === undefined ||\n hintsBefore === undefined ||\n hintsAfter === undefined ||\n hintsBefore === hintsAfter\n ) {\n continue;\n }\n const value = text.slice(firstToken.start, lastToken.end);\n if (pathHintPattern.test(value)) {\n add(result, seen, value, firstToken.start, lastToken.end, \"span\");\n }\n }\n }\n }\n}\nexport function extractCandidates(text: string, level: SearchLevel): Candidate[] {\n const result: Candidate[] = [];\n const seen = new Set<string>();\n addQuotedMatches(result, seen, text);\n addMatches(result, seen, text, explicitPattern, \"explicit\");\n if (level >= 2) {\n addMatches(result, seen, text, variablePathPattern, \"heuristic\");\n addMatches(result, seen, text, pathTokenPattern, \"heuristic\");\n }\n if (level >= 3) {\n const maximumWords =\n settings.spanWordLimits[Math.min(level - 3, settings.spanWordLimits.length - 1)];\n if (maximumWords === undefined) {\n throw new RangeError(\"No text-span level is configured\");\n }\n addSpanMatches(result, seen, text, maximumWords);\n }\n return result;\n}\n","import { readdir, stat } from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport pLimit from \"p-limit\";\nimport { settings } from \"../../config/settings.js\";\nimport type { PathKind } from \"../types.js\";\n\nconst knownFileErrors = new Set([\n \"EACCES\",\n \"ELOOP\",\n \"ENAMETOOLONG\",\n \"ENOTDIR\",\n \"ENOENT\",\n \"EPERM\",\n \"EINVAL\",\n]);\nconst unverifiableUncErrors = new Set([\"UNKNOWN\", \"EUNKNOWN\"]);\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction fileErrorCode(error: unknown): string | undefined {\n if (error instanceof Error && \"code\" in error && typeof error.code === \"string\") {\n return error.code;\n }\n return undefined;\n}\nfunction isKnownFileError(error: unknown, filePath?: string): boolean {\n const code = fileErrorCode(error);\n return (\n code !== undefined &&\n (knownFileErrors.has(code) ||\n (filePath?.startsWith(\"\\\\\\\\\") === true && unverifiableUncErrors.has(code)))\n );\n}\nasync function classifyPath(filePath: string): Promise<PathKind | undefined> {\n try {\n const pathStats = await stat(filePath);\n if (pathStats.isFile()) {\n return \"file\";\n }\n return pathStats.isDirectory() ? \"directory\" : undefined;\n } catch (error) {\n if (isKnownFileError(error, filePath)) {\n return undefined;\n }\n throw error;\n }\n}\nasync function classifyAndAdd(found: Map<string, PathKind>, filePath: string): Promise<void> {\n const kind = await classifyPath(filePath);\n if (kind !== undefined) {\n found.set(filePath, kind);\n }\n}\nexport async function classifyExistingPaths(\n paths: readonly string[],\n roots: readonly string[],\n): Promise<Map<string, PathKind>> {\n const found = new Map<string, PathKind>();\n const limit = pLimit(settings.validationConcurrency);\n if (paths.length < settings.batchValidationThreshold) {\n await Promise.all(paths.map((filePath) => limit(() => classifyAndAdd(found, filePath))));\n return found;\n }\n const rootKeys = new Set(roots.map(pathKey));\n const pathsByParent = new Map<string, { parent: string; paths: string[] }>();\n for (const filePath of paths) {\n if (rootKeys.has(pathKey(filePath))) {\n found.set(filePath, \"directory\");\n continue;\n }\n const parent = nodePath.dirname(filePath);\n const key = pathKey(parent);\n const group = pathsByParent.get(key) ?? { parent, paths: [] };\n group.paths.push(filePath);\n pathsByParent.set(key, group);\n }\n const directPaths: string[] = [];\n const scannedGroups: { parent: string; paths: string[] }[] = [];\n for (const group of pathsByParent.values()) {\n if (group.paths.length < settings.directoryScanThreshold) {\n directPaths.push(...group.paths);\n } else {\n scannedGroups.push(group);\n }\n }\n await Promise.all([\n ...directPaths.map((filePath) => limit(() => classifyAndAdd(found, filePath))),\n ...scannedGroups.map(({ parent, paths: groupPaths }) =>\n limit(async () => {\n let entries;\n try {\n entries = await readdir(parent, { withFileTypes: true });\n } catch (error) {\n if (isKnownFileError(error, parent)) {\n return;\n }\n throw error;\n }\n const entriesByName = new Map(entries.map((entry) => [pathKey(entry.name), entry]));\n await Promise.all(\n groupPaths.map(async (filePath) => {\n const name = nodePath.basename(filePath);\n const entry = entriesByName.get(pathKey(name));\n if (entry?.isFile()) {\n found.set(filePath, \"file\");\n } else if (entry?.isDirectory()) {\n found.set(filePath, \"directory\");\n } else if (\n entry !== undefined ||\n (process.platform === \"win32\" && name.includes(\":\"))\n ) {\n await classifyAndAdd(found, filePath);\n }\n }),\n );\n }),\n ),\n ]);\n return found;\n}\n","import type { PathMatch } from \"../types.js\";\n\nexport function removeContainedMatches(matches: readonly PathMatch[]): PathMatch[] {\n const ordered = matches\n .map((match, index) => ({ index, match }))\n .toSorted(\n ({ match: left }, { match: right }) =>\n left.position.start - right.position.start || right.position.end - left.position.end,\n );\n const kept = new Set<number>();\n let maxEndBeforeStart = -1;\n let groupStart = -1;\n let maxEndInGroup = -1;\n for (const { index, match } of ordered) {\n const { start, end } = match.position;\n if (start !== groupStart) {\n maxEndBeforeStart = Math.max(maxEndBeforeStart, maxEndInGroup);\n groupStart = start;\n maxEndInGroup = -1;\n }\n if (maxEndBeforeStart < end && maxEndInGroup <= end) {\n kept.add(index);\n }\n maxEndInGroup = Math.max(maxEndInGroup, end);\n }\n return matches.filter((_, index) => kept.has(index));\n}\n","import { isIP } from \"node:net\";\nimport { hostname, networkInterfaces } from \"node:os\";\nimport nodePath from \"node:path\";\nimport nativeBridge from \"./windows-bridge.cjs\";\n\nconst native = process.platform === \"win32\" ? nativeBridge : undefined;\nconst uncServerSegmentPattern = /^[^\\\\/:*?\"<>|]+$/u;\nconst unmappedDriveErrors = new Set([1200, 1201, 1203, 1222, 2250]);\nconst errorMoreData = 234;\nconst mappingBufferChars = 32_768;\ninterface UncPath {\n canonical: string;\n server: string;\n share: string;\n suffix: string;\n}\ninterface DriveMapping {\n drive: string;\n remote: string;\n}\nfunction normalizeServerName(value: string): string {\n return value.replace(/\\.+$/u, \"\").toLowerCase();\n}\nfunction addLocalServerName(names: Set<string>, value: string | undefined): void {\n if (value !== undefined && uncServerSegmentPattern.test(value)) {\n names.add(normalizeServerName(value));\n }\n}\nfunction addIpv6LiteralName(names: Set<string>, value: string): void {\n const zoneIndex = value.indexOf(\"%\");\n const address = zoneIndex === -1 ? value : value.slice(0, zoneIndex);\n const zone = zoneIndex === -1 ? \"\" : `s${value.slice(zoneIndex + 1)}`;\n addLocalServerName(names, `${address.replaceAll(\":\", \"-\")}${zone}.ipv6-literal.net`);\n}\nfunction collectLocalServerNames(): Set<string> {\n const names = new Set<string>([\"localhost\"]);\n const computerName = process.env.COMPUTERNAME;\n addLocalServerName(names, hostname());\n addLocalServerName(names, computerName);\n if (computerName !== undefined && process.env.USERDNSDOMAIN !== undefined) {\n addLocalServerName(names, `${computerName}.${process.env.USERDNSDOMAIN}`);\n }\n for (const addresses of Object.values(networkInterfaces())) {\n for (const address of addresses ?? []) {\n if (isIP(address.address) === 4) {\n addLocalServerName(names, address.address);\n } else if (isIP(address.address) === 6) {\n addIpv6LiteralName(names, address.address);\n }\n }\n }\n addLocalServerName(names, \"--1.ipv6-literal.net\");\n return names;\n}\nconst localServerNames =\n process.platform === \"win32\" ? collectLocalServerNames() : new Set<string>();\nlet driveMappings: DriveMapping[] | undefined;\nfunction containsControlCharacter(value: string): boolean {\n return [...value].some((character) => character.charCodeAt(0) < 32);\n}\nfunction normalizeUncRoot(value: string): string {\n return value.replaceAll(\"/\", \"\\\\\").replace(/\\\\+$/u, \"\").toLowerCase();\n}\nfunction parseUncPath(value: string): UncPath | undefined {\n const normalized = value.replaceAll(\"/\", \"\\\\\");\n const extended = normalized.slice(0, 8).toLowerCase() === \"\\\\\\\\?\\\\unc\\\\\";\n if (normalized.startsWith(\"\\\\\\\\.\\\\\") || (normalized.startsWith(\"\\\\\\\\?\\\\\") && !extended)) {\n return undefined;\n }\n const serverStart = extended ? 8 : 2;\n const serverSeparator = normalized.slice(serverStart).indexOf(\"\\\\\");\n if (serverSeparator <= 0) {\n return undefined;\n }\n const serverEnd = serverStart + serverSeparator;\n const shareStart = serverEnd + 1;\n const shareSeparator = normalized.slice(shareStart).indexOf(\"\\\\\");\n const shareEnd = shareSeparator === -1 ? normalized.length : shareStart + shareSeparator;\n const server = normalized.slice(serverStart, serverEnd);\n const share = normalized.slice(shareStart, shareEnd);\n if (\n share.length === 0 ||\n !uncServerSegmentPattern.test(server) ||\n !uncServerSegmentPattern.test(share)\n ) {\n return undefined;\n }\n const suffix = normalized.slice(shareEnd);\n return {\n canonical: `\\\\\\\\${server}\\\\${share}${suffix}`,\n server,\n share,\n suffix,\n };\n}\nfunction queryDriveMapping(drive: string): string | undefined {\n if (native === undefined) {\n return undefined;\n }\n const { remote, status } = native.getDriveConnection(drive, mappingBufferChars);\n if (status === errorMoreData) {\n throw new Error(`WNetGetConnectionW returned an oversized mapping for ${drive}`);\n }\n if (unmappedDriveErrors.has(status)) {\n return undefined;\n }\n if (status !== 0) {\n throw new Error(`WNetGetConnectionW failed for ${drive} with error ${status}`);\n }\n if (typeof remote !== \"string\" || !remote.startsWith(\"\\\\\\\\\")) {\n throw new TypeError(`WNetGetConnectionW returned an invalid mapping for ${drive}`);\n }\n return normalizeUncRoot(remote);\n}\nfunction queryDriveMappings(): DriveMapping[] {\n if (driveMappings !== undefined) {\n return driveMappings;\n }\n const result: DriveMapping[] = [];\n for (let code = \"A\".charCodeAt(0); code <= \"Z\".charCodeAt(0); code += 1) {\n const drive = `${String.fromCharCode(code)}:`;\n const remote = queryDriveMapping(drive);\n if (remote !== undefined) {\n result.push({ drive, remote });\n }\n }\n driveMappings = result.toSorted((left, right) => right.remote.length - left.remote.length);\n return driveMappings;\n}\nfunction resolveMappedUncPath(path: UncPath): string | undefined {\n const canonical = normalizeUncRoot(path.canonical);\n const mapping = queryDriveMappings().find(\n ({ remote }) => canonical === remote || canonical.startsWith(`${remote}\\\\`),\n );\n if (mapping === undefined) {\n return undefined;\n }\n const relative = path.canonical.slice(mapping.remote.length);\n return nodePath.win32.normalize(`${mapping.drive}${relative}`);\n}\nfunction isLocalServer(value: string): boolean {\n const normalized = normalizeServerName(value);\n return (\n localServerNames.has(normalized) ||\n (isIP(value) === 4 && value.split(\".\")[0] === \"127\") ||\n normalized === \"--1.ipv6-literal.net\"\n );\n}\nfunction resolveLocalAdministrativeShare(path: UncPath): string | undefined {\n const match = /^([A-Za-z])\\$$/u.exec(path.share);\n if (match === null || !isLocalServer(path.server)) {\n return undefined;\n }\n return nodePath.win32.normalize(`${match[1]}:${path.suffix || \"\\\\\"}`);\n}\nexport function resolveUncPath(value: string): string | undefined {\n if (process.platform !== \"win32\" || (!value.startsWith(\"\\\\\\\\\") && !value.startsWith(\"//\"))) {\n return value;\n }\n if (containsControlCharacter(value)) {\n return undefined;\n }\n const path = parseUncPath(value);\n if (path === undefined) {\n return undefined;\n }\n return resolveMappedUncPath(path) ?? resolveLocalAdministrativeShare(path);\n}\n","import { stat } from \"node:fs/promises\";\nimport nodePath from \"node:path\";\nimport fastGlob from \"fast-glob\";\nimport { convertPathToPattern, globby } from \"globby\";\nimport { settings } from \"../../config/settings.js\";\nimport { resolveUncPath } from \"../native/unc.js\";\nimport type { SearchEntry } from \"../types.js\";\n\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction isWithinRoot(filePath: string, root: string): boolean {\n const relative = nodePath.relative(root, filePath);\n return (\n relative === \"\" ||\n (relative !== \"..\" &&\n !relative.startsWith(`..${nodePath.sep}`) &&\n !nodePath.isAbsolute(relative))\n );\n}\nfunction isHidden(relativePath: string): boolean {\n return relativePath.split(/[\\\\/]/u).some((part) => part.length > 1 && part.startsWith(\".\"));\n}\nfunction traversalOptions(root: string, searchHidden: boolean) {\n return {\n caseSensitiveMatch: process.platform !== \"win32\",\n cwd: root,\n dot: searchHidden,\n followSymbolicLinks: false,\n onlyFiles: false,\n unique: true,\n } as const;\n}\nfunction globbyOptions(root: string, respectIgnore: boolean, searchHidden: boolean) {\n return {\n ...traversalOptions(root, searchHidden),\n expandDirectories: false,\n gitignore: respectIgnore,\n globalGitignore: respectIgnore,\n ...(respectIgnore ? { ignoreFiles: settings.ignoreFilePatterns } : {}),\n } as const;\n}\nexport async function resolveSearchDirectories(directories: readonly string[]): Promise<string[]> {\n if (!Array.isArray(directories)) {\n throw new TypeError(\"directories must be an array\");\n }\n if (directories.length === 0) {\n throw new RangeError(\"directories must not be empty\");\n }\n const unique = new Map<string, string>();\n for (const directory of directories) {\n if (typeof directory !== \"string\" || directory.length === 0) {\n throw new TypeError(\"every directory must be a non-empty string\");\n }\n const resolvedUnc = resolveUncPath(directory);\n if (resolvedUnc === undefined || resolvedUnc.length === 0) {\n throw new TypeError(`${directory} cannot be represented as a drive-based path`);\n }\n const resolved = nodePath.resolve(resolvedUnc);\n unique.set(pathKey(resolved), resolved);\n }\n await Promise.all(\n [...unique.values()].map(async (directory) => {\n if (!(await stat(directory)).isDirectory()) {\n throw new TypeError(`${directory} is not a directory`);\n }\n }),\n );\n return [...unique.values()];\n}\nexport async function listSearchEntries(\n root: string,\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<SearchEntry[]> {\n const entries = !respectIgnore\n ? await fastGlob(\"**/*\", { ...traversalOptions(root, searchHidden), objectMode: true })\n : await globby(\"**/*\", {\n ...globbyOptions(root, respectIgnore, searchHidden),\n objectMode: true,\n });\n return entries.map((entry) => ({\n directory: entry.dirent.isDirectory(),\n path: entry.path,\n }));\n}\nexport async function filterSearchablePaths(\n paths: readonly string[],\n roots: readonly string[],\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<Set<string>> {\n const allowed = new Set<string>();\n const pathsByRoot = new Map<string, string[]>();\n for (const filePath of paths) {\n let hasSearchRoot = false;\n for (const root of roots) {\n if (!isWithinRoot(filePath, root)) {\n continue;\n }\n hasSearchRoot = true;\n const relative = nodePath.relative(root, filePath);\n if (!searchHidden && isHidden(relative)) {\n continue;\n }\n if (relative === \"\" || !respectIgnore) {\n allowed.add(filePath);\n } else {\n const grouped = pathsByRoot.get(root) ?? [];\n grouped.push(relative);\n pathsByRoot.set(root, grouped);\n }\n }\n if (hasSearchRoot) {\n continue;\n }\n const filesystemRelative = nodePath.relative(nodePath.parse(filePath).root, filePath);\n if (searchHidden || !isHidden(filesystemRelative)) {\n allowed.add(filePath);\n }\n }\n await Promise.all(\n [...pathsByRoot].map(async ([root, relativePaths]) => {\n const patterns = relativePaths.map(convertPathToPattern);\n const matches = await globby(patterns, {\n ...globbyOptions(root, true, true),\n absolute: true,\n });\n for (const match of matches) {\n allowed.add(nodePath.normalize(match));\n }\n }),\n );\n return allowed;\n}\n","import { fileURLToPath } from \"node:url\";\nimport nodePath from \"node:path\";\nimport { classifyExistingPaths } from \"./existence.js\";\nimport { removeContainedMatches } from \"./containment.js\";\nimport { filterSearchablePaths } from \"../search/policy.js\";\nimport { expandVariables } from \"../variables.js\";\nimport { resolveUncPath } from \"../native/unc.js\";\nimport { settings } from \"../../config/settings.js\";\nimport type {\n Candidate,\n PathKind,\n PathLocation,\n PathMatch,\n PathPosition,\n Variables,\n} from \"../types.js\";\n\ninterface ResolvedCandidate {\n expectedKind?: PathKind;\n location?: PathLocation;\n path: string;\n position: PathPosition;\n}\ntype PreparedCandidate = Pick<ResolvedCandidate, \"location\" | \"position\"> & { value: string };\nfunction pathKey(value: string): string {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\nfunction uniquePaths(values: Iterable<string>): string[] {\n const paths = new Map<string, string>();\n for (const value of values) {\n paths.set(pathKey(value), value);\n }\n return [...paths.values()];\n}\nfunction parseLocationPart(value: string, name: string): number {\n const result = Number(value);\n if (!Number.isSafeInteger(result)) {\n throw new RangeError(`${name} must be a safe integer`);\n }\n return result;\n}\nfunction prepareCandidate(candidate: Candidate): PreparedCandidate {\n let end = candidate.end;\n let start = candidate.start;\n let value = candidate.value;\n if (candidate.kind !== \"inventory\" && candidate.kind !== \"quoted\") {\n const startTrimmed = value.trimStart();\n start += value.length - startTrimmed.length;\n value = startTrimmed;\n const endTrimmed = value.trimEnd();\n end -= value.length - endTrimmed.length;\n value = endTrimmed;\n if (\n value.length >= 2 &&\n ((value[0] === '\"' && value.at(-1) === '\"') ||\n (value[0] === \"'\" && value.at(-1) === \"'\") ||\n (value[0] === \"`\" && value.at(-1) === \"`\"))\n ) {\n start += 1;\n end -= 1;\n value = value.slice(1, -1);\n }\n while (value.length > 0 && settings.trailingPunctuation.includes(value.at(-1) ?? \"\")) {\n end -= 1;\n value = value.slice(0, -1);\n }\n }\n if (candidate.kind === \"inventory\") {\n return { position: { end, start }, value };\n }\n const match = settings.locationSuffixPattern.exec(value);\n if (match === null) {\n return { position: { end, start }, value };\n }\n const lineValue = match.groups?.line;\n if (lineValue === undefined) {\n throw new TypeError(\"locationSuffixPattern must capture a line\");\n }\n const columnValue = match.groups?.column;\n const location: PathLocation =\n columnValue === undefined\n ? { line: parseLocationPart(lineValue, \"line\") }\n : {\n column: parseLocationPart(columnValue, \"column\"),\n line: parseLocationPart(lineValue, \"line\"),\n };\n end -= match[0].length;\n return {\n location,\n position: { end, start },\n value: value.slice(0, match.index),\n };\n}\nfunction unescape(value: string): string {\n if (value.startsWith(\"\\\\\\\\\") && !value.startsWith(\"\\\\\\\\\\\\\\\\\")) {\n return value;\n }\n return value.replace(/\\\\([\"'`\\\\])/gu, \"$1\").replace(/\\\\\\\\/gu, \"\\\\\");\n}\nfunction toPaths(value: string, roots: readonly string[], variables: Variables): string[] {\n let expanded = expandVariables(value, variables);\n if (expanded.startsWith(\"file://\")) {\n try {\n expanded = fileURLToPath(expanded);\n } catch (error) {\n if (error instanceof TypeError) {\n return [];\n }\n throw error;\n }\n } else {\n expanded = unescape(expanded);\n if (expanded === \"~\" || /^~[\\\\/]/u.test(expanded)) {\n expanded = nodePath.join(\n variables.HOME ??\n variables.USERPROFILE ??\n process.env.HOME ??\n process.env.USERPROFILE ??\n \"\",\n expanded.slice(2),\n );\n }\n }\n const resolvedPath = resolveUncPath(expanded);\n if (resolvedPath === undefined || resolvedPath.length === 0) {\n return [];\n }\n expanded = resolvedPath;\n if (nodePath.isAbsolute(expanded)) {\n return [nodePath.normalize(expanded)];\n }\n return uniquePaths(roots.map((root) => nodePath.resolve(root, expanded)));\n}\nfunction mergeLocation(match: PathMatch, location: PathLocation | undefined): void {\n if (location === undefined) {\n return;\n }\n if (match.location === undefined) {\n match.location = location;\n return;\n }\n if (match.location.line !== location.line || match.location.column !== location.column) {\n throw new Error(\"Candidates for the same path and position have conflicting locations\");\n }\n}\nexport async function validateCandidates(\n candidates: Candidate[],\n roots: readonly string[],\n variables: Variables,\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<PathMatch[]> {\n const resolvedCandidates: ResolvedCandidate[] = [];\n const validationPaths = new Map<string, string>();\n for (const candidate of candidates) {\n const prepared = prepareCandidate(candidate);\n const paths = toPaths(prepared.value, roots, variables);\n for (const filePath of paths) {\n resolvedCandidates.push({\n ...(candidate.expectedKind === undefined ? {} : { expectedKind: candidate.expectedKind }),\n ...(prepared.location === undefined ? {} : { location: prepared.location }),\n path: filePath,\n position: prepared.position,\n });\n validationPaths.set(pathKey(filePath), filePath);\n }\n }\n let searchablePaths = [...validationPaths.values()];\n if (respectIgnore || !searchHidden) {\n searchablePaths = [\n ...(await filterSearchablePaths(searchablePaths, roots, respectIgnore, searchHidden)),\n ];\n }\n const classifiedPaths = await classifyExistingPaths(searchablePaths, roots);\n const kindsByPath = new Map(\n [...classifiedPaths].map(([filePath, kind]) => [pathKey(filePath), kind]),\n );\n const matches = new Map<string, PathMatch>();\n for (const { expectedKind, location, path, position } of resolvedCandidates) {\n const kind = kindsByPath.get(pathKey(path));\n if (kind === undefined || (expectedKind !== undefined && kind !== expectedKind)) {\n continue;\n }\n const key = `${pathKey(path)}\\0${position.start}\\0${position.end}`;\n const existing = matches.get(key);\n if (existing !== undefined) {\n mergeLocation(existing, location);\n continue;\n }\n matches.set(key, {\n kind,\n ...(location === undefined ? {} : { location }),\n path,\n position,\n });\n }\n return removeContainedMatches([...matches.values()]);\n}\n","import nodePath from \"node:path\";\nimport { AhoCorasick } from \"@monyone/aho-corasick\";\nimport { listSearchEntries } from \"./policy.js\";\nimport type {\n Candidate,\n InventoryMatcher,\n InventoryPattern,\n RootPrefix,\n SearchEntry,\n} from \"../types.js\";\n\nlet inventoryMatcherCache: InventoryMatcher | undefined;\nfunction isBoundary(\n value: string | undefined,\n following: string | undefined,\n directoryEnd = false,\n): boolean {\n if (directoryEnd && value !== \".\") {\n return value === undefined || /[\\s\"'`<>)\\]},;:!?,。;:!?、]/u.test(value);\n }\n if (value === \".\") {\n return following === undefined || !/[\\p{L}\\p{N}_-]/u.test(following);\n }\n return value === undefined || !/[\\p{L}\\p{N}_/\\\\-]/u.test(value);\n}\nfunction addMatch(\n result: Candidate[],\n seen: Set<string>,\n text: string,\n value: string,\n start: number,\n end: number,\n expectedKind: InventoryPattern[\"expectedKind\"],\n): void {\n if (\n !isBoundary(text[start - 1], text[start]) ||\n !isBoundary(text[end], text[end + 1], expectedKind === \"directory\")\n ) {\n return;\n }\n const key = `${start}:${end}:${text.slice(start, end)}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push({ end, expectedKind, kind: \"inventory\", start, value });\n }\n}\nfunction addVariant(\n patterns: Map<string, InventoryPattern>,\n entry: SearchEntry,\n value: string,\n): void {\n const key = process.platform === \"win32\" ? value.toLowerCase() : value;\n if (!patterns.has(key)) {\n patterns.set(key, {\n expectedKind: entry.directory ? \"directory\" : \"file\",\n relative: entry.path,\n value,\n });\n }\n}\nfunction addEntryVariants(patterns: Map<string, InventoryPattern>, entry: SearchEntry): void {\n const native = entry.path.replaceAll(\"/\", nodePath.sep);\n if (entry.directory) {\n addVariant(patterns, entry, `${entry.path}/`);\n addVariant(patterns, entry, `${native}${nodePath.sep}`);\n return;\n }\n addVariant(patterns, entry, entry.path);\n addVariant(patterns, entry, native);\n}\nfunction createRootPrefixes(roots: readonly string[]): RootPrefix[] {\n const prefixes = new Map<string, RootPrefix>();\n for (const root of roots) {\n const native = root.endsWith(nodePath.sep) ? root : `${root}${nodePath.sep}`;\n const slashRoot = root.replaceAll(nodePath.sep, \"/\");\n const slash = slashRoot.endsWith(\"/\") ? slashRoot : `${slashRoot}/`;\n for (const value of [native, slash]) {\n const key = process.platform === \"win32\" ? value.toLowerCase() : value;\n prefixes.set(key, { root, value: key });\n }\n }\n return [...prefixes.values()];\n}\nfunction addAbsoluteMatch(\n result: Candidate[],\n seen: Set<string>,\n source: string,\n text: string,\n pattern: InventoryPattern,\n prefixes: readonly RootPrefix[],\n end: number,\n relativeStart: number,\n): boolean {\n for (const prefix of prefixes) {\n const start = relativeStart - prefix.value.length;\n if (start >= 0 && source.startsWith(prefix.value, start)) {\n addMatch(\n result,\n seen,\n text,\n nodePath.resolve(prefix.root, pattern.relative),\n start,\n end,\n pattern.expectedKind,\n );\n return true;\n }\n }\n return false;\n}\nfunction hasSameEntries(\n cached: InventoryMatcher,\n entries: readonly (readonly SearchEntry[])[],\n): boolean {\n if (cached.entries.length !== entries.length) {\n return false;\n }\n for (let index = 0; index < entries.length; index += 1) {\n const cachedEntries = cached.entries[index];\n const currentEntries = entries[index];\n if (cachedEntries === undefined || currentEntries === undefined) {\n return false;\n }\n if (cachedEntries.length !== currentEntries.length) {\n return false;\n }\n for (let entryIndex = 0; entryIndex < currentEntries.length; entryIndex += 1) {\n const cachedEntry = cachedEntries[entryIndex];\n const currentEntry = currentEntries[entryIndex];\n if (\n cachedEntry === undefined ||\n currentEntry === undefined ||\n cachedEntry.directory !== currentEntry.directory ||\n cachedEntry.path !== currentEntry.path\n ) {\n return false;\n }\n }\n }\n return true;\n}\nfunction canReuseMatcher(\n cached: InventoryMatcher | undefined,\n entries: readonly (readonly SearchEntry[])[],\n roots: readonly string[],\n respectIgnore: boolean,\n searchHidden: boolean,\n): cached is InventoryMatcher {\n return (\n cached !== undefined &&\n cached.respectIgnore === respectIgnore &&\n cached.searchHidden === searchHidden &&\n cached.roots.length === roots.length &&\n cached.roots.every((root, index) => root === roots[index]) &&\n hasSameEntries(cached, entries)\n );\n}\nexport async function inventoryCandidates(\n text: string,\n roots: readonly string[],\n respectIgnore: boolean,\n searchHidden: boolean,\n): Promise<Candidate[]> {\n const entries = await Promise.all(\n roots.map((root) => listSearchEntries(root, respectIgnore, searchHidden)),\n );\n const result: Candidate[] = [];\n const seen = new Set<string>();\n const source = process.platform === \"win32\" ? text.toLowerCase() : text;\n let inventoryMatcher = inventoryMatcherCache;\n if (!canReuseMatcher(inventoryMatcher, entries, roots, respectIgnore, searchHidden)) {\n const patterns = new Map<string, InventoryPattern>();\n for (const relativeEntries of entries) {\n for (const entry of relativeEntries) {\n addEntryVariants(patterns, entry);\n }\n }\n inventoryMatcher = {\n entries,\n matcher: new AhoCorasick([...patterns.keys()]),\n patterns,\n prefixes: createRootPrefixes(roots),\n respectIgnore,\n roots: [...roots],\n searchHidden,\n };\n inventoryMatcherCache = inventoryMatcher;\n }\n for (const { begin, end, keyword } of inventoryMatcher.matcher.matchInText(source)) {\n const pattern = inventoryMatcher.patterns.get(keyword);\n if (pattern === undefined) {\n throw new Error(\"Inventory matcher returned an unknown path\");\n }\n if (\n !addAbsoluteMatch(result, seen, source, text, pattern, inventoryMatcher.prefixes, end, begin)\n ) {\n addMatch(result, seen, text, pattern.value, begin, end, pattern.expectedKind);\n }\n }\n return result;\n}\n","import { extractCandidates } from \"./candidates.js\";\nimport { validateCandidates } from \"./validation/filesystem.js\";\nimport { inventoryCandidates } from \"./search/inventory.js\";\nimport { resolveSearchDirectories } from \"./search/policy.js\";\nimport { settings } from \"../config/settings.js\";\nimport type { FindExistingPathsOptions, PathMatch, Variables } from \"./types.js\";\n\nexport const MAX_LEVEL = settings.spanWordLimits.length + 3;\nfunction validateOptions(value: unknown): asserts value is FindExistingPathsOptions {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"options must be an object\");\n }\n}\nfunction validateVariables(value: unknown): asserts value is Variables {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n Object.values(value).some((item) => typeof item !== \"string\")\n ) {\n throw new TypeError(\"variables must be an object of string values\");\n }\n}\nexport async function findExistingPaths(options: FindExistingPathsOptions): Promise<PathMatch[]> {\n validateOptions(options);\n const {\n directories,\n level,\n respectIgnore = settings.respectIgnoreByDefault,\n searchHidden = settings.searchHiddenByDefault,\n text,\n variables = {},\n } = options;\n if (typeof text !== \"string\") {\n throw new TypeError(\"text must be a string\");\n }\n if (!Number.isInteger(level) || level < 1 || level > MAX_LEVEL) {\n throw new RangeError(`level must be an integer from 1 to ${MAX_LEVEL}`);\n }\n validateVariables(variables);\n if (typeof respectIgnore !== \"boolean\") {\n throw new TypeError(\"respectIgnore must be a boolean\");\n }\n if (typeof searchHidden !== \"boolean\") {\n throw new TypeError(\"searchHidden must be a boolean\");\n }\n const roots = await resolveSearchDirectories(directories);\n const candidates = extractCandidates(text, level);\n if (level === MAX_LEVEL) {\n candidates.push(...(await inventoryCandidates(text, roots, respectIgnore, searchHidden)));\n }\n return validateCandidates(candidates, roots, variables, respectIgnore, searchHidden);\n}\nexport type {\n FindExistingPathsOptions,\n PathKind,\n PathLocation,\n PathMatch,\n PathPosition,\n SearchLevel,\n Variables,\n} from \"./types.js\";\n"],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ const { Buffer } = require("node:buffer");
2
+ let connectionApi;
3
+ function getDriveConnection(drive, bufferChars) {
4
+ if (connectionApi === undefined) {
5
+ const koffi = require("koffi");
6
+ const getConnectionW = koffi
7
+ .load("mpr.dll")
8
+ .func(
9
+ "uint32_t WNetGetConnectionW(const char16_t *lpLocalName, _Out_ char16_t *lpRemoteName, _Inout_ uint32_t *lpnLength)",
10
+ );
11
+ connectionApi = { getConnectionW, koffi };
12
+ }
13
+ const buffer = Buffer.alloc(bufferChars * 2);
14
+ const length = [bufferChars];
15
+ const status = connectionApi.getConnectionW(drive, buffer, length);
16
+ const remote =
17
+ status === 0 ? connectionApi.koffi.decode(buffer, "char16_t", bufferChars) : undefined;
18
+ return { remote, status };
19
+ }
20
+ module.exports = { getDriveConnection };
@@ -1,4 +1,4 @@
1
- import type { PathMatch, SearchLevel, Variables } from "./types.js";
1
+ import type { FindExistingPathsOptions, PathMatch } from "./types.js";
2
2
  export declare const MAX_LEVEL: number;
3
- export declare function findExistingPaths(text: string, level: SearchLevel, directories: readonly string[], variables?: Variables, respectIgnore?: boolean, searchHidden?: boolean): Promise<PathMatch[]>;
4
- export type { PathKind, PathLocation, PathMatch, PathPosition, SearchLevel, Variables, } from "./types.js";
3
+ export declare function findExistingPaths(options: FindExistingPathsOptions): Promise<PathMatch[]>;
4
+ export type { FindExistingPathsOptions, PathKind, PathLocation, PathMatch, PathPosition, SearchLevel, Variables, } from "./types.js";
@@ -1,2 +1,2 @@
1
- import type { Candidate } from "./types.js";
1
+ import type { Candidate } from "../types.js";
2
2
  export declare function inventoryCandidates(text: string, roots: readonly string[], respectIgnore: boolean, searchHidden: boolean): Promise<Candidate[]>;
@@ -1,3 +1,4 @@
1
+ import type { SearchEntry } from "../types.js";
1
2
  export declare function resolveSearchDirectories(directories: readonly string[]): Promise<string[]>;
2
- export declare function listSearchEntries(root: string, respectIgnore: boolean, searchHidden: boolean): Promise<string[]>;
3
+ export declare function listSearchEntries(root: string, respectIgnore: boolean, searchHidden: boolean): Promise<SearchEntry[]>;
3
4
  export declare function filterSearchablePaths(paths: readonly string[], roots: readonly string[], respectIgnore: boolean, searchHidden: boolean): Promise<Set<string>>;
@@ -1,3 +1,4 @@
1
+ import type { AhoCorasick } from "@monyone/aho-corasick";
1
2
  export type SearchLevel = number;
2
3
  export type PathKind = "directory" | "file";
3
4
  export interface PathPosition {
@@ -14,9 +15,40 @@ export interface PathMatch {
14
15
  path: string;
15
16
  position: PathPosition;
16
17
  }
18
+ export interface FindExistingPathsOptions {
19
+ directories: readonly string[];
20
+ level: SearchLevel;
21
+ respectIgnore?: boolean;
22
+ searchHidden?: boolean;
23
+ text: string;
24
+ variables?: Variables;
25
+ }
26
+ export interface InventoryPattern {
27
+ expectedKind: PathKind;
28
+ relative: string;
29
+ value: string;
30
+ }
31
+ export interface InventoryMatcher {
32
+ entries: readonly (readonly SearchEntry[])[];
33
+ matcher: AhoCorasick;
34
+ patterns: Map<string, InventoryPattern>;
35
+ prefixes: readonly RootPrefix[];
36
+ respectIgnore: boolean;
37
+ roots: readonly string[];
38
+ searchHidden: boolean;
39
+ }
40
+ export interface RootPrefix {
41
+ root: string;
42
+ value: string;
43
+ }
44
+ export interface SearchEntry {
45
+ directory: boolean;
46
+ path: string;
47
+ }
17
48
  export type CandidateKind = "explicit" | "heuristic" | "inventory" | "quoted" | "span";
18
49
  export interface Candidate {
19
50
  end: number;
51
+ expectedKind?: PathKind;
20
52
  kind: CandidateKind;
21
53
  start: number;
22
54
  value: string;
@@ -0,0 +1,2 @@
1
+ import type { PathMatch } from "../types.js";
2
+ export declare function removeContainedMatches(matches: readonly PathMatch[]): PathMatch[];
@@ -1,2 +1,2 @@
1
- import type { PathKind } from "./types.js";
1
+ import type { PathKind } from "../types.js";
2
2
  export declare function classifyExistingPaths(paths: readonly string[], roots: readonly string[]): Promise<Map<string, PathKind>>;
@@ -1,2 +1,2 @@
1
- import type { Candidate, PathMatch, Variables } from "./types.js";
1
+ import type { Candidate, PathMatch, Variables } from "../types.js";
2
2
  export declare function validateCandidates(candidates: Candidate[], roots: readonly string[], variables: Variables, respectIgnore: boolean, searchHidden: boolean): Promise<PathMatch[]>;
@@ -1,3 +1,3 @@
1
- import type { Variables } from "../types.js";
1
+ import type { Variables } from "./types.js";
2
2
  export declare const variableReferenceSource: string;
3
3
  export declare function expandVariables(value: string, variables: Variables): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pathprobe",
3
- "version": "0.5.4",
3
+ "version": "0.6.7",
4
4
  "description": "Extract, resolve, and validate file and directory paths mentioned in text, with variable expansion, ignore rules, hidden-file control, and configurable search roots.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -15,9 +15,6 @@
15
15
  ".": {
16
16
  "types": "./dist/types/src/index.d.ts",
17
17
  "import": "./dist/index.mjs"
18
- },
19
- "./native-loader": {
20
- "require": "./dist/native-loader.cjs"
21
18
  }
22
19
  },
23
20
  "scripts": {
@@ -30,6 +27,7 @@
30
27
  "test:benchmark:bun": "bun quality/benchmark/run.mjs"
31
28
  },
32
29
  "dependencies": {
30
+ "@monyone/aho-corasick": "latest",
33
31
  "fast-glob": "latest",
34
32
  "globby": "latest",
35
33
  "koffi": "latest",
@@ -1,16 +0,0 @@
1
- const { Buffer } = require("node:buffer");
2
- const koffi = require("koffi");
3
-
4
- const getConnectionW = koffi
5
- .load("mpr.dll")
6
- .func(
7
- "uint32_t WNetGetConnectionW(const char16_t *lpLocalName, _Out_ char16_t *lpRemoteName, _Inout_ uint32_t *lpnLength)",
8
- );
9
- function getDriveConnection(drive, bufferChars) {
10
- const buffer = Buffer.alloc(bufferChars * 2);
11
- const length = [bufferChars];
12
- const status = getConnectionW(drive, buffer, length);
13
- const remote = status === 0 ? koffi.decode(buffer, "char16_t", bufferChars) : undefined;
14
- return { remote, status };
15
- }
16
- module.exports = { getDriveConnection };