view-ignored 0.4.7 → 0.5.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.
Files changed (135) hide show
  1. package/README.md +64 -96
  2. package/out/index.d.ts +1 -4
  3. package/out/index.js +1 -4
  4. package/out/patterns/gitignore.d.ts +3 -0
  5. package/out/patterns/gitignore.js +35 -0
  6. package/out/patterns/index.d.ts +4 -0
  7. package/out/patterns/index.js +4 -0
  8. package/out/patterns/jsrjson.d.ts +4 -0
  9. package/out/patterns/jsrjson.js +39 -0
  10. package/out/patterns/matcher.d.ts +39 -0
  11. package/out/patterns/matcher.js +118 -0
  12. package/out/patterns/packagejson.d.ts +3 -0
  13. package/out/patterns/packagejson.js +25 -0
  14. package/out/scan.d.ts +46 -0
  15. package/out/scan.js +113 -0
  16. package/out/targets/git.d.ts +2 -0
  17. package/out/targets/git.js +22 -0
  18. package/out/targets/index.d.ts +6 -0
  19. package/out/targets/index.js +6 -0
  20. package/out/targets/jsr.d.ts +2 -0
  21. package/out/targets/jsr.js +25 -0
  22. package/out/targets/npm.d.ts +2 -0
  23. package/out/targets/npm.js +46 -0
  24. package/out/targets/target.d.ts +7 -0
  25. package/out/targets/target.js +1 -0
  26. package/out/targets/vsce.d.ts +2 -0
  27. package/out/targets/vsce.js +24 -0
  28. package/out/targets/yarn.d.ts +2 -0
  29. package/out/targets/yarn.js +49 -0
  30. package/out/walk.d.ts +2 -0
  31. package/out/walk.js +19 -0
  32. package/package.json +21 -55
  33. package/bin/viewig +0 -4
  34. package/out/browser/binds/index.d.ts +0 -56
  35. package/out/browser/binds/index.d.ts.map +0 -1
  36. package/out/browser/binds/index.js +0 -95
  37. package/out/browser/binds/index.js.map +0 -1
  38. package/out/browser/binds/plugins/git.d.ts +0 -23
  39. package/out/browser/binds/plugins/git.d.ts.map +0 -1
  40. package/out/browser/binds/plugins/git.js +0 -67
  41. package/out/browser/binds/plugins/git.js.map +0 -1
  42. package/out/browser/binds/plugins/jsr.d.ts +0 -39
  43. package/out/browser/binds/plugins/jsr.d.ts.map +0 -1
  44. package/out/browser/binds/plugins/jsr.js +0 -117
  45. package/out/browser/binds/plugins/jsr.js.map +0 -1
  46. package/out/browser/binds/plugins/npm.d.ts +0 -39
  47. package/out/browser/binds/plugins/npm.d.ts.map +0 -1
  48. package/out/browser/binds/plugins/npm.js +0 -146
  49. package/out/browser/binds/plugins/npm.js.map +0 -1
  50. package/out/browser/binds/plugins/vsce.d.ts +0 -26
  51. package/out/browser/binds/plugins/vsce.d.ts.map +0 -1
  52. package/out/browser/binds/plugins/vsce.js +0 -71
  53. package/out/browser/binds/plugins/vsce.js.map +0 -1
  54. package/out/browser/binds/plugins/yarn.d.ts +0 -12
  55. package/out/browser/binds/plugins/yarn.d.ts.map +0 -1
  56. package/out/browser/binds/plugins/yarn.js +0 -36
  57. package/out/browser/binds/plugins/yarn.js.map +0 -1
  58. package/out/browser/binds/scanner.d.ts +0 -47
  59. package/out/browser/binds/scanner.d.ts.map +0 -1
  60. package/out/browser/binds/scanner.js +0 -166
  61. package/out/browser/binds/scanner.js.map +0 -1
  62. package/out/browser/binds/targets.d.ts +0 -78
  63. package/out/browser/binds/targets.d.ts.map +0 -1
  64. package/out/browser/binds/targets.js +0 -46
  65. package/out/browser/binds/targets.js.map +0 -1
  66. package/out/browser/conc.d.ts +0 -2
  67. package/out/browser/conc.d.ts.map +0 -1
  68. package/out/browser/conc.js +0 -19
  69. package/out/browser/conc.js.map +0 -1
  70. package/out/browser/errors.d.ts +0 -47
  71. package/out/browser/errors.d.ts.map +0 -1
  72. package/out/browser/errors.js +0 -35
  73. package/out/browser/errors.js.map +0 -1
  74. package/out/browser/filtering.d.ts +0 -13
  75. package/out/browser/filtering.d.ts.map +0 -1
  76. package/out/browser/filtering.js +0 -12
  77. package/out/browser/filtering.js.map +0 -1
  78. package/out/browser/fs/directory.d.ts +0 -145
  79. package/out/browser/fs/directory.d.ts.map +0 -1
  80. package/out/browser/fs/directory.js +0 -244
  81. package/out/browser/fs/directory.js.map +0 -1
  82. package/out/browser/fs/file-info.d.ts +0 -89
  83. package/out/browser/fs/file-info.d.ts.map +0 -1
  84. package/out/browser/fs/file-info.js +0 -101
  85. package/out/browser/fs/file-info.js.map +0 -1
  86. package/out/browser/fs/file.d.ts +0 -39
  87. package/out/browser/fs/file.d.ts.map +0 -1
  88. package/out/browser/fs/file.js +0 -42
  89. package/out/browser/fs/file.js.map +0 -1
  90. package/out/browser/fs/index.d.ts +0 -5
  91. package/out/browser/fs/index.d.ts.map +0 -1
  92. package/out/browser/fs/index.js +0 -5
  93. package/out/browser/fs/index.js.map +0 -1
  94. package/out/browser/fs/source-info.d.ts +0 -29
  95. package/out/browser/fs/source-info.d.ts.map +0 -1
  96. package/out/browser/fs/source-info.js +0 -31
  97. package/out/browser/fs/source-info.js.map +0 -1
  98. package/out/browser/index.d.ts +0 -4
  99. package/out/browser/index.d.ts.map +0 -1
  100. package/out/browser/index.js +0 -4
  101. package/out/browser/index.js.map +0 -1
  102. package/out/browser/lib.d.ts +0 -138
  103. package/out/browser/lib.d.ts.map +0 -1
  104. package/out/browser/lib.js +0 -89
  105. package/out/browser/lib.js.map +0 -1
  106. package/out/browser/sorting.d.ts +0 -52
  107. package/out/browser/sorting.d.ts.map +0 -1
  108. package/out/browser/sorting.js +0 -137
  109. package/out/browser/sorting.js.map +0 -1
  110. package/out/browser/styling.d.ts +0 -92
  111. package/out/browser/styling.d.ts.map +0 -1
  112. package/out/browser/styling.js +0 -66
  113. package/out/browser/styling.js.map +0 -1
  114. package/out/cli.d.ts +0 -90
  115. package/out/cli.d.ts.map +0 -1
  116. package/out/cli.js +0 -361
  117. package/out/cli.js.map +0 -1
  118. package/out/config.d.ts +0 -186
  119. package/out/config.d.ts.map +0 -1
  120. package/out/config.js +0 -370
  121. package/out/config.js.map +0 -1
  122. package/out/errors.d.ts +0 -7
  123. package/out/errors.d.ts.map +0 -1
  124. package/out/errors.js +0 -3
  125. package/out/errors.js.map +0 -1
  126. package/out/index.d.ts.map +0 -1
  127. package/out/index.js.map +0 -1
  128. package/out/lib.d.ts +0 -5
  129. package/out/lib.d.ts.map +0 -1
  130. package/out/lib.js +0 -5
  131. package/out/lib.js.map +0 -1
  132. package/out/styling.d.ts +0 -5
  133. package/out/styling.d.ts.map +0 -1
  134. package/out/styling.js +0 -49
  135. package/out/styling.js.map +0 -1
