@paparats/shared 2.6.2 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,11 +13,15 @@ npm install @paparats/shared
13
13
  ### Path Validation
14
14
 
15
15
  ```ts
16
- import { validateIndexingPaths } from '@paparats/shared';
16
+ import { validateIndexingPaths, filterFilesWithinRoot } from '@paparats/shared';
17
17
 
18
- // Rejects absolute paths and path traversal in indexing config
19
- const errors = validateIndexingPaths(['src', '../etc/passwd']);
20
- // errors: ['Path traversal not allowed: ../etc/passwd']
18
+ // Throws on absolute paths, path traversal, glob syntax that could expand to a
19
+ // traversal ({..,src}, [.][.]), and symlinked directories leading outside the project
20
+ validateIndexingPaths(['src', '../etc/passwd'], '/path/to/repo');
21
+ // Error: Path must be inside project directory: ../etc/passwd
22
+
23
+ // Drop globbed files whose real path is outside the root, inside .git, or a dangling link
24
+ const safe = filterFilesWithinRoot(allFiles, '/path/to/repo');
21
25
  ```
22
26
 
23
27
  ### Gitignore Filtering
@@ -46,8 +50,11 @@ import {
46
50
  DEFAULT_EXCLUDE_BARE,
47
51
  } from '@paparats/shared';
48
52
 
49
- // Bare dir names become glob patterns: 'node_modules' -> '**/node_modules/**'
50
- const patterns = normalizeExcludePatterns(['node_modules', 'dist']);
53
+ // .gitignore-style: bare names match at any depth, paths with '/' are root-relative,
54
+ // and both cover everything beneath a matching directory:
55
+ // 'node_modules' -> '**/node_modules', '**/node_modules/**'
56
+ // 'spec/fixtures' -> 'spec/fixtures', 'spec/fixtures/**'
57
+ const patterns = normalizeExcludePatterns(['node_modules', 'spec/fixtures']);
51
58
 
52
59
  // Get default excludes for specific languages
53
60
  const excludes = getDefaultExcludeForLanguages(['typescript', 'python']);
@@ -1,6 +1,2 @@
1
- /**
2
- * Normalize exclude patterns: bare dir names become glob patterns to ignore entire dirs.
3
- * Patterns with / or ** are left unchanged.
4
- */
5
1
  export declare function normalizeExcludePatterns(patterns: string[]): string[];
6
2
  //# sourceMappingURL=exclude-patterns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exclude-patterns.d.ts","sourceRoot":"","sources":["../src/exclude-patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAKrE"}
1
+ {"version":3,"file":"exclude-patterns.d.ts","sourceRoot":"","sources":["../src/exclude-patterns.ts"],"names":[],"mappings":"AAgBA,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAoBrE"}
@@ -1,12 +1,40 @@
1
- /**
2
- * Normalize exclude patterns: bare dir names become glob patterns to ignore entire dirs.
3
- * Patterns with / or ** are left unchanged.
4
- */
1
+ // Normalize exclude patterns into globs usable as glob's `ignore` option.
2
+ //
3
+ // glob matches an ignore pattern against the whole relative path, so a raw
4
+ // `spec/fixtures` only drops a file literally named `spec/fixtures` and keeps
5
+ // everything inside it. Semantics follow .gitignore:
6
+ //
7
+ // - patterns containing `**` are left unchanged: the author spelled out depth;
8
+ // - a pattern with a `/` (or `./`) at the start or in the middle is anchored
9
+ // to the project root: `spec/fixtures` -> `spec/fixtures` + `spec/fixtures/**`;
10
+ // - anything else matches at any depth: `node_modules` -> `**/node_modules` +
11
+ // `**/node_modules/**`, `*.class` -> `**/*.class` + `**/*.class/**`.
12
+ //
13
+ // Leading `./` and trailing `/` are dropped. Output is de-duplicated, and
14
+ // normalizing it again changes nothing — except a root-anchored single name
15
+ // (`/tmp` -> `tmp`), which a second pass widens to any depth: more excluded,
16
+ // never less.
5
17
  export function normalizeExcludePatterns(patterns) {
6
- return patterns.map((p) => {
7
- if (p.includes('/') || p.includes('**'))
8
- return p;
9
- return `**/${p.replace(/^\//, '')}/**`;
10
- });
18
+ const out = new Set();
19
+ for (const raw of patterns) {
20
+ const pattern = raw.trim();
21
+ if (!pattern)
22
+ continue;
23
+ if (pattern.includes('**')) {
24
+ out.add(pattern);
25
+ continue;
26
+ }
27
+ const body = pattern
28
+ .replace(/^(\.\/)+/, '')
29
+ .replace(/^\/+/, '')
30
+ .replace(/\/+$/, '');
31
+ if (!body)
32
+ continue;
33
+ const anchored = /^\.?\//.test(pattern) || body.includes('/');
34
+ const base = anchored ? body : `**/${body}`;
35
+ out.add(base);
36
+ out.add(`${base}/**`);
37
+ }
38
+ return Array.from(out);
11
39
  }
