@meteorjs/rspack 0.0.52 → 0.0.54
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/lib/ignore.js +98 -131
- package/lib/test.js +17 -16
- package/package.json +1 -1
- package/rspack.config.js +23 -23
package/lib/ignore.js
CHANGED
|
@@ -1,172 +1,139 @@
|
|
|
1
1
|
var fs = require('fs');
|
|
2
2
|
var path = require('path');
|
|
3
3
|
|
|
4
|
-
// Cleans an entry from wildcard patterns (*/**)
|
|
5
|
-
function cleanWildcardEntry(entry) {
|
|
6
|
-
// If it's an extension pattern like *.ext, skip it
|
|
7
|
-
if (entry.match(/\*\.[^\/]+$/)) {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Handle patterns like my-folder/**/* by extracting the folder part
|
|
12
|
-
if (entry.includes('/**/')) {
|
|
13
|
-
const folderContext = entry.split('/**/')[0].replace(/\/+$/, '');
|
|
14
|
-
if (folderContext) {
|
|
15
|
-
return folderContext;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Otherwise, extract the folder context by removing the wildcard part
|
|
20
|
-
if (entry.includes('*')) {
|
|
21
|
-
const folderContext = entry.split('*')[0].replace(/\/+$/, '');
|
|
22
|
-
if (folderContext) {
|
|
23
|
-
return folderContext;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return entry;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
4
|
/**
|
|
32
5
|
* Reads the .meteorignore file from the given project directory and returns
|
|
33
|
-
* the parsed entries.
|
|
6
|
+
* the parsed entries. Empty lines and comment lines (starting with #) are filtered out.
|
|
34
7
|
*
|
|
35
8
|
* @param {string} projectDir - The project directory path
|
|
36
|
-
* @returns {
|
|
9
|
+
* @returns {string[]} - Array of ignore patterns
|
|
37
10
|
*/
|
|
38
11
|
const getMeteorIgnoreEntries = function (projectDir) {
|
|
39
12
|
const meteorIgnorePath = path.join(projectDir, '.meteorignore');
|
|
40
13
|
|
|
41
14
|
// Check if .meteorignore file exists
|
|
42
|
-
let entries = [];
|
|
43
15
|
try {
|
|
44
16
|
const fileContent = fs.readFileSync(meteorIgnorePath, 'utf8');
|
|
45
17
|
|
|
46
18
|
// Process each line in the file
|
|
47
|
-
entries = fileContent.split(/\r?\n/)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}).map(line => line.trim()); // Ensure all lines are trimmed
|
|
53
|
-
|
|
54
|
-
// Clean all entries from wildcard patterns (*/** parts)
|
|
55
|
-
entries = entries.map(entry => {
|
|
56
|
-
return cleanWildcardEntry(entry);
|
|
57
|
-
}).filter(entry => entry !== null);
|
|
58
|
-
|
|
59
|
-
// Separate entries into rootFolders and nestedFolders
|
|
60
|
-
const rootFolders = [];
|
|
61
|
-
const nestedFolders = [];
|
|
62
|
-
|
|
63
|
-
entries.forEach(entry => {
|
|
64
|
-
// If entry starts with / or ./, it's a root folder
|
|
65
|
-
if (entry.startsWith('/') || entry.startsWith('./')) {
|
|
66
|
-
rootFolders.push(entry);
|
|
67
|
-
} else {
|
|
68
|
-
// Otherwise, it's a nested folder
|
|
69
|
-
nestedFolders.push(entry);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
return { rootFolders, nestedFolders };
|
|
19
|
+
const entries = fileContent.split(/\r?\n/)
|
|
20
|
+
.map(line => line.trim())
|
|
21
|
+
.filter(line => line !== '' && !line.startsWith('#'));
|
|
22
|
+
|
|
23
|
+
return entries;
|
|
74
24
|
} catch (e) {
|
|
75
|
-
// If the file doesn't exist or can't be read, return empty
|
|
76
|
-
return
|
|
25
|
+
// If the file doesn't exist or can't be read, return empty array
|
|
26
|
+
return [];
|
|
77
27
|
}
|
|
78
28
|
};
|
|
79
29
|
|
|
80
30
|
/**
|
|
81
|
-
* Creates a
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* @
|
|
85
|
-
* @param {string[]} [options.nestedFolders] - Array of folder names to ignore anywhere in the path
|
|
86
|
-
* @param {string[]} [options.rootFolders] - Array of folder names that should only match at the root level
|
|
87
|
-
* @returns {RegExp} - Regex pattern to ignore the specified folders
|
|
31
|
+
* Creates a glob config array for ignoring specified patterns.
|
|
32
|
+
* Transforms .gitignore-style entries into chokidar-compatible glob patterns.
|
|
33
|
+
* @param {string[]} entries - Array of .gitignore-style patterns
|
|
34
|
+
* @returns {string[]} - Array of glob patterns for chokidar
|
|
88
35
|
*/
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!Array.isArray(nestedFolders) || nestedFolders.length === 0) {
|
|
94
|
-
throw new Error('nestedFolders must be a non-empty array');
|
|
36
|
+
function createIgnoreGlobConfig(entries = []) {
|
|
37
|
+
if (!Array.isArray(entries)) {
|
|
38
|
+
throw new Error('Entries must be an array');
|
|
95
39
|
}
|
|
96
40
|
|
|
97
|
-
|
|
98
|
-
if (!rootFolders || !Array.isArray(rootFolders) || rootFolders.length === 0) {
|
|
99
|
-
// Escape special regex characters in folder names
|
|
100
|
-
const escapedFolders = nestedFolders.map(folder =>
|
|
101
|
-
folder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
102
|
-
);
|
|
41
|
+
const globPatterns = [];
|
|
103
42
|
|
|
104
|
-
|
|
105
|
-
|
|
43
|
+
entries.forEach(entry => {
|
|
44
|
+
// Skip empty entries
|
|
45
|
+
if (!entry.trim()) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
106
48
|
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
49
|
+
// Handle comments
|
|
50
|
+
if (entry.startsWith('#')) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check if it's a negation pattern
|
|
55
|
+
const isNegation = entry.startsWith('!');
|
|
56
|
+
let pattern = isNegation ? entry.substring(1).trim() : entry.trim();
|
|
111
57
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
58
|
+
// Remove leading ./ or / if present
|
|
59
|
+
pattern = pattern.replace(/^(\.\/|\/)/g, '');
|
|
60
|
+
|
|
61
|
+
// If it ends with /, it's a directory pattern, add ** to match all contents
|
|
62
|
+
if (pattern.endsWith('/')) {
|
|
63
|
+
pattern = pattern.slice(0, -1) + '/**';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// If it doesn't include a /, it could match anywhere in the path
|
|
67
|
+
if (!pattern.includes('/')) {
|
|
68
|
+
pattern = '**/' + pattern;
|
|
69
|
+
} else if (!pattern.startsWith('**/') && !pattern.startsWith('/')) {
|
|
70
|
+
// If it has a / but doesn't start with **/, add **/ to match anywhere
|
|
71
|
+
pattern = '**/' + pattern;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Add the negation back if it was present
|
|
75
|
+
if (isNegation) {
|
|
76
|
+
pattern = '!' + pattern;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
globPatterns.push(pattern);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return globPatterns;
|
|
131
83
|
}
|
|
132
84
|
|
|
133
85
|
/**
|
|
134
|
-
* Creates a
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* @param {
|
|
138
|
-
* @
|
|
139
|
-
* @param {string[]} [options.rootFolders] - Array of folder names that should only match at the root level
|
|
140
|
-
* @returns {string[]} - Array of glob patterns to ignore the specified folders
|
|
86
|
+
* Creates a regex pattern to match the specified glob patterns.
|
|
87
|
+
* Converts glob patterns with * and ** into regex equivalents.
|
|
88
|
+
*
|
|
89
|
+
* @param {string[]} globPatterns - Array of glob patterns from createIgnoreGlobConfig
|
|
90
|
+
* @returns {RegExp} - Regex pattern to match the specified patterns
|
|
141
91
|
*/
|
|
142
|
-
function
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const globPatterns = [];
|
|
146
|
-
|
|
147
|
-
// Create glob patterns for nested folders: **/{nestedFolder}/**
|
|
148
|
-
if (Array.isArray(nestedFolders) && nestedFolders.length > 0) {
|
|
149
|
-
nestedFolders.forEach(folder => {
|
|
150
|
-
// Remove leading ./ or / if present
|
|
151
|
-
const cleanFolder = folder.replace(/^(\.\/|\/)/g, '');
|
|
152
|
-
globPatterns.push(`**/${cleanFolder}/**`);
|
|
153
|
-
});
|
|
92
|
+
function createIgnoreRegex(globPatterns) {
|
|
93
|
+
if (!Array.isArray(globPatterns) || globPatterns.length === 0) {
|
|
94
|
+
throw new Error('globPatterns must be a non-empty array');
|
|
154
95
|
}
|
|
155
96
|
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
97
|
+
// Process each glob pattern and convert to regex
|
|
98
|
+
const regexPatterns = globPatterns.map(pattern => {
|
|
99
|
+
// Skip negation patterns for the regex
|
|
100
|
+
if (pattern.startsWith('!')) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Escape special regex characters, but not * and /
|
|
105
|
+
let regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
106
|
+
|
|
107
|
+
// Use a temporary placeholder for ** that won't be affected by the * replacement
|
|
108
|
+
// This is necessary because if we directly replace ** with .* and then replace * with [^/]*
|
|
109
|
+
const DOUBLE_ASTERISK_PLACEHOLDER = '__DOUBLE_ASTERISK__';
|
|
110
|
+
regexPattern = regexPattern.replace(/\*\*/g, DOUBLE_ASTERISK_PLACEHOLDER);
|
|
111
|
+
|
|
112
|
+
// Convert * to regex equivalent (any number of characters except /)
|
|
113
|
+
regexPattern = regexPattern.replace(/\*/g, '[^/]*');
|
|
114
|
+
|
|
115
|
+
// Convert the ** placeholder to its regex equivalent (any number of characters including /)
|
|
116
|
+
regexPattern = regexPattern.replace(new RegExp(DOUBLE_ASTERISK_PLACEHOLDER, 'g'), '.*');
|
|
117
|
+
|
|
118
|
+
// For absolute paths, we don't want to force the pattern to match from the beginning
|
|
119
|
+
// but we still want to ensure it matches to the end of the path segment
|
|
120
|
+
regexPattern = '(?:^|/)' + regexPattern + '$';
|
|
121
|
+
|
|
122
|
+
return regexPattern;
|
|
123
|
+
}).filter(pattern => pattern !== null);
|
|
124
|
+
|
|
125
|
+
if (regexPatterns.length === 0) {
|
|
126
|
+
// If all patterns were negations, return a regex that matches nothing
|
|
127
|
+
return new RegExp('^$');
|
|
163
128
|
}
|
|
164
129
|
|
|
165
|
-
|
|
130
|
+
// Join all patterns with | to create a single regex
|
|
131
|
+
const combinedPattern = regexPatterns.join('|');
|
|
132
|
+
return new RegExp(combinedPattern);
|
|
166
133
|
}
|
|
167
134
|
|
|
168
135
|
module.exports = {
|
|
169
|
-
|
|
136
|
+
createIgnoreRegex,
|
|
170
137
|
getMeteorIgnoreEntries,
|
|
171
138
|
createIgnoreGlobConfig,
|
|
172
139
|
};
|
package/lib/test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const {
|
|
3
|
+
const { createIgnoreRegex, createIgnoreGlobConfig } = require("./ignore.js");
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generates eager test files dynamically
|
|
@@ -8,33 +8,34 @@ const { createIgnoreFoldersRegex } = require("./ignore.js");
|
|
|
8
8
|
* @param {boolean} options.isAppTest - Whether this is an app test
|
|
9
9
|
* @param {string} options.projectDir - The project directory
|
|
10
10
|
* @param {string} options.buildContext - The build context
|
|
11
|
-
* @param {string} options.
|
|
12
|
-
* @param {string} options.nestedFolders
|
|
11
|
+
* @param {string[]} options.entries - Array of ignore patterns
|
|
13
12
|
* @returns {string} The path to the generated file
|
|
14
13
|
*/
|
|
15
14
|
const generateEagerTestFile = ({
|
|
16
15
|
isAppTest,
|
|
17
16
|
projectDir,
|
|
18
17
|
buildContext,
|
|
19
|
-
|
|
20
|
-
nestedFolders,
|
|
18
|
+
entries = [],
|
|
21
19
|
}) => {
|
|
22
20
|
const distDir = path.resolve(projectDir, ".meteor/local/test");
|
|
23
21
|
if (!fs.existsSync(distDir)) {
|
|
24
22
|
fs.mkdirSync(distDir, { recursive: true });
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
// Combine all ignore entries
|
|
26
|
+
const ignoreEntries = [
|
|
27
|
+
"**/node_modules/**",
|
|
28
|
+
"**/.meteor/**",
|
|
29
|
+
"**/public/**",
|
|
30
|
+
"**/private/**",
|
|
31
|
+
`**/${buildContext}/**`,
|
|
32
|
+
...entries,
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Create regex from ignore entries
|
|
36
|
+
const excludeFoldersRegex = createIgnoreRegex(
|
|
37
|
+
createIgnoreGlobConfig(ignoreEntries)
|
|
38
|
+
);
|
|
38
39
|
|
|
39
40
|
const filename = isAppTest ? "eager-app-tests.mjs" : "eager-tests.mjs";
|
|
40
41
|
const filePath = path.resolve(distDir, filename);
|
package/package.json
CHANGED
package/rspack.config.js
CHANGED
|
@@ -27,16 +27,16 @@ function safeRequire(moduleName) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// Persistent filesystem cache strategy
|
|
30
|
-
function createCacheStrategy(mode) {
|
|
30
|
+
function createCacheStrategy(mode, side) {
|
|
31
31
|
return {
|
|
32
32
|
cache: true,
|
|
33
33
|
experiments: {
|
|
34
34
|
cache: {
|
|
35
|
-
version: `swc-${mode}`,
|
|
36
|
-
type:
|
|
35
|
+
version: `swc-${mode}${(side && `-${side}`) || ""}`,
|
|
36
|
+
type: "persistent",
|
|
37
37
|
storage: {
|
|
38
|
-
type:
|
|
39
|
-
directory:
|
|
38
|
+
type: "filesystem",
|
|
39
|
+
directory: `node_modules/.cache/rspack${(side && `/${side}`) || ""}`,
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
},
|
|
@@ -195,22 +195,24 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
195
195
|
};
|
|
196
196
|
|
|
197
197
|
// Get Meteor ignore entries
|
|
198
|
-
const
|
|
198
|
+
const meteorIgnoreEntries = getMeteorIgnoreEntries(projectDir);
|
|
199
|
+
|
|
200
|
+
// Additional ignore entries
|
|
201
|
+
const additionalEntries = [
|
|
202
|
+
"**/.meteor/local/**",
|
|
203
|
+
"**/dist/**",
|
|
204
|
+
...(isTest && isTestEager
|
|
205
|
+
? [`**/${buildContext}/**`, "**/.meteor/local/**", "node_modules/**"]
|
|
206
|
+
: []),
|
|
207
|
+
];
|
|
199
208
|
|
|
200
209
|
// Set default watch options
|
|
201
210
|
const watchOptions = {
|
|
202
211
|
ignored: [
|
|
203
|
-
...createIgnoreGlobConfig(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
"dist",
|
|
208
|
-
...(isTest && isTestEager
|
|
209
|
-
? [buildContext, ".meteor/local", "node_modules"]
|
|
210
|
-
: []),
|
|
211
|
-
...(nestedFolders || []),
|
|
212
|
-
],
|
|
213
|
-
}),
|
|
212
|
+
...createIgnoreGlobConfig([
|
|
213
|
+
...meteorIgnoreEntries,
|
|
214
|
+
...additionalEntries,
|
|
215
|
+
]),
|
|
214
216
|
],
|
|
215
217
|
};
|
|
216
218
|
|
|
@@ -369,7 +371,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
369
371
|
},
|
|
370
372
|
},
|
|
371
373
|
}),
|
|
372
|
-
experiments: { css: true }
|
|
374
|
+
...merge(createCacheStrategy(mode, "client"), { experiments: { css: true } })
|
|
373
375
|
};
|
|
374
376
|
|
|
375
377
|
|
|
@@ -379,16 +381,14 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
379
381
|
isAppTest: true,
|
|
380
382
|
projectDir,
|
|
381
383
|
buildContext,
|
|
382
|
-
|
|
383
|
-
nestedFolders,
|
|
384
|
+
entries: meteorIgnoreEntries,
|
|
384
385
|
})
|
|
385
386
|
: isTest && isTestEager
|
|
386
387
|
? generateEagerTestFile({
|
|
387
388
|
isAppTest: false,
|
|
388
389
|
projectDir,
|
|
389
390
|
buildContext,
|
|
390
|
-
|
|
391
|
-
nestedFolders,
|
|
391
|
+
entries: meteorIgnoreEntries,
|
|
392
392
|
})
|
|
393
393
|
: path.resolve(projectDir, buildContext, entryPath);
|
|
394
394
|
const serverNameConfig = `[${(isTest && 'test-') || ''}${
|
|
@@ -449,7 +449,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
449
449
|
watchOptions,
|
|
450
450
|
devtool: isDevEnvironment || isNative || isTest ? 'source-map' : 'hidden-source-map',
|
|
451
451
|
...((isDevEnvironment || (isTest && !isTestEager) || isNative) &&
|
|
452
|
-
createCacheStrategy(mode)),
|
|
452
|
+
createCacheStrategy(mode, "server")),
|
|
453
453
|
};
|
|
454
454
|
|
|
455
455
|
// Load and apply project-level overrides for the selected build
|