@meteorjs/rspack 0.0.51 → 0.0.52
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 +97 -42
- package/lib/test.js +21 -10
- package/package.json +1 -1
- package/rspack.config.js +36 -23
package/lib/ignore.js
CHANGED
|
@@ -33,14 +33,9 @@ function cleanWildcardEntry(entry) {
|
|
|
33
33
|
* the parsed entries.
|
|
34
34
|
*
|
|
35
35
|
* @param {string} projectDir - The project directory path
|
|
36
|
-
* @
|
|
37
|
-
* @param {boolean} options.foldersOnly - If true, returns only folder entries
|
|
38
|
-
* @returns {Array<string>} - Array of ignore entries
|
|
36
|
+
* @returns {Object} - Object with rootFolders and nestedFolders arrays
|
|
39
37
|
*/
|
|
40
|
-
const getMeteorIgnoreEntries = function (projectDir
|
|
41
|
-
options = options || {};
|
|
42
|
-
const foldersOnly = !!options.foldersOnly;
|
|
43
|
-
|
|
38
|
+
const getMeteorIgnoreEntries = function (projectDir) {
|
|
44
39
|
const meteorIgnorePath = path.join(projectDir, '.meteorignore');
|
|
45
40
|
|
|
46
41
|
// Check if .meteorignore file exists
|
|
@@ -50,39 +45,35 @@ const getMeteorIgnoreEntries = function (projectDir, options) {
|
|
|
50
45
|
|
|
51
46
|
// Process each line in the file
|
|
52
47
|
entries = fileContent.split(/\r?\n/).filter(line => {
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
// Trim the line
|
|
49
|
+
const trimmedLine = line.trim();
|
|
50
|
+
// Skip empty lines, comments, and negation entries (starting with !)
|
|
51
|
+
return trimmedLine !== '' && !trimmedLine.startsWith('#') && !trimmedLine.startsWith('!');
|
|
52
|
+
}).map(line => line.trim()); // Ensure all lines are trimmed
|
|
56
53
|
|
|
57
54
|
// Clean all entries from wildcard patterns (*/** parts)
|
|
58
55
|
entries = entries.map(entry => {
|
|
59
56
|
return cleanWildcardEntry(entry);
|
|
60
57
|
}).filter(entry => entry !== null);
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
} catch (e) {
|
|
76
|
-
// If we can't determine, assume it's not a folder
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
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
|
+
});
|
|
81
72
|
|
|
82
|
-
return
|
|
73
|
+
return { rootFolders, nestedFolders };
|
|
83
74
|
} catch (e) {
|
|
84
|
-
// If the file doesn't exist or can't be read, return
|
|
85
|
-
return [];
|
|
75
|
+
// If the file doesn't exist or can't be read, return empty arrays
|
|
76
|
+
return { rootFolders: [], nestedFolders: [] };
|
|
86
77
|
}
|
|
87
78
|
};
|
|
88
79
|
|
|
@@ -90,28 +81,92 @@ const getMeteorIgnoreEntries = function (projectDir, options) {
|
|
|
90
81
|
* Creates a regex pattern to ignore specified folders.
|
|
91
82
|
* The pattern will match paths where the specified folders appear as complete path segments.
|
|
92
83
|
* Special regex characters in folder names are automatically escaped.
|
|
93
|
-
* @param {string[]}
|
|
84
|
+
* @param {Object|string[]} options - Options object
|
|
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
|
|
94
87
|
* @returns {RegExp} - Regex pattern to ignore the specified folders
|
|
95
88
|
*/
|
|
96
|
-
function createIgnoreFoldersRegex(
|
|
97
|
-
|
|
98
|
-
|
|
89
|
+
function createIgnoreFoldersRegex(options) {
|
|
90
|
+
const nestedFolders = options.nestedFolders || [];
|
|
91
|
+
const rootFolders = options.rootFolders || [];
|
|
92
|
+
|
|
93
|
+
if (!Array.isArray(nestedFolders) || nestedFolders.length === 0) {
|
|
94
|
+
throw new Error('nestedFolders must be a non-empty array');
|
|
99
95
|
}
|
|
100
96
|
|
|
97
|
+
// If rootFolders is not provided or empty, use the original behavior
|
|
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
|
+
);
|
|
103
|
+
|
|
104
|
+
// Join folder names with | for the regex pattern
|
|
105
|
+
const foldersPattern = escapedFolders.join('|');
|
|
106
|
+
|
|
107
|
+
// Create a regex that matches paths where the specified folders appear as complete path segments
|
|
108
|
+
// Format: /(^|\/)(folder1|folder2|folder3)(\/|$)/
|
|
109
|
+
return new RegExp(`(^|\\/)(${foldersPattern})(\\/|$)`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Handle both rootFolders and nestedFolders
|
|
101
113
|
// Escape special regex characters in folder names
|
|
102
|
-
const
|
|
114
|
+
const escapedNestedFolders = nestedFolders.map(folder =>
|
|
115
|
+
folder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const escapedRootFolders = rootFolders.map(folder =>
|
|
103
119
|
folder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
104
120
|
);
|
|
105
121
|
|
|
106
|
-
// Join folder names with | for the regex
|
|
107
|
-
const
|
|
122
|
+
// Join folder names with | for the regex patterns
|
|
123
|
+
const nestedFoldersPattern = escapedNestedFolders.join('|');
|
|
124
|
+
const rootFoldersPattern = escapedRootFolders.join('|');
|
|
125
|
+
|
|
126
|
+
// Create a regex that matches:
|
|
127
|
+
// 1. Root folders at the beginning of the path: /^(folderRootOnly)(\/|$)/
|
|
128
|
+
// 2. Nested folders anywhere in the path: /(^|\/)(folderAny1|folderAny2)(\/|$)/
|
|
129
|
+
const pattern = `^(${rootFoldersPattern})(\\/|$)|(^|\\/)(${nestedFoldersPattern})(\\/|$)`;
|
|
130
|
+
return new RegExp(pattern);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Creates a glob config array for ignoring specified folders.
|
|
135
|
+
* For nested folders, the pattern will be "**/" + folder + "/**".
|
|
136
|
+
* For root folders, the pattern will be folder + "/**".
|
|
137
|
+
* @param {Object} options - Options object
|
|
138
|
+
* @param {string[]} [options.nestedFolders] - Array of folder names to ignore anywhere in the path
|
|
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
|
|
141
|
+
*/
|
|
142
|
+
function createIgnoreGlobConfig(options = {}) {
|
|
143
|
+
const nestedFolders = options.nestedFolders || [];
|
|
144
|
+
const rootFolders = options.rootFolders || [];
|
|
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
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Create glob patterns for root folders: {rootFolder}/**
|
|
157
|
+
if (Array.isArray(rootFolders) && rootFolders.length > 0) {
|
|
158
|
+
rootFolders.forEach(folder => {
|
|
159
|
+
// Remove leading ./ or / if present
|
|
160
|
+
const cleanFolder = folder.replace(/^(\.\/|\/)/g, '');
|
|
161
|
+
globPatterns.push(`${cleanFolder}/**`);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
108
164
|
|
|
109
|
-
|
|
110
|
-
// Format: /(^|\/)(folder1|folder2|folder3)(\/|$)/
|
|
111
|
-
return new RegExp(`(^|\\/)(${foldersPattern})(\\/|$)`);
|
|
165
|
+
return globPatterns;
|
|
112
166
|
}
|
|
113
167
|
|
|
114
168
|
module.exports = {
|
|
115
169
|
createIgnoreFoldersRegex,
|
|
116
170
|
getMeteorIgnoreEntries,
|
|
171
|
+
createIgnoreGlobConfig,
|
|
117
172
|
};
|
package/lib/test.js
CHANGED
|
@@ -1,29 +1,40 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const { createIgnoreFoldersRegex
|
|
3
|
+
const { createIgnoreFoldersRegex } = require("./ignore.js");
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generates eager test files dynamically
|
|
7
7
|
* @param {Object} options - Options for generating the test file
|
|
8
8
|
* @param {boolean} options.isAppTest - Whether this is an app test
|
|
9
9
|
* @param {string} options.projectDir - The project directory
|
|
10
|
+
* @param {string} options.buildContext - The build context
|
|
11
|
+
* @param {string} options.rootFolders
|
|
12
|
+
* @param {string} options.nestedFolders
|
|
10
13
|
* @returns {string} The path to the generated file
|
|
11
14
|
*/
|
|
12
|
-
const generateEagerTestFile = ({
|
|
15
|
+
const generateEagerTestFile = ({
|
|
16
|
+
isAppTest,
|
|
17
|
+
projectDir,
|
|
18
|
+
buildContext,
|
|
19
|
+
rootFolders,
|
|
20
|
+
nestedFolders,
|
|
21
|
+
}) => {
|
|
13
22
|
const distDir = path.resolve(projectDir, ".meteor/local/test");
|
|
14
23
|
if (!fs.existsSync(distDir)) {
|
|
15
24
|
fs.mkdirSync(distDir, { recursive: true });
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
const
|
|
19
|
-
|
|
27
|
+
const excludeFoldersRegex = createIgnoreFoldersRegex({
|
|
28
|
+
nestedFolders: [
|
|
29
|
+
"node_modules",
|
|
30
|
+
".meteor",
|
|
31
|
+
"public",
|
|
32
|
+
"private",
|
|
33
|
+
buildContext,
|
|
34
|
+
...nestedFolders,
|
|
35
|
+
],
|
|
36
|
+
rootFolders,
|
|
20
37
|
});
|
|
21
|
-
const excludeFoldersRegex = createIgnoreFoldersRegex([
|
|
22
|
-
"node_modules",
|
|
23
|
-
".meteor",
|
|
24
|
-
"_build",
|
|
25
|
-
...ignoredFolders,
|
|
26
|
-
]);
|
|
27
38
|
|
|
28
39
|
const filename = isAppTest ? "eager-app-tests.mjs" : "eager-tests.mjs";
|
|
29
40
|
const filePath = path.resolve(distDir, filename);
|
package/package.json
CHANGED
package/rspack.config.js
CHANGED
|
@@ -8,8 +8,8 @@ const { cleanOmittedPaths, mergeSplitOverlap } = require("./lib/mergeRulesSplitO
|
|
|
8
8
|
const { getMeteorAppSwcConfig } = require('./lib/swc.js');
|
|
9
9
|
const HtmlRspackPlugin = require('./plugins/HtmlRspackPlugin.js');
|
|
10
10
|
const { RequireExternalsPlugin } = require('./plugins/RequireExtenalsPlugin.js');
|
|
11
|
-
const { createIgnoreFoldersRegex, getMeteorIgnoreEntries } = require("./lib/ignore.js");
|
|
12
11
|
const { generateEagerTestFile } = require("./lib/test.js");
|
|
12
|
+
const { getMeteorIgnoreEntries, createIgnoreGlobConfig } = require("./lib/ignore");
|
|
13
13
|
|
|
14
14
|
// Safe require that doesn't throw if the module isn't found
|
|
15
15
|
function safeRequire(moduleName) {
|
|
@@ -103,11 +103,6 @@ function keepOutsideBuild() {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
// Watch options shared across both builds
|
|
107
|
-
const defaultWatchOptions = {
|
|
108
|
-
ignored: ['**/.meteor/local/**', '**/dist/**'],
|
|
109
|
-
};
|
|
110
|
-
|
|
111
106
|
/**
|
|
112
107
|
* @param {{ isClient: boolean; isServer: boolean; isDevelopment?: boolean; isProduction?: boolean; isTest?: boolean }} Meteor
|
|
113
108
|
* @param {{ mode?: string; clientEntry?: string; serverEntry?: string; clientOutputFolder?: string; serverOutputFolder?: string; chunksContext?: string; assetsContext?: string; serverAssetsContext?: string }} argv
|
|
@@ -165,8 +160,8 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
165
160
|
const bannerOutput = JSON.parse(Meteor.bannerOutput || process.env.RSPACK_BANNER || '""');
|
|
166
161
|
|
|
167
162
|
// Determine output directories
|
|
168
|
-
const clientOutputDir = path.resolve(
|
|
169
|
-
const serverOutputDir = path.resolve(
|
|
163
|
+
const clientOutputDir = path.resolve(projectDir, 'public');
|
|
164
|
+
const serverOutputDir = path.resolve(projectDir, 'private');
|
|
170
165
|
|
|
171
166
|
// Determine context for bundles and assets
|
|
172
167
|
const buildContext = Meteor.buildContext || '_build';
|
|
@@ -174,7 +169,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
174
169
|
const chunksContext = Meteor.chunksContext || 'build-chunks';
|
|
175
170
|
|
|
176
171
|
// Determine build output and pass to Meteor
|
|
177
|
-
const buildOutputDir = path.resolve(
|
|
172
|
+
const buildOutputDir = path.resolve(projectDir, buildContext, outputDir);
|
|
178
173
|
Meteor.buildOutputDir = buildOutputDir;
|
|
179
174
|
|
|
180
175
|
// Add HtmlRspackPlugin function to Meteor
|
|
@@ -199,18 +194,24 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
199
194
|
});
|
|
200
195
|
};
|
|
201
196
|
|
|
202
|
-
//
|
|
197
|
+
// Get Meteor ignore entries
|
|
198
|
+
const { rootFolders, nestedFolders } = getMeteorIgnoreEntries(projectDir);
|
|
199
|
+
|
|
200
|
+
// Set default watch options
|
|
203
201
|
const watchOptions = {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
202
|
+
ignored: [
|
|
203
|
+
...createIgnoreGlobConfig({
|
|
204
|
+
rootFolders,
|
|
205
|
+
nestedFolders: [
|
|
206
|
+
".meteor/local",
|
|
207
|
+
"dist",
|
|
208
|
+
...(isTest && isTestEager
|
|
209
|
+
? [buildContext, ".meteor/local", "node_modules"]
|
|
210
|
+
: []),
|
|
211
|
+
...(nestedFolders || []),
|
|
212
212
|
],
|
|
213
213
|
}),
|
|
214
|
+
],
|
|
214
215
|
};
|
|
215
216
|
|
|
216
217
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
@@ -374,10 +375,22 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
374
375
|
|
|
375
376
|
const serverEntry =
|
|
376
377
|
isTest && isTestEager && isTestFullApp
|
|
377
|
-
? generateEagerTestFile({
|
|
378
|
+
? generateEagerTestFile({
|
|
379
|
+
isAppTest: true,
|
|
380
|
+
projectDir,
|
|
381
|
+
buildContext,
|
|
382
|
+
rootFolders,
|
|
383
|
+
nestedFolders,
|
|
384
|
+
})
|
|
378
385
|
: isTest && isTestEager
|
|
379
|
-
? generateEagerTestFile({
|
|
380
|
-
|
|
386
|
+
? generateEagerTestFile({
|
|
387
|
+
isAppTest: false,
|
|
388
|
+
projectDir,
|
|
389
|
+
buildContext,
|
|
390
|
+
rootFolders,
|
|
391
|
+
nestedFolders,
|
|
392
|
+
})
|
|
393
|
+
: path.resolve(projectDir, buildContext, entryPath);
|
|
381
394
|
const serverNameConfig = `[${(isTest && 'test-') || ''}${
|
|
382
395
|
(isTestModule && 'module') || 'server'
|
|
383
396
|
}-rspack]`;
|
|
@@ -408,7 +421,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
408
421
|
resolve: {
|
|
409
422
|
extensions,
|
|
410
423
|
alias,
|
|
411
|
-
modules: ['node_modules', path.resolve(
|
|
424
|
+
modules: ['node_modules', path.resolve(projectDir)],
|
|
412
425
|
conditionNames: ['import', 'require', 'node', 'default'],
|
|
413
426
|
},
|
|
414
427
|
externals,
|
|
@@ -441,7 +454,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
441
454
|
|
|
442
455
|
// Load and apply project-level overrides for the selected build
|
|
443
456
|
// Check if we're in a Meteor package directory by looking at the path
|
|
444
|
-
const isMeteorPackageConfig =
|
|
457
|
+
const isMeteorPackageConfig = projectDir.includes('/packages/rspack');
|
|
445
458
|
if (fs.existsSync(projectConfigPath) && !isMeteorPackageConfig) {
|
|
446
459
|
// Check if there's a .mjs or .cjs version of the config file
|
|
447
460
|
const mjsConfigPath = projectConfigPath.replace(/\.js$/, '.mjs');
|