12
40
  //# sourceMappingURL=exclude-patterns.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"exclude-patterns.js","sourceRoot":"","sources":["../src/exclude-patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAkB;IACzD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAClD,OAAO,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"exclude-patterns.js","sourceRoot":"","sources":["../src/exclude-patterns.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,qDAAqD;AACrD,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,kFAAkF;AAClF,8EAA8E;AAC9E,uEAAuE;AACvE,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,cAAc;AACd,MAAM,UAAU,wBAAwB,CAAC,QAAkB;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACjB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,OAAO;aACjB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;aACvB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;aACnB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACd,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=exclude-patterns.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclude-patterns.test.d.ts","sourceRoot":"","sources":["../src/exclude-patterns.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import fs from 'fs';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import { glob } from 'glob';
6
+ import { normalizeExcludePatterns } from './exclude-patterns.js';
7
+ import { LANGUAGE_EXCLUDE_DEFAULTS } from './language-excludes.js';
8
+ describe('normalizeExcludePatterns', () => {
9
+ it('matches bare names at any depth, as file or directory', () => {
10
+ expect(normalizeExcludePatterns(['node_modules', '*.class'])).toEqual([
11
+ '**/node_modules',
12
+ '**/node_modules/**',
13
+ '**/*.class',
14
+ '**/*.class/**',
15
+ ]);
16
+ });
17
+ it('anchors patterns containing a slash and also matches their contents', () => {
18
+ expect(normalizeExcludePatterns(['spec/fixtures', 'app/assets/builds'])).toEqual([
19
+ 'spec/fixtures',
20
+ 'spec/fixtures/**',
21
+ 'app/assets/builds',
22
+ 'app/assets/builds/**',
23
+ ]);
24
+ });
25
+ it('treats a trailing slash as a directory name, a leading slash as root-anchored', () => {
26
+ expect(normalizeExcludePatterns(['vendor/', '/tmp', './log'])).toEqual([
27
+ '**/vendor',
28
+ '**/vendor/**',
29
+ 'tmp',
30
+ 'tmp/**',
31
+ 'log',
32
+ 'log/**',
33
+ ]);
34
+ });
35
+ it('leaves explicit ** patterns unchanged and drops empties and duplicates', () => {
36
+ expect(normalizeExcludePatterns(['**/*.min.js', '', ' / ', 'dist', 'dist', '**/node_modules/**'])).toEqual(['**/*.min.js', '**/dist', '**/dist/**', '**/node_modules/**']);
37
+ });
38
+ it('is stable when applied twice (server and CLI re-normalize the built-in defaults)', () => {
39
+ const once = normalizeExcludePatterns(['vendor', 'spec/fixtures', '*.class', '**/a/**']);
40
+ expect(normalizeExcludePatterns(once)).toEqual(once);
41
+ // A root-anchored single name is the exception: a second pass widens it to
42
+ // any depth, which excludes more, never less.
43
+ expect(normalizeExcludePatterns(normalizeExcludePatterns(['/tmp']))).toEqual(expect.arrayContaining(['tmp/**', '**/tmp/**']));
44
+ });
45
+ // End-to-end against the glob version the indexers use: an ignore list that
46
+ // looks right but matches nothing is exactly the bug this guards.
47
+ describe('with glob ignore', () => {
48
+ let root;
49
+ const files = [
50
+ 'spec/fixtures/a.rb',
51
+ 'spec/fixtures/deep/b.rb',
52
+ 'app/assets/builds/c.rb',
53
+ 'public/packs/d.rb',
54
+ 'vendor/x/e.rb',
55
+ 'lib/vendor/f.rb',
56
+ 'tmp/g.rb',
57
+ 'lib/tmp/h.rb',
58
+ 'app/models/user.rb',
59
+ 'build/Foo.class',
60
+ 'src/Bar.class',
61
+ ];
62
+ beforeAll(() => {
63
+ root = fs.mkdtempSync(path.join(os.tmpdir(), 'paparats-exclude-'));
64
+ for (const f of files) {
65
+ fs.mkdirSync(path.dirname(path.join(root, f)), { recursive: true });
66
+ fs.writeFileSync(path.join(root, f), 'x');
67
+ }
68
+ });
69
+ afterAll(() => {
70
+ fs.rmSync(root, { recursive: true, force: true });
71
+ });
72
+ const run = (exclude) => glob('**/*', {
73
+ cwd: root,
74
+ nodir: true,
75
+ ignore: normalizeExcludePatterns(exclude),
76
+ }).then((found) => found.map((f) => f.split(path.sep).join('/')).sort());
77
+ it('excludes directory contents for slash-containing patterns', async () => {
78
+ const found = await run(['spec/fixtures', 'app/assets/builds/']);
79
+ expect(found).not.toContain('spec/fixtures/a.rb');
80
+ expect(found).not.toContain('spec/fixtures/deep/b.rb');
81
+ expect(found).not.toContain('app/assets/builds/c.rb');
82
+ expect(found).toContain('app/models/user.rb');
83
+ });
84
+ it('anchors `/tmp` to the root but matches bare `vendor` at any depth', async () => {
85
+ const found = await run(['/tmp', 'vendor']);
86
+ expect(found).not.toContain('tmp/g.rb');
87
+ expect(found).toContain('lib/tmp/h.rb');
88
+ expect(found).not.toContain('vendor/x/e.rb');
89
+ expect(found).not.toContain('lib/vendor/f.rb');
90
+ });
91
+ it('applies the built-in ruby and java defaults', async () => {
92
+ const found = await run([
93
+ ...LANGUAGE_EXCLUDE_DEFAULTS.ruby,
94
+ ...LANGUAGE_EXCLUDE_DEFAULTS.java,
95
+ ]);
96
+ expect(found).not.toContain('public/packs/d.rb');
97
+ expect(found).not.toContain('src/Bar.class');
98
+ expect(found).not.toContain('build/Foo.class');
99
+ expect(found).toContain('app/models/user.rb');
100
+ });
101
+ });
102
+ });
103
+ //# sourceMappingURL=exclude-patterns.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclude-patterns.test.js","sourceRoot":"","sources":["../src/exclude-patterns.test.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { validateIndexingPaths } from './path-validation.js';
1
+ export { validateIndexingPaths, filterFilesWithinRoot } from './path-validation.js';
2
2
  export { normalizeExcludePatterns } from './exclude-patterns.js';
