srcpack 0.1.6 → 0.1.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 +2 -0
- package/dist/cli.js +33 -3
- package/package.json +1 -1
- package/src/bundle.ts +71 -6
package/README.md
CHANGED
|
@@ -159,6 +159,8 @@ const config = await loadConfig();
|
|
|
159
159
|
- [Discord](https://discord.com/invite/aG83xEb6RX) — Questions, feedback, and discussion
|
|
160
160
|
- [GitHub Issues](https://github.com/kriasoft/srcpack/issues) — Bug reports and feature requests
|
|
161
161
|
|
|
162
|
+
New contributors and OSS maintainers are welcome — join us on Discord or open an issue / PR.
|
|
163
|
+
|
|
162
164
|
## Backers
|
|
163
165
|
|
|
164
166
|
<a href="https://reactstarter.com/b/1"><img src="https://reactstarter.com/b/1.png" height="60" /></a> <a href="https://reactstarter.com/b/2"><img src="https://reactstarter.com/b/2.png" height="60" /></a> <a href="https://reactstarter.com/b/3"><img src="https://reactstarter.com/b/3.png" height="60" /></a> <a href="https://reactstarter.com/b/4"><img src="https://reactstarter.com/b/4.png" height="60" /></a> <a href="https://reactstarter.com/b/5"><img src="https://reactstarter.com/b/5.png" height="60" /></a> <a href="https://reactstarter.com/b/6"><img src="https://reactstarter.com/b/6.png" height="60" /></a> <a href="https://reactstarter.com/b/7"><img src="https://reactstarter.com/b/7.png" height="60" /></a> <a href="https://reactstarter.com/b/8"><img src="https://reactstarter.com/b/8.png" height="60" /></a>
|
package/dist/cli.js
CHANGED
|
@@ -207577,22 +207577,52 @@ function normalizePatterns(config) {
|
|
|
207577
207577
|
function isExcluded(filePath, matchers) {
|
|
207578
207578
|
return matchers.some((match) => match(filePath));
|
|
207579
207579
|
}
|
|
207580
|
+
function gitignoreToGlobPatterns(lines) {
|
|
207581
|
+
const hasNegation = lines.some((line) => {
|
|
207582
|
+
const trimmed = line.trim();
|
|
207583
|
+
return trimmed.startsWith("!");
|
|
207584
|
+
});
|
|
207585
|
+
if (hasNegation)
|
|
207586
|
+
return [];
|
|
207587
|
+
const patterns = [];
|
|
207588
|
+
for (const line of lines) {
|
|
207589
|
+
const trimmed = line.trim();
|
|
207590
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
207591
|
+
continue;
|
|
207592
|
+
if (trimmed.startsWith("/") || trimmed.includes("*") || trimmed.includes("?") || trimmed.includes("[") || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
207593
|
+
continue;
|
|
207594
|
+
}
|
|
207595
|
+
const name = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
|
|
207596
|
+
if (name && /^[\w.-]+$/.test(name)) {
|
|
207597
|
+
patterns.push(`**/${name}/**`);
|
|
207598
|
+
}
|
|
207599
|
+
}
|
|
207600
|
+
return patterns;
|
|
207601
|
+
}
|
|
207580
207602
|
async function loadGitignore(cwd) {
|
|
207581
207603
|
const ig = import_ignore.default();
|
|
207582
207604
|
const gitignorePath = join(cwd, ".gitignore");
|
|
207605
|
+
let globPatterns = [];
|
|
207583
207606
|
try {
|
|
207584
207607
|
const content = await readFile(gitignorePath, "utf-8");
|
|
207585
207608
|
ig.add(content);
|
|
207609
|
+
globPatterns = gitignoreToGlobPatterns(content.split(`
|
|
207610
|
+
`));
|
|
207586
207611
|
} catch {}
|
|
207587
|
-
return ig;
|
|
207612
|
+
return { ignore: ig, globPatterns };
|
|
207588
207613
|
}
|
|
207589
207614
|
async function resolvePatterns(config, cwd) {
|
|
207590
207615
|
const { include, exclude, force } = normalizePatterns(config);
|
|
207591
207616
|
const excludeMatchers = exclude.map((p) => import_picomatch.default(p));
|
|
207592
|
-
const gitignore = await loadGitignore(cwd);
|
|
207617
|
+
const { ignore: gitignore, globPatterns } = await loadGitignore(cwd);
|
|
207593
207618
|
const files = new Set;
|
|
207594
207619
|
if (include.length > 0) {
|
|
207595
|
-
const matches = await import_fast_glob.glob(include, {
|
|
207620
|
+
const matches = await import_fast_glob.glob(include, {
|
|
207621
|
+
cwd,
|
|
207622
|
+
onlyFiles: true,
|
|
207623
|
+
dot: true,
|
|
207624
|
+
ignore: globPatterns
|
|
207625
|
+
});
|
|
207596
207626
|
for (const match of matches) {
|
|
207597
207627
|
if (!isExcluded(match, excludeMatchers) && !gitignore.ignores(match)) {
|
|
207598
207628
|
const fullPath = join(cwd, match);
|
package/package.json
CHANGED
package/src/bundle.ts
CHANGED
|
@@ -86,20 +86,79 @@ function isExcluded(filePath: string, matchers: Matcher[]): boolean {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
89
|
+
* Convert gitignore patterns to glob ignore patterns for fast-glob.
|
|
90
|
+
* This prevents traversing into ignored directories (performance optimization).
|
|
91
|
+
*
|
|
92
|
+
* Conservative approach: only convert simple, unambiguous directory patterns.
|
|
93
|
+
* Complex patterns (negations, root-anchored, globs) are left to the ignore filter.
|
|
90
94
|
*/
|
|
91
|
-
|
|
95
|
+
function gitignoreToGlobPatterns(lines: string[]): string[] {
|
|
96
|
+
// If any negation patterns exist, skip optimization entirely
|
|
97
|
+
// (negations could re-include files in otherwise-ignored directories)
|
|
98
|
+
const hasNegation = lines.some((line) => {
|
|
99
|
+
const trimmed = line.trim();
|
|
100
|
+
// Any line starting with ! is a negation (including !#file which negates "#file")
|
|
101
|
+
return trimmed.startsWith("!");
|
|
102
|
+
});
|
|
103
|
+
if (hasNegation) return [];
|
|
104
|
+
|
|
105
|
+
const patterns: string[] = [];
|
|
106
|
+
|
|
107
|
+
for (const line of lines) {
|
|
108
|
+
const trimmed = line.trim();
|
|
109
|
+
// Skip empty lines and comments
|
|
110
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
111
|
+
|
|
112
|
+
// Skip patterns with special gitignore features we can't safely convert:
|
|
113
|
+
// - Root-anchored (starts with /)
|
|
114
|
+
// - Contains globs (*, ?, [)
|
|
115
|
+
// - Contains path separators (complex paths)
|
|
116
|
+
// - Escaped characters
|
|
117
|
+
if (
|
|
118
|
+
trimmed.startsWith("/") ||
|
|
119
|
+
trimmed.includes("*") ||
|
|
120
|
+
trimmed.includes("?") ||
|
|
121
|
+
trimmed.includes("[") ||
|
|
122
|
+
trimmed.includes("/") ||
|
|
123
|
+
trimmed.includes("\\")
|
|
124
|
+
) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Only convert simple directory names (e.g., "node_modules", "dist")
|
|
129
|
+
// These are safe to prune at any depth
|
|
130
|
+
const name = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
|
|
131
|
+
if (name && /^[\w.-]+$/.test(name)) {
|
|
132
|
+
patterns.push(`**/${name}/**`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return patterns;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface GitignoreResult {
|
|
140
|
+
ignore: Ignore;
|
|
141
|
+
globPatterns: string[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Load and parse .gitignore file from a directory.
|
|
146
|
+
* Returns both an Ignore instance for filtering and glob patterns for fast-glob.
|
|
147
|
+
*/
|
|
148
|
+
async function loadGitignore(cwd: string): Promise<GitignoreResult> {
|
|
92
149
|
const ig = ignore();
|
|
93
150
|
const gitignorePath = join(cwd, ".gitignore");
|
|
151
|
+
let globPatterns: string[] = [];
|
|
94
152
|
|
|
95
153
|
try {
|
|
96
154
|
const content = await readFile(gitignorePath, "utf-8");
|
|
97
155
|
ig.add(content);
|
|
156
|
+
globPatterns = gitignoreToGlobPatterns(content.split("\n"));
|
|
98
157
|
} catch {
|
|
99
158
|
// No .gitignore file, return empty ignore instance
|
|
100
159
|
}
|
|
101
160
|
|
|
102
|
-
return ig;
|
|
161
|
+
return { ignore: ig, globPatterns };
|
|
103
162
|
}
|
|
104
163
|
|
|
105
164
|
/**
|
|
@@ -114,12 +173,18 @@ export async function resolvePatterns(
|
|
|
114
173
|
): Promise<string[]> {
|
|
115
174
|
const { include, exclude, force } = normalizePatterns(config);
|
|
116
175
|
const excludeMatchers = exclude.map((p) => picomatch(p));
|
|
117
|
-
const gitignore = await loadGitignore(cwd);
|
|
176
|
+
const { ignore: gitignore, globPatterns } = await loadGitignore(cwd);
|
|
118
177
|
const files = new Set<string>();
|
|
119
178
|
|
|
120
179
|
// Regular includes: respect .gitignore
|
|
180
|
+
// Pass gitignore patterns to fast-glob to skip ignored directories during traversal
|
|
121
181
|
if (include.length > 0) {
|
|
122
|
-
const matches = await glob(include, {
|
|
182
|
+
const matches = await glob(include, {
|
|
183
|
+
cwd,
|
|
184
|
+
onlyFiles: true,
|
|
185
|
+
dot: true,
|
|
186
|
+
ignore: globPatterns,
|
|
187
|
+
});
|
|
123
188
|
for (const match of matches) {
|
|
124
189
|
if (!isExcluded(match, excludeMatchers) && !gitignore.ignores(match)) {
|
|
125
190
|
const fullPath = join(cwd, match);
|
|
@@ -130,7 +195,7 @@ export async function resolvePatterns(
|
|
|
130
195
|
}
|
|
131
196
|
}
|
|
132
197
|
|
|
133
|
-
// Force includes: bypass .gitignore
|
|
198
|
+
// Force includes: bypass .gitignore (no ignore patterns passed to glob)
|
|
134
199
|
if (force.length > 0) {
|
|
135
200
|
const matches = await glob(force, { cwd, onlyFiles: true, dot: true });
|
|
136
201
|
for (const match of matches) {
|