@meteorjs/rspack 0.0.53 → 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 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 {Object} - Object with rootFolders and nestedFolders arrays
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/).filter(line => {
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
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 arrays
76
- return { rootFolders: [], nestedFolders: [] };
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 regex pattern to ignore specified folders.
82
- * The pattern will match paths where the specified folders appear as complete path segments.
83
- * Special regex characters in folder names are automatically escaped.
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
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 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');
36
+ function createIgnoreGlobConfig(entries = []) {
37
+ if (!Array.isArray(entries)) {
38
+ throw new Error('Entries must be an array');
95
39
  }
96
40
 
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
- );
41
+ const globPatterns = [];
103
42
 
104
- // Join folder names with | for the regex pattern
105
- const foldersPattern = escapedFolders.join('|');
43
+ entries.forEach(entry => {
44
+ // Skip empty entries
45
+ if (!entry.trim()) {
46
+ return;
47
+ }
106
48
 
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
- }
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
- // Handle both rootFolders and nestedFolders
113
- // Escape special regex characters in folder names
114
- const escapedNestedFolders = nestedFolders.map(folder =>
115
- folder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
116
- );
117
-
118
- const escapedRootFolders = rootFolders.map(folder =>
119
- folder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
120
- );
121
-
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);
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 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
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 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
- });
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
- // 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
- });
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
- return globPatterns;
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
- createIgnoreFoldersRegex,
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 { createIgnoreFoldersRegex } = require("./ignore.js");
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.rootFolders
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
- rootFolders,
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
- const excludeFoldersRegex = createIgnoreFoldersRegex({
28
- nestedFolders: [
29
- "node_modules",
30
- ".meteor",
31
- "public",
32
- "private",
33
- buildContext,
34
- ...nestedFolders,
35
- ],
36
- rootFolders,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meteorjs/rspack",
3
- "version": "0.0.53",
3
+ "version": "0.0.54",
4
4
  "description": "Configuration logic for using Rspack in Meteor projects",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
package/rspack.config.js CHANGED
@@ -195,22 +195,24 @@ module.exports = async function (inMeteor = {}, argv = {}) {
195
195
  };
196
196
 
197
197
  // Get Meteor ignore entries
198
- const { rootFolders, nestedFolders } = getMeteorIgnoreEntries(projectDir);
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
- rootFolders,
205
- nestedFolders: [
206
- ".meteor/local",
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
 
@@ -379,16 +381,14 @@ module.exports = async function (inMeteor = {}, argv = {}) {
379
381
  isAppTest: true,
380
382
  projectDir,
381
383
  buildContext,
382
- rootFolders,
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
- rootFolders,
391
- nestedFolders,
391
+ entries: meteorIgnoreEntries,
392
392
  })
393
393
  : path.resolve(projectDir, buildContext, entryPath);
394
394
  const serverNameConfig = `[${(isTest && 'test-') || ''}${