3
3
  export { LANGUAGE_EXCLUDE_DEFAULTS, COMMON_EXCLUDE, DEFAULT_EXCLUDE_BARE, getDefaultExcludeForLanguages, } from './language-excludes.js';
4
4
  export { createGitignoreFilter, filterFilesByGitignore } from './gitignore.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { validateIndexingPaths } from './path-validation.js';
1
+ export { validateIndexingPaths, filterFilesWithinRoot } from './path-validation.js';
2
2
  export { normalizeExcludePatterns } from './exclude-patterns.js';
3
3
  export { LANGUAGE_EXCLUDE_DEFAULTS, COMMON_EXCLUDE, DEFAULT_EXCLUDE_BARE, getDefaultExcludeForLanguages, } from './language-excludes.js';
4
4
  export { createGitignoreFilter, filterFilesByGitignore } from './gitignore.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAyB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAyB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -115,9 +115,9 @@ export const LANGUAGE_EXCLUDE_DEFAULTS = {
115
115
  scala: ['target', '.bsp', '.metals', '.bloop', 'project/target', 'project/project'],
116
116
  kotlin: ['build', '.gradle', '.idea', '*.iml', 'out', 'bin'],
117
117
  swift: ['.build', '.swiftpm', 'DerivedData', '*.xcodeproj', '*.xcworkspace', 'Pods'],
