@meteorjs/rspack 0.0.53 → 0.0.55
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 +20 -18
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
|
@@ -50,6 +50,7 @@ function createSwcConfig({
|
|
|
50
50
|
isTsxEnabled,
|
|
51
51
|
externalHelpers,
|
|
52
52
|
isDevEnvironment,
|
|
53
|
+
isClient,
|
|
53
54
|
}) {
|
|
54
55
|
const defaultConfig = {
|
|
55
56
|
jsc: {
|
|
@@ -64,7 +65,7 @@ function createSwcConfig({
|
|
|
64
65
|
transform: {
|
|
65
66
|
react: {
|
|
66
67
|
development: isDevEnvironment,
|
|
67
|
-
refresh: isDevEnvironment,
|
|
68
|
+
...(isClient && { refresh: isDevEnvironment }),
|
|
68
69
|
},
|
|
69
70
|
},
|
|
70
71
|
externalHelpers,
|
|
@@ -195,22 +196,24 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
195
196
|
};
|
|
196
197
|
|
|
197
198
|
// Get Meteor ignore entries
|
|
198
|
-
const
|
|
199
|
+
const meteorIgnoreEntries = getMeteorIgnoreEntries(projectDir);
|
|
200
|
+
|
|
201
|
+
// Additional ignore entries
|
|
202
|
+
const additionalEntries = [
|
|
203
|
+
"**/.meteor/local/**",
|
|
204
|
+
"**/dist/**",
|
|
205
|
+
...(isTest && isTestEager
|
|
206
|
+
? [`**/${buildContext}/**`, "**/.meteor/local/**", "node_modules/**"]
|
|
207
|
+
: []),
|
|
208
|
+
];
|
|
199
209
|
|
|
200
210
|
// Set default watch options
|
|
201
211
|
const watchOptions = {
|
|
202
212
|
ignored: [
|
|
203
|
-
...createIgnoreGlobConfig(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
"dist",
|
|
208
|
-
...(isTest && isTestEager
|
|
209
|
-
? [buildContext, ".meteor/local", "node_modules"]
|
|
210
|
-
: []),
|
|
211
|
-
...(nestedFolders || []),
|
|
212
|
-
],
|
|
213
|
-
}),
|
|
213
|
+
...createIgnoreGlobConfig([
|
|
214
|
+
...meteorIgnoreEntries,
|
|
215
|
+
...additionalEntries,
|
|
216
|
+
]),
|
|
214
217
|
],
|
|
215
218
|
};
|
|
216
219
|
|
|
@@ -227,6 +230,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
227
230
|
isTsxEnabled,
|
|
228
231
|
externalHelpers: enableSwcExternalHelpers,
|
|
229
232
|
isDevEnvironment,
|
|
233
|
+
isClient,
|
|
230
234
|
});
|
|
231
235
|
// Expose swc config to use in custom configs
|
|
232
236
|
Meteor.swcConfigOptions = swcConfigRule.options;
|
|
@@ -272,7 +276,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
272
276
|
const rsdoctorModule = isBundleVisualizerEnabled
|
|
273
277
|
? safeRequire('@rsdoctor/rspack-plugin')
|
|
274
278
|
: null;
|
|
275
|
-
const doctorPluginConfig = isBundleVisualizerEnabled && rsdoctorModule?.RsdoctorRspackPlugin
|
|
279
|
+
const doctorPluginConfig = isRun && isBundleVisualizerEnabled && rsdoctorModule?.RsdoctorRspackPlugin
|
|
276
280
|
? [
|
|
277
281
|
new rsdoctorModule.RsdoctorRspackPlugin({
|
|
278
282
|
port: isClient
|
|
@@ -379,16 +383,14 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
379
383
|
isAppTest: true,
|
|
380
384
|
projectDir,
|
|
381
385
|
buildContext,
|
|
382
|
-
|
|
383
|
-
nestedFolders,
|
|
386
|
+
entries: meteorIgnoreEntries,
|
|
384
387
|
})
|
|
385
388
|
: isTest && isTestEager
|
|
386
389
|
? generateEagerTestFile({
|
|
387
390
|
isAppTest: false,
|
|
388
391
|
projectDir,
|
|
389
392
|
buildContext,
|
|
390
|
-
|
|
391
|
-
nestedFolders,
|
|
393
|
+
entries: meteorIgnoreEntries,
|
|
392
394
|
})
|
|
393
395
|
: path.resolve(projectDir, buildContext, entryPath);
|
|
394
396
|
const serverNameConfig = `[${(isTest && 'test-') || ''}${
|