package/README.md CHANGED
@@ -5,124 +5,88 @@
5
5
  [![github](https://img.shields.io/github/stars/Mopsgamer/view-ignored.svg?style=flat)](https://github.com/Mopsgamer/view-ignored)
6
6
  [![github issues](https://img.shields.io/github/issues/Mopsgamer/view-ignored.svg?style=flat)](https://github.com/Mopsgamer/view-ignored/issues)
7
7
 
8
- Retrieve list of files ignored/included by Git, NPM, Yarn, JSR, VSCE or other
9
- tools.
8
+ Retrieve list of files ignored/included
9
+ by Git, NPM, Yarn, JSR, VSCE or other tools.
10
10
 
11
11
  ## Requirements
12
12
 
13
- Requires Node.js v18 or later.
13
+ - Node.js 18 or later for production
14
+ - Node.js 20 or later for production type definitions
15
+ - Node.js 22 or later for development type definitions
14
16
 
15
17
  ## Highlights
16
18
 
17
- - **Multi-target.** Get a list of included files using configuration file
19
+ - **Native.** Get a list of included files using configuration file
18
20
  readers, not command-line wrappers.
19
- - **Use in browser.** view-ignored can run in the browser using a file system
20
- adapter.
21
- - **Command-line.** Supports no-color and multiple output styles (tree, list,
22
- parsable, etc.), including
23
- [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts).
24
- - **Plugins.** view-ignored allows you to add new [targets](#targets)
25
- programmatically. Command-line interface supports plugins through `--plugins`
26
- option.
21
+ - **Plugins.** Built-in [targets](#targets) for popular tools. Use custom
22
+ targets by implementing the `Target` interface.
23
+ - **TypeScript.** Written in TypeScript with type definitions included.
24
+ - **Lightweight.** Minimal dependencies for fast performance and small bundle size.
25
+ - **Easy-to-modify.** Well-written and MIT-licensed.
26
+
27
+ > [!NOTE]
28
+ > Despite the name of the package being "view-ignored",
29
+ > the primary purpose is to get the list of
30
+ > **included** files, i.e., files that are **not ignored**.
31
+ > You can invert the results if you need the ignored files
32
+ > by setting the `invert` option to `true`.
27
33
 
28
34
  ## Usage
29
35
 
30
- ### Command-line
31
-
32
- After installing globally, you can use the following commands:
33
-
34
- ```bash
35
- # get started
36
- npm i -g view-ignored
37
- viewig --help
38
- view-ignored --help
39
-
40
- # scan: git (default) and npm
41
- viewig scan
42
- viewig scan --target=npm
43
- viewig sc -t npm
44
- viewig scan --parsable
45
-
46
- # scan: plugins (space, comma or pipe separated)
47
- # all built-in plugins loaded automatically
48
- # Replace example1/example2 with real plugin names
49
- viewig scan --plugins="example1, example2"
50
- viewig scan --plugins="example1 example2"
51
- viewig scan --plugins example1 example2
52
- viewig scan --plugins example1, example2
53
-
54
- # config: print configuration entries
55
- viewig config get
56
- viewig config get --real
57
- # config: set npm as default target and scan for npm
58
- viewig config set target=npm
59
- viewig scan
60
- # config: always use nerdfonts
61
- viewig config set style=tree
62
- # config: always use Nerd Fonts for decoration
63
- viewig config set decor=nerdfonts
64
- # config: always use plugins
65
- viewig config set plugins=example1,example2
66
- ```
67
-
68
- ### Programmatically
36
+ ### Basic example
69
37
 
70
- To use programmatically:
38
+ ```ts
39
+ import * as vign from "view-ignored";
40
+ import { Git } from "view-ignored/targets";
71
41
 
72
- ```js
73
- import * as vign from "view-ignored"; // or "view-ignored/browser"
42
+ const results = await vign.scan({ target: Git });
43
+ results.paths.has(".git/HEAD");
44
+ ```
74
45
 
75
- await vign.Plugins.loadBuiltIns(["git", "npm"]); // load built-in plugins
76
- await vign.Plugins.loadBuiltIns(); // load all built-in plugins
77
- await vign.Plugins.loadPlugins(["example"]); // load third-party plugins
46
+ ### Using custom target
78
47
 
79
- // scan - options available
80
- const fileInfoList = await vign.scan(".", {
81
- target: "git",
82
- cwd: process.cwd(),
83
- });
84
- const fileInfoList2 = await vign.scan(["./path/to/file"], {
85
- target: "git",
86
- cwd: process.cwd(),
87
- });
48
+ ```ts
49
+ import * as vign from "view-ignored";
50
+ import {
51
+ type SourceExtractor,
52
+ type SignedPattern,
53
+ extractGitignore
54
+ findAndExtract,
55
+ signedPatternIgnores,
56
+ } from "view-ignored/patterns";
57
+ import type { Target } from "view-ignored/targets";
58
+
59
+ const gitSources = ['.gitignore'];
60
+ const gitSourceMap = new Map<string, SourceExtractor>([
61
+ ['.gitignore', extractGitignore]
62
+ ]);
63
+ const gitPattern: SignedPattern = {
64
+ exclude: [
65
+ '.git',
66
+ '.DS_Store',
67
+ ],
68
+ include: []
69
+ };
88
70
 
89
- // use results
90
- for (const fileInfo of fileInfoList) {
91
- if (fileInfo.ignored) {
92
- superCodeEditor.explorer.colorFile(fileInfo.relativePath, "gray");
71
+ export const Git: Target = {
72
+ async matcher(entry, isDir, ctx) {
73
+ if (isDir) {
74
+ await findAndExtract(entry, gitSources, gitSourceMap, ctx);
75
+ return true;
76
+ }
77
+ return await signedPatternIgnores(gitPattern, entry, gitSources, gitSourceMap, ctx);
93
78
  }
94
- }
95
- ```
96
-
97
- #### Sorting
98
-
99
- ```js
100
- const sorter = vign.Sorting.firstFolders;
101
- const fileInfoList = await vign.scan(".", { target: "npm" });
102
- const fileInfoSorted = fileInfoList.sort((a, b) =>
103
- sorter(String(a), String(b))
104
- );
79
+ };
105
80
  ```
106
81
 
107
- #### Plugin export example
108
-
109
82
  ```ts
110
- const bind: Plugins.TargetBind = {
111
- id,
112
- icon,
113
- name,
114
- testCommand,
115
- scanOptions: {
116
- target: methodologyGitignoreLike(".gitignore"),
117
- },
118
- };
119
- const git: Plugins.PluginExport = { viewignored: { addTargets: [bind] } };
120
- export default git;
83
+ vign.scan({ target: Git });
121
84
  ```
122
85
 
123
- ### Targets
86
+ ## Targets
87
+
124
88
 
125
- The following built-in plugins are available:
89
+ The following built-in targets are available:
126
90
 
127
91
  - `git`
128
92
  - `npm` (compatible with Bun, PNPM, and others)
@@ -133,3 +97,7 @@ The following built-in plugins are available:
133
97
  ## License
134
98
 
135
99
  MIT License. See [LICENSE.txt](LICENSE.txt) for details.
100
+
101
+ ## Target implementations
102
+ <!-- .ts links -->
103
+ See [Target implementations](src/targets/README.md) for details.
package/out/index.d.ts CHANGED
@@ -1,4 +1 @@
1
- import * as ViewIgnored from './lib.js';
2
- export default ViewIgnored;
3
- export * from './lib.js';
4
- //# sourceMappingURL=index.d.ts.map
1
+ export * from './scan.js';
package/out/index.js CHANGED
@@ -1,4 +1 @@
1
- import * as ViewIgnored from './lib.js';
2
- export default ViewIgnored;
3
- export * from './lib.js';
4
- //# sourceMappingURL=index.js.map
1
+ export * from './scan.js';
@@ -0,0 +1,3 @@
1
+ import type { Source } from './matcher.js';
2
+ export declare function extractGitignore(source: Source, content: Buffer<ArrayBuffer>): void;
3
+ export declare function gitignoreMatch(pattern: string, path: string): boolean;
@@ -0,0 +1,35 @@
1
+ import { minimatch } from 'minimatch';
2
+ export function extractGitignore(source, content) {
3
+ for (let line of content.toString().split('\n')) {
4
+ line = line.trim();
5
+ if (line === '' || line.startsWith('#')) {
6
+ continue;
7
+ }
8
+ const cdx = line.indexOf('#');
9
+ if (cdx >= 0) {
10
+ line = line.substring(-cdx);
11
+ }
12
+ if (line.startsWith('!')) {
13
+ source.pattern.include.push(line.substring(1));
14
+ }
15
+ else {
16
+ source.pattern.exclude.push(line);
17
+ }
18
+ }
19
+ // TODO: validate gitignore
20
+ }
21
+ extractGitignore;
22
+ export function gitignoreMatch(pattern, path) {
23
+ const o = { dot: true };
24
+ if (pattern.startsWith('/')) {
25
+ pattern = pattern.substring(1);
26
+ }
27
+ else if (!pattern.startsWith('**/')) {
28
+ if (minimatch(path, '**/' + pattern, o))
29
+ return true;
30
+ }
31
+ if (pattern.endsWith('/')) {
32
+ pattern = pattern.substring(-1);
33
+ }
34
+ return minimatch(path, pattern, o) || minimatch(path, pattern + '/**', o);
35
+ }
@@ -0,0 +1,4 @@
1
+ export * from './matcher.js';
2
+ export * from './gitignore.js';
3
+ export * from './jsrjson.js';
4
+ export * from './packagejson.js';
@@ -0,0 +1,4 @@
1
+ export * from './matcher.js';
2
+ export * from './gitignore.js';
3
+ export * from './jsrjson.js';
4
+ export * from './packagejson.js';
@@ -0,0 +1,4 @@
1
+ import { type } from 'arktype';
2
+ import type { Source } from './matcher.js';
3
+ export declare function extractJsrJson(source: Source, content: Buffer<ArrayBuffer>): type.errors | undefined;
4
+ export declare function extractJsrJsonc(source: Source, content: Buffer<ArrayBuffer>): type.errors | undefined;
@@ -0,0 +1,39 @@
1
+ import { type } from 'arktype';
2
+ import stripJsonComments from 'strip-json-comments';
3
+ const jsrManifest = type({
4
+ exclude: 'string[]?',
5
+ include: 'string[]?',
6
+ publish: {
7
+ exclude: 'string[]?',
8
+ include: 'string[]?',
9
+ },
10
+ });
11
+ const parse = jsrManifest.pipe((s) => JSON.parse(s));
12
+ export function extractJsrJson(source, content) {
13
+ const dist = parse(content.toString());
14
+ if (dist instanceof type.errors) {
15
+ return dist;
16
+ }
17
+ if (!dist.publish) {
18
+ if (dist.exclude) {
19
+ source.pattern.exclude.push(...dist.exclude);
20
+ }
21
+ }
22
+ else if (dist.publish.exclude) {
23
+ source.pattern.exclude.push(...dist.publish.exclude);
24
+ }
25
+ if (!dist.publish) {
26
+ if (dist.include) {
27
+ source.pattern.include.push(...dist.include);
28
+ }
29
+ }
30
+ else if (dist.publish.include) {
31
+ source.pattern.include.push(...dist.publish.include);
32
+ }
33
+ return;
34
+ }
35
+ extractJsrJson;
36
+ export function extractJsrJsonc(source, content) {
37
+ return extractJsrJson(source, Buffer.from(stripJsonComments(content.toString())));
38
+ }
39
+ extractJsrJsonc;
@@ -0,0 +1,39 @@
1
+ export type MatcherContext = {
2
+ paths: Set<string>;
3
+ external: Map<string, Source>;
4
+ depthPaths: Map<string, number>;
5
+ sourceErrors: Error[];
6
+ totalFiles: number;
7
+ totalMatchedFiles: number;
8
+ totalDirs: number;
9
+ };
10
+ /**
11
+ * Represents a list of positive minimatch patterns.
12
+ */
13
+ export type Pattern = string[];
14
+ export declare function patternMatches(pattern: Pattern, path: string): boolean;
15
+ /**
16
+ * Represents a set of include and exclude patterns.
17
+ * These patterns are positive minimatch patterns.
18
+ */
19
+ export type SignedPattern = {
20
+ include: Pattern;
21
+ exclude: Pattern;
22
+ };
23
+ /**
24
+ * Combined internal and external patterns for matching.
25
+ * Used in {@link signedPatternIgnores} function.
26
+ */
27
+ export type PatternMatcher = {
28
+ internal: SignedPattern;
29
+ external: SignedPattern;
30
+ };
31
+ export type PathChecker = (path: string, isDir: boolean, ctx: MatcherContext) => Promise<boolean>;
32
+ export type Source = {
33
+ pattern: SignedPattern;
34
+ name: string;
35
+ inverted: boolean;
36
+ };
37
+ export type SourceExtractor = (source: Source, content: Buffer<ArrayBuffer>) => void;
38
+ export declare function findAndExtract(directory: string, sources: string[], matcher: Map<string, SourceExtractor>, ctx: MatcherContext): Promise<void>;
39
+ export declare function signedPatternIgnores(internal: SignedPattern, file: string, sources: string[], sourceMap: Map<string, SourceExtractor>, ctx: MatcherContext): Promise<boolean>;
@@ -0,0 +1,118 @@
1
+ import * as fsp from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ import { gitignoreMatch } from './gitignore.js';
4
+ export function patternMatches(pattern, path) {
5
+ for (const p of pattern) {
6
+ const matched = gitignoreMatch(p, path);
7
+ if (matched) {
8
+ return true;
9
+ }
10
+ }
11
+ return false;
12
+ }
13
+ export async function findAndExtract(directory, sources, matcher, ctx) {
14
+ const keys = [];
15
+ for (const sourceFileName of sources) {
16
+ for (;;) {
17
+ let buff;
18
+ try {
19
+ buff = await fsp.readFile(directory + '/' + sourceFileName);
20
+ }
21
+ catch (err) {
22
+ const error = err;
23
+ if (error.code !== 'ENOENT') {
24
+ ctx.sourceErrors.push(error);
25
+ return;
26
+ }
27
+ }
28
+ const dir = dirname(directory);
29
+ if (!ctx.external.has(directory)) {
30
+ keys.push(directory);
31
+ }
32
+ if (!buff) {
33
+ if (directory === '.') {
34
+ break;
35
+ }
36
+ directory = dir;
37
+ continue;
38
+ }
39
+ if (directory === '.' && !keys.length) {
40
+ break;
41
+ }
42
+ const sourceExtractor = matcher.get(sourceFileName);
43
+ if (!sourceExtractor) {
44
+ const err = new Error('No extractor for source file: ' + sourceFileName);
45
+ ctx.sourceErrors.push(err);
46
+ break;
47
+ }
48
+ const source = {
49
+ inverted: false,
50
+ name: sourceFileName,
51
+ pattern: {
52
+ exclude: [],
53
+ include: [],
54
+ },
55
+ };
56
+ try {
57
+ sourceExtractor(source, buff);
58
+ }
59
+ catch (err) {
60
+ ctx.sourceErrors.push(err);
61
+ break;
62
+ }
63
+ for (const key of keys) {
64
+ const m = ctx.external.get(key);
65
+ if (!m) {
66
+ ctx.external.set(key, source);
67
+ }
68
+ }
69
+ if (directory === '.') {
70
+ return;
71
+ }
72
+ keys.length = 0;
73
+ directory = dir;
74
+ }
75
+ }
76
+ }
77
+ export async function signedPatternIgnores(internal, file, sources, sourceMap, ctx) {
78
+ const parent = dirname(file);
79
+ let source = ctx.external.get(parent);
80
+ if (!source) {
81
+ await findAndExtract(parent, sources, sourceMap, ctx);
82
+ if (ctx.sourceErrors.length) {
83
+ return false;
84
+ }
85
+ source = ctx.external.get(parent);
86
+ if (!source) {
87
+ return false;
88
+ }
89
+ }
90
+ const matcher = {
91
+ internal,
92
+ external: source.pattern,
93
+ };
94
+ try {
95
+ let check = false;
96
+ check = patternMatches(matcher.internal.exclude, file);
97
+ if (check) {
98
+ return true;
99
+ }
100
+ check = patternMatches(matcher.internal.include, file);
101
+ if (check) {
102
+ return false;
103
+ }
104
+ check = patternMatches(matcher.external.exclude, file);
105
+ if (check) {
106
+ return true;
107
+ }
108
+ check = patternMatches(matcher.external.include, file);
109
+ if (check) {
110
+ return false;
111
+ }
112
+ }
113
+ catch (err) {
114
+ ctx.sourceErrors.push(err);
115
+ return false;
116
+ }
117
+ return source.inverted;
118
+ }
@@ -0,0 +1,3 @@
1
+ import { type } from 'arktype';
2
+ import type { Source } from './matcher.js';
3
+ export declare function extractPackageJson(source: Source, content: Buffer<ArrayBuffer>): type.errors | undefined;
@@ -0,0 +1,25 @@
1
+ import { type } from 'arktype';
2
+ const nodeJsManifest = type({
3
+ files: 'string[]?',
4
+ });
5
+ const parse = nodeJsManifest.pipe((s) => JSON.parse(s));
6
+ export function extractPackageJson(source, content) {
7
+ source.inverted = true;
8
+ const dist = parse(content.toString());
9
+ if (dist instanceof type.errors) {
10
+ return dist;
11
+ }
12
+ if (!dist.files) {
13
+ return;
14
+ }
15
+ for (const p of dist.files) {
16
+ if (p.startsWith('!')) {
17
+ source.pattern.exclude.push(...p.substring(1));
18
+ }
19
+ else {
20
+ source.pattern.include.push(...p);
21
+ }
22
+ }
23
+ return;
24
+ }
25
+ extractPackageJson;
package/out/scan.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ import type { MatcherContext } from './patterns/matcher.js';
2
+ import type { Target } from './targets/target.js';
3
+ export type DepthMode = 'files' | undefined;
4
+ export type ScanOptions = {
5
+ /**
6
+ * Provides the matcher to use for scanning.
7
+ */
8
+ target: Target;
9
+ /**
10
+ * Current working directory to start the scan from.
11
+ */
12
+ cwd?: string;
13
+ /**
14
+ * If enabled, the scan will return files that are ignored by the target matchers.
15
+ */
16
+ invert?: boolean;
17
+ /**
18
+ * Starting from depth `0` means you will see
19
+ * children of the current working directory.
20
+ */
21
+ depth?: number;
22
+ /**
23
+ * Return as soon as possible.
24
+ */
25
+ signal?: AbortSignal;
26
+ /**
27
+ * If enabled, Depth will be calculated faster by skipping
28
+ * other files after first match.
29
+ * This makes the scan faster but affects
30
+ * {@link MatcherContext.totalDirs},
31
+ * {@link MatcherContext.totalFiles},
32
+ * {@link MatcherContext.totalMatchedFiles}
33
+ * and {@link MatcherContext.depthPaths}.
34
+ */
35
+ fastDepth?: boolean;
36
+ };
37
+ /**
38
+ * Scan the directory for included files based on the provided targets.
39
+ *
40
+ * Note that this function uses `fs/promises.opendir` with recursive option,
41
+ * and `fs/promises.readFile`. It also normalizes paths to use forward slashes..
42
+ *
43
+ * @param options Scan options.
44
+ * @returns A promise that resolves to a map of targets to their matcher contexts.
45
+ */
46
+ export declare function scan(options: ScanOptions): Promise<MatcherContext>;
package/out/scan.js ADDED
@@ -0,0 +1,113 @@
1
+ import { posix } from 'node:path';
2
+ import { opendir } from './walk.js';
3
+ /**
4
+ * Scan the directory for included files based on the provided targets.
5
+ *
6
+ * Note that this function uses `fs/promises.opendir` with recursive option,
7
+ * and `fs/promises.readFile`. It also normalizes paths to use forward slashes..
8
+ *
9
+ * @param options Scan options.
10
+ * @returns A promise that resolves to a map of targets to their matcher contexts.
11
+ */
12
+ export async function scan(options) {
13
+ const { target, cwd: cwdo = (await import('node:process')).cwd(), depth: maxDepth = Infinity, invert = false, signal = undefined, fastDepth = false, } = options;
14
+ const cwd = cwdo.replaceAll('\\', '/');
15
+ const ctx = {
16
+ paths: new Set(),
17
+ external: new Map(),
18
+ depthPaths: new Map(),
19
+ sourceErrors: [],
20
+ totalFiles: 0,
21
+ totalMatchedFiles: 0,
22
+ totalDirs: 0,
23
+ };
24
+ await opendir(cwd, async (entry) => {
25
+ if (signal?.aborted) {
26
+ return 2;
27
+ }
28
+ const path = posix.join(posix.relative(cwd, entry.parentPath.replaceAll('\\', '/')), entry.name);
29
+ if (entry.isDirectory()) {
30
+ ctx.totalDirs++;
31
+ if (!fastDepth) {
32
+ return 0;
33
+ }
34
+ const { depth } = getDepth(path, maxDepth);
35
+ if (depth <= maxDepth) {
36
+ return 0;
37
+ }
38
+ return 1;
39
+ }
40
+ ctx.totalFiles++;
41
+ if (fastDepth) {
42
+ const { depth, depthSlash } = getDepth(path, maxDepth);
43
+ if (depth > maxDepth) {
44
+ let ignored = await target.matcher(path, false, ctx);
45
+ if (ctx.sourceErrors.length > 0) {
46
+ return 2;
47
+ }
48
+ if (invert) {
49
+ ignored = !ignored;
50
+ }
51
+ if (ignored) {
52
+ return 0;
53
+ }
54
+ const dir = path.substring(0, depthSlash);
55
+ ctx.depthPaths.set(dir, (ctx.depthPaths.get(dir) ?? 0) + 1);
56
+ return 1;
57
+ }
58
+ }
59
+ let ignored = await target.matcher(path, false, ctx);
60
+ if (ctx.sourceErrors.length > 0) {
61
+ return 2;
62
+ }
63
+ if (invert) {
64
+ ignored = !ignored;
65
+ }
66
+ if (ignored) {
67
+ return 0;
68
+ }
69
+ ctx.totalMatchedFiles++;
70
+ const { depth, depthSlash } = getDepth(path, maxDepth);
71
+ if (depth > maxDepth) {
72
+ const dir = path.substring(0, depthSlash);
73
+ ctx.depthPaths.set(dir, (ctx.depthPaths.get(dir) ?? 0) + 1);
74
+ }
75
+ else {
76
+ ctx.paths.add(path);
77
+ }
78
+ return 0;
79
+ });
80
+ if (signal?.aborted) {
81
+ return ctx;
82
+ }
83
+ for (const [dir, count] of ctx.depthPaths) {
84
+ if (count === 0) {
85
+ continue;
86
+ }
87
+ ctx.paths.add(dir + '/');
88
+ }
89
+ console.log(ctx.paths);
90
+ return ctx;
91
+ }
92
+ function getDepth(path, maxDepth) {
93
+ const result = {
94
+ depth: 0,
95
+ depthSlash: 0,
96
+ };
97
+ result.depthSlash = -1;
98
+ if (maxDepth < 0) {
99
+ return result;
100
+ }
101
+ for (const [i, c] of Array.from(path).entries()) {
102
+ if (c !== '/') {
103
+ continue;
104
+ }
105
+ result.depth++;
106
+ if (result.depth < maxDepth) {
107
+ continue;
108
+ }
109
+ result.depthSlash = i;
110
+ return result;
111
+ }
112
+ return result;
113
+ }
@@ -0,0 +1,2 @@
1
+ import type { Target } from './target.js';
2
+ export declare const Git: Target;
@@ -0,0 +1,22 @@
1
+ import { signedPatternIgnores, findAndExtract } from '../patterns/matcher.js';
2
+ import { extractGitignore } from '../patterns/gitignore.js';
3
+ const gitSources = ['.gitignore'];
4
+ const gitSourceMap = new Map([
5
+ ['.gitignore', extractGitignore],
6
+ ]);
7
+ const gitPattern = {
8
+ exclude: [
9
+ '.git',
10
+ '.DS_Store',
11
+ ],
12
+ include: [],
13
+ };
14
+ export const Git = {
15
+ async matcher(entry, isDir, ctx) {
16
+ if (isDir) {
17
+ await findAndExtract(entry, gitSources, gitSourceMap, ctx);
18
+ return true;
19
+ }
20
+ return await signedPatternIgnores(gitPattern, entry, gitSources, gitSourceMap, ctx);
21
+ },
22
+ };