118
- // Secrets/state must be excluded at ANY depth. normalizeExcludePatterns leaves
119
- // patterns containing a glob unchanged, so file patterns carry an explicit `**/`
120
- // prefix (a bare `*.tfvars` would only match at the scan root).
118
+ // Secrets/state must be excluded at ANY depth. normalizeExcludePatterns already
119
+ // matches slash-free patterns at any depth; the explicit `**/` prefix keeps that
120
+ // guarantee obvious and independent of normalization.
121
121
  terraform: [
122
122
  '.terraform',
123
123
  '**/*.tfstate',
@@ -1 +1 @@
1
- {"version":3,"file":"language-excludes.js","sourceRoot":"","sources":["../src/language-excludes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"language-excludes.js","sourceRoot":"","sources":["../src/language-excludes.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,20 @@
1
1
  /**
2
- * Validate indexing paths: no absolute paths, no path traversal.
2
+ * Validate indexing paths: no absolute paths, no path traversal, no glob syntax
3
+ * that could expand to a traversal, and no symlink resolving outside the project.
3
4
  * Ensures all paths stay within the project directory to prevent
4
5
  * reading sensitive files from outside the project (e.g. via malicious .paparats.yml).
5
6
  */
6
7
  export declare function validateIndexingPaths(paths: string[], projectDir: string): void;
8
+ /**
9
+ * Drop files that must never be indexed even though a glob matched them:
10
+ * anything whose real path (symlinks resolved) is outside `root`, anything
11
+ * inside a `.git` directory (its config can carry a token-bearing remote URL),
12
+ * and dangling or unreadable links. Guards against a committed symlink such as
13
+ * `leak.ts -> ../../.ssh/id_rsa` or `notes.md -> .git/config`.
14
+ *
15
+ * Returns the surviving entries unchanged (not their real paths), in input
16
+ * order. Relative entries are resolved against `root`. Returns `[]` when `root`
17
+ * itself cannot be resolved.
18
+ */
19
+ export declare function filterFilesWithinRoot(files: string[], root: string): string[];
7
20
  //# sourceMappingURL=path-validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-validation.d.ts","sourceRoot":"","sources":["../src/path-validation.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAY/E"}
1
+ {"version":3,"file":"path-validation.d.ts","sourceRoot":"","sources":["../src/path-validation.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAuB/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ7E"}
@@ -1,20 +1,73 @@
1
+ import fs from 'fs';
1
2
  import path from 'path';
2
3
  /**
3
- * Validate indexing paths: no absolute paths, no path traversal.
4
+ * Glob syntax that can turn an innocent-looking entry into a parent-directory
5
+ * segment once the path is joined into a glob pattern: brace expansion
6
+ * (`{..,src}`), character classes (`[.][.]`), backslash escapes (`\.\.`), and
7
+ * `?`, `!` and extglob groups. `*` is allowed: it never matches `.` or `..`,
8
+ * and `app/**` is a documented way to write a subtree.
9
+ */
10
+ const UNSAFE_GLOB_CHARS = /[{}[\]?!()\\]/;
11
+ /**
12
+ * Validate indexing paths: no absolute paths, no path traversal, no glob syntax
13
+ * that could expand to a traversal, and no symlink resolving outside the project.
4
14
  * Ensures all paths stay within the project directory to prevent
5
15
  * reading sensitive files from outside the project (e.g. via malicious .paparats.yml).
6
16
  */
7
17
  export function validateIndexingPaths(paths, projectDir) {
8
18
  const resolvedProject = path.resolve(projectDir);
19
+ const realProject = realpathOrNull(resolvedProject);
9
20
  for (const p of paths) {
10
21
  if (path.isAbsolute(p)) {
11
22
  throw new Error(`Absolute paths not allowed in indexing.paths: ${p}`);
12
23
  }
24
+ if (UNSAFE_GLOB_CHARS.test(p)) {
25
+ throw new Error(`Glob syntax not allowed in indexing.paths (use plain directory names): ${p}`);
26
+ }
13
27
  const fullPath = path.resolve(projectDir, p);
14
- const relative = path.relative(resolvedProject, fullPath);
15
- if (relative.startsWith('..') || path.isAbsolute(relative)) {
28
+ if (!isInside(resolvedProject, fullPath)) {
16
29
  throw new Error(`Path must be inside project directory: ${p}`);
17
30
  }
31
+ // Lexically inside, but a symlinked directory can still point elsewhere.
32
+ // Only checkable when both ends exist; a missing path globs to nothing.
33
+ const realPath = realProject ? realpathOrNull(fullPath) : null;
34
+ if (realProject && realPath && !isInside(realProject, realPath)) {
35
+ throw new Error(`Path must be inside project directory (resolves through a symlink): ${p}`);
36
+ }
37
+ }
38
+ }
39
+ /**
40
+ * Drop files that must never be indexed even though a glob matched them:
41
+ * anything whose real path (symlinks resolved) is outside `root`, anything
42
+ * inside a `.git` directory (its config can carry a token-bearing remote URL),
43
+ * and dangling or unreadable links. Guards against a committed symlink such as
44
+ * `leak.ts -> ../../.ssh/id_rsa` or `notes.md -> .git/config`.
45
+ *
46
+ * Returns the surviving entries unchanged (not their real paths), in input
47
+ * order. Relative entries are resolved against `root`. Returns `[]` when `root`
48
+ * itself cannot be resolved.
49
+ */
50
+ export function filterFilesWithinRoot(files, root) {
51
+ const realRoot = realpathOrNull(path.resolve(root));
52
+ if (!realRoot)
53
+ return [];
54
+ return files.filter((file) => {
55
+ const real = realpathOrNull(path.resolve(root, file));
56
+ if (!real || real === realRoot || !isInside(realRoot, real))
57
+ return false;
58
+ return !path.relative(realRoot, real).split(path.sep).includes('.git');
59
+ });
60
+ }
61
+ function isInside(root, candidate) {
62
+ const rel = path.relative(root, candidate);
63
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel));
64
+ }
65
+ function realpathOrNull(p) {
66
+ try {
67
+ return fs.realpathSync.native(p);
68
+ }
69
+ catch {
70
+ return null;
18
71
  }
19
72
  }
20
73
  //# sourceMappingURL=path-validation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../src/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAe,EAAE,UAAkB;IACvE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"path-validation.js","sourceRoot":"","sources":["../src/path-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAe,EAAE,UAAkB;IACvE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,0EAA0E,CAAC,EAAE,CAC9E,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,yEAAyE;QACzE,wEAAwE;QACxE,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/D,IAAI,WAAW,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,EAAE,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAe,EAAE,IAAY;IACjE,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,SAAiB;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3C,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -1,11 +1,16 @@
1
- import { describe, it, expect } from 'vitest';
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import fs from 'fs';
3
+ import os from 'os';
2
4
  import path from 'path';
3
- import { validateIndexingPaths } from './path-validation.js';
5
+ import { validateIndexingPaths, filterFilesWithinRoot } from './path-validation.js';
4
6
  describe('validateIndexingPaths', () => {
5
7
  const projectDir = path.resolve('/some/project');
6
8
  it('accepts valid relative paths', () => {
7
9
  expect(() => validateIndexingPaths(['./', 'src', 'lib/'], projectDir)).not.toThrow();
8
10
  });
11
+ it('accepts `*` wildcards, which cannot expand to a parent directory', () => {
12
+ expect(() => validateIndexingPaths(['app/**', 'packages/*/src'], projectDir)).not.toThrow();
13
+ });
9
14
  it('rejects absolute paths', () => {
10
15
  const absolutePath = path.sep === '\\' ? 'C:\\tmp' : '/tmp';
11
16
  expect(() => validateIndexingPaths([absolutePath], projectDir)).toThrow('Absolute paths not allowed in indexing.paths');
@@ -16,5 +21,81 @@ describe('validateIndexingPaths', () => {
16
21
  it('rejects path traversal with single parent', () => {
17
22
  expect(() => validateIndexingPaths(['../'], projectDir)).toThrow('Path must be inside project directory');
18
23
  });
24
+ it.each(['{..,src}', '[.][.]', '.\\.', '?.', '!(src)', '@(..)', 'src/{a,b}'])('rejects glob syntax that can expand to a traversal: %s', (p) => {
25
+ expect(() => validateIndexingPaths([p], projectDir)).toThrow('Glob syntax not allowed in indexing.paths');
26
+ });
27
+ describe('on disk', () => {
28
+ let base;
29
+ let project;
30
+ beforeEach(() => {
31
+ base = fs.mkdtempSync(path.join(os.tmpdir(), 'paparats-paths-'));
32
+ project = path.join(base, 'project');
33
+ fs.mkdirSync(path.join(project, 'src'), { recursive: true });
34
+ fs.mkdirSync(path.join(base, 'sibling'));
35
+ });
36
+ afterEach(() => {
37
+ fs.rmSync(base, { recursive: true, force: true });
38
+ });
39
+ it('rejects a symlinked directory that resolves outside the project', () => {
40
+ fs.symlinkSync(path.join(base, 'sibling'), path.join(project, 'linked'));
41
+ expect(() => validateIndexingPaths(['linked'], project)).toThrow(/resolves through a symlink/);
42
+ });
43
+ it('accepts a symlinked directory that stays inside the project', () => {
44
+ fs.symlinkSync(path.join(project, 'src'), path.join(project, 'alias'));
45
+ expect(() => validateIndexingPaths(['alias', 'src', 'missing'], project)).not.toThrow();
46
+ });
47
+ });
48
+ });
49
+ describe('filterFilesWithinRoot', () => {
50
+ let base;
51
+ let root;
52
+ beforeEach(() => {
53
+ base = fs.mkdtempSync(path.join(os.tmpdir(), 'paparats-within-'));
54
+ root = path.join(base, 'repo');
55
+ fs.mkdirSync(path.join(root, 'src'), { recursive: true });
56
+ fs.mkdirSync(path.join(root, '.git'));
57
+ fs.writeFileSync(path.join(root, '.git', 'config'), '[remote "origin"]\n');
58
+ fs.writeFileSync(path.join(root, 'src', 'a.ts'), 'export {}');
59
+ fs.writeFileSync(path.join(base, 'outside.ts'), 'secret');
60
+ });
61
+ afterEach(() => {
62
+ fs.rmSync(base, { recursive: true, force: true });
63
+ });
64
+ it('keeps regular files and symlinks that stay inside the root', () => {
65
+ fs.symlinkSync(path.join(root, 'src', 'a.ts'), path.join(root, 'alias.ts'));
66
+ const files = [path.join(root, 'src', 'a.ts'), path.join(root, 'alias.ts')];
67
+ expect(filterFilesWithinRoot(files, root)).toEqual(files);
68
+ });
69
+ it('drops a symlink resolving outside the root', () => {
70
+ fs.symlinkSync(path.join(base, 'outside.ts'), path.join(root, 'leak.ts'));
71
+ const kept = path.join(root, 'src', 'a.ts');
72
+ expect(filterFilesWithinRoot([kept, path.join(root, 'leak.ts')], root)).toEqual([kept]);
73
+ });
74
+ it('drops a symlink into .git and files inside .git', () => {
75
+ fs.symlinkSync(path.join(root, '.git', 'config'), path.join(root, 'leak.ts'));
76
+ const files = [path.join(root, 'leak.ts'), path.join(root, '.git', 'config')];
77
+ expect(filterFilesWithinRoot(files, root)).toEqual([]);
78
+ });
79
+ it('drops files reached through a symlinked directory pointing outside', () => {
80
+ fs.symlinkSync(base, path.join(root, 'up'));
81
+ expect(filterFilesWithinRoot([path.join(root, 'up', 'outside.ts')], root)).toEqual([]);
82
+ });
83
+ it('drops dangling links and missing files', () => {
84
+ fs.symlinkSync(path.join(root, 'nowhere.ts'), path.join(root, 'dangling.ts'));
85
+ const files = [path.join(root, 'dangling.ts'), path.join(root, 'gone.ts')];
86
+ expect(filterFilesWithinRoot(files, root)).toEqual([]);
87
+ });
88
+ it('resolves relative entries against the root', () => {
89
+ expect(filterFilesWithinRoot(['src/a.ts', '../outside.ts'], root)).toEqual(['src/a.ts']);
90
+ });
91
+ it('works when the root itself is reached through a symlink', () => {
92
+ const viaLink = path.join(base, 'repo-link');
93
+ fs.symlinkSync(root, viaLink);
94
+ const file = path.join(viaLink, 'src', 'a.ts');
95
+ expect(filterFilesWithinRoot([file], viaLink)).toEqual([file]);
96
+ });
97
+ it('returns nothing when the root does not exist', () => {
98
+ expect(filterFilesWithinRoot([path.join(base, 'outside.ts')], path.join(base, 'nope'))).toEqual([]);
99
+ });
19
100
  });
20
101
  //# sourceMappingURL=path-validation.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path-validation.test.js","sourceRoot":"","sources":["../src/path-validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAEjD,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CACrE,8CAA8C,CAC/C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CACpE,uCAAuC,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAC9D,uCAAuC,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"path-validation.test.js","sourceRoot":"","sources":["../src/path-validation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAEpF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAEjD,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CACrE,8CAA8C,CAC/C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CACpE,uCAAuC,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAC9D,uCAAuC,CACxC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAC3E,wDAAwD,EACxD,CAAC,CAAC,EAAE,EAAE;QACJ,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAC1D,2CAA2C,CAC5C,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,IAAI,IAAY,CAAC;QACjB,IAAI,OAAe,CAAC;QAEpB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;YACjE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACrC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;YACzE,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAC9D,4BAA4B,CAC7B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvE,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC1F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAI,IAAY,CAAC;IACjB,IAAI,IAAY,CAAC;IAEjB,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;QAClE,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACtC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAC3E,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC;QAC9D,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5E,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,qBAAqB,CAAC,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC7C,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAC7F,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paparats/shared",
3
- "version": "2.6.2",
3
+ "version": "2.8.0",
4
4
  "type": "module",
5
5
  "description": "Shared utilities for Paparats MCP - path validation, gitignore filtering, language-aware exclude patterns",
6
6
  "license": "MIT",
@@ -53,11 +53,11 @@
53
53
  "prepublishOnly": "npm run build && npm run test"
54
54
  },
55
55
  "dependencies": {
56
- "ignore": "^7.0.5"
56
+ "ignore": "^7.0.12"
57
57
  },
58
58
  "devDependencies": {
59
- "@types/node": "^26.1.1",
60
- "typescript": "^5.9.3",
61
- "vitest": "^4.1.10"
59
+ "@types/node": "^26.6.4",
60
+ "typescript": "^6.0.3",
61
+ "vitest": "^5.0.3"
62
62
  }
63
63
  }