@aneuhold/core-ts-lib 2.2.7 → 2.2.8
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/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/index.ts +7 -5
- package/lib/interfaces/ITracer.d.ts.map +1 -1
- package/lib/interfaces/ITracer.js.map +1 -1
- package/lib/interfaces/ITracer.ts +2 -8
- package/lib/services/ArrayService.d.ts.map +1 -1
- package/lib/services/ArrayService.js.map +1 -1
- package/lib/services/ArrayService.ts +1 -4
- package/lib/services/DateService/DateService.d.ts.map +1 -1
- package/lib/services/DateService/DateService.js +1 -3
- package/lib/services/DateService/DateService.js.map +1 -1
- package/lib/services/DateService/DateService.ts +7 -25
- package/lib/services/DependencyService.d.ts.map +1 -1
- package/lib/services/DependencyService.js +1 -3
- package/lib/services/DependencyService.js.map +1 -1
- package/lib/services/DependencyService.ts +10 -32
- package/lib/services/FileSystemService/FileSystemService.d.ts +38 -12
- package/lib/services/FileSystemService/FileSystemService.d.ts.map +1 -1
- package/lib/services/FileSystemService/FileSystemService.js +83 -26
- package/lib/services/FileSystemService/FileSystemService.js.map +1 -1
- package/lib/services/FileSystemService/FileSystemService.ts +138 -53
- package/lib/services/FileSystemService/GlobMatchingService.d.ts +48 -0
- package/lib/services/FileSystemService/GlobMatchingService.d.ts.map +1 -0
- package/lib/services/FileSystemService/GlobMatchingService.js +129 -0
- package/lib/services/FileSystemService/GlobMatchingService.js.map +1 -0
- package/lib/services/FileSystemService/GlobMatchingService.ts +153 -0
- package/lib/services/PackageService.d.ts +60 -4
- package/lib/services/PackageService.d.ts.map +1 -1
- package/lib/services/PackageService.js +182 -43
- package/lib/services/PackageService.js.map +1 -1
- package/lib/services/PackageService.ts +241 -119
- package/lib/utils/ErrorUtils.d.ts.map +1 -1
- package/lib/utils/ErrorUtils.js.map +1 -1
- package/lib/utils/ErrorUtils.ts +1 -3
- package/package.json +1 -1
- package/lib/services/DateService/DateService.spec.ts +0 -98
- package/lib/services/FileSystemService/FileSystemService.spec.ts +0 -133
|
@@ -5,6 +5,7 @@ import { promisify } from 'util';
|
|
|
5
5
|
import ErrorUtils from '../../utils/ErrorUtils.js';
|
|
6
6
|
import { DR } from '../DependencyRegistry.js';
|
|
7
7
|
import StringService from '../StringService.js';
|
|
8
|
+
import GlobMatchingService from './GlobMatchingService.js';
|
|
8
9
|
const execAsync = promisify(exec);
|
|
9
10
|
/**
|
|
10
11
|
* A service which can be used to interact with the file system, only in build
|
|
@@ -18,8 +19,8 @@ export default class FileSystemService {
|
|
|
18
19
|
*
|
|
19
20
|
* @param folderPath the path to the folder which contains the file that should
|
|
20
21
|
* be updated
|
|
21
|
-
* @param fileName
|
|
22
|
-
* @param textToInsert
|
|
22
|
+
* @param fileName the name of the file to update
|
|
23
|
+
* @param textToInsert the text to insert into the file
|
|
23
24
|
*/
|
|
24
25
|
static async findAndInsertText(folderPath, fileName, textToInsert) {
|
|
25
26
|
const filePath = path.join(folderPath, fileName);
|
|
@@ -43,8 +44,8 @@ export default class FileSystemService {
|
|
|
43
44
|
/**
|
|
44
45
|
* Copies the contents of one folder to another folder.
|
|
45
46
|
*
|
|
46
|
-
* @param sourceFolderPath
|
|
47
|
-
* @param targetFolderPath
|
|
47
|
+
* @param sourceFolderPath the path to the source folder
|
|
48
|
+
* @param targetFolderPath the path to the target folder
|
|
48
49
|
* @param ignoreExtensions is an array with extensions that should be
|
|
49
50
|
* ignored. For example, if you want to ignore all .ts files, you would pass
|
|
50
51
|
* in ['.ts']. Multi-part extensions like '.spec.ts' are also supported.
|
|
@@ -65,32 +66,12 @@ export default class FileSystemService {
|
|
|
65
66
|
const sourceFile = path.join(sourceFolderPath, sourceFilePath);
|
|
66
67
|
const targetFile = path.join(targetFolderPath, sourceFilePath);
|
|
67
68
|
// Check if the file should be ignored based on extensions
|
|
68
|
-
if (ignoreExtensions &&
|
|
69
|
-
FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)) {
|
|
69
|
+
if (ignoreExtensions && FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)) {
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
await cp(sourceFile, targetFile, { recursive: true });
|
|
73
73
|
}));
|
|
74
74
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Checks if a file should be ignored based on the provided extensions.
|
|
77
|
-
* Supports both simple extensions (e.g., '.ts') and multi-part extensions (e.g., '.spec.ts').
|
|
78
|
-
*
|
|
79
|
-
* @param filePath the path to the file to check
|
|
80
|
-
* @param ignoreExtensions array of extensions to ignore
|
|
81
|
-
*/
|
|
82
|
-
static shouldIgnoreFile(filePath, ignoreExtensions) {
|
|
83
|
-
const fileName = path.basename(filePath);
|
|
84
|
-
return ignoreExtensions.some((extension) => {
|
|
85
|
-
// Handle multi-part extensions like '.spec.ts'
|
|
86
|
-
if (extension.includes('.', 1)) {
|
|
87
|
-
return fileName.endsWith(extension);
|
|
88
|
-
}
|
|
89
|
-
// Handle simple extensions like '.ts'
|
|
90
|
-
const fileExtension = StringService.getFileNameExtension(filePath);
|
|
91
|
-
return fileExtension === extension;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
75
|
static async checkOrCreateFolder(folderPath) {
|
|
95
76
|
try {
|
|
96
77
|
await access(folderPath);
|
|
@@ -146,7 +127,11 @@ export default class FileSystemService {
|
|
|
146
127
|
static async getAllFilePathsRelative(dirPath) {
|
|
147
128
|
const filePaths = await this.getAllFilePaths(dirPath);
|
|
148
129
|
return filePaths.map((filePath) => {
|
|
149
|
-
|
|
130
|
+
const relativePath = filePath.replace(dirPath, '');
|
|
131
|
+
// Remove leading path separator if present
|
|
132
|
+
return relativePath.startsWith('/') || relativePath.startsWith('\\')
|
|
133
|
+
? relativePath.slice(1)
|
|
134
|
+
: relativePath;
|
|
150
135
|
});
|
|
151
136
|
}
|
|
152
137
|
/**
|
|
@@ -193,6 +178,59 @@ export default class FileSystemService {
|
|
|
193
178
|
return this.traverseDirectoryTree(startDir, fileName, stopAt, false // findFirst = false
|
|
194
179
|
);
|
|
195
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Replaces all occurrences of a string in files within a directory.
|
|
183
|
+
* Supports glob patterns for including/excluding files and handles URL encoding.
|
|
184
|
+
*
|
|
185
|
+
* @param options Configuration object for the replacement operation
|
|
186
|
+
*/
|
|
187
|
+
static async replaceInFiles(options) {
|
|
188
|
+
const { searchString, replaceString, rootPath, includePatterns = ['**/*'], excludePatterns = ['**/node_modules/**', '**/.*/**'], includeUrlEncoded = true, dryRun = false } = options;
|
|
189
|
+
DR.logger.info(`Replacing "${searchString}" with "${replaceString}" in ${rootPath}`);
|
|
190
|
+
if (dryRun) {
|
|
191
|
+
DR.logger.info('DRY RUN MODE - No files will be modified');
|
|
192
|
+
}
|
|
193
|
+
const allFiles = await this.getAllFilePaths(rootPath);
|
|
194
|
+
const filesToProcess = GlobMatchingService.getMatchingFiles(allFiles, rootPath, includePatterns, excludePatterns);
|
|
195
|
+
let processedCount = 0;
|
|
196
|
+
let modifiedCount = 0;
|
|
197
|
+
for (const filePath of filesToProcess) {
|
|
198
|
+
try {
|
|
199
|
+
const content = await readFile(filePath, 'utf8');
|
|
200
|
+
let hasChanges = false;
|
|
201
|
+
let updatedContent = content;
|
|
202
|
+
// Replace the main string
|
|
203
|
+
if (content.includes(searchString)) {
|
|
204
|
+
updatedContent = updatedContent.replaceAll(searchString, replaceString);
|
|
205
|
+
hasChanges = true;
|
|
206
|
+
}
|
|
207
|
+
// Replace URL-encoded version if requested
|
|
208
|
+
if (includeUrlEncoded) {
|
|
209
|
+
const encodedSearchString = encodeURIComponent(searchString);
|
|
210
|
+
const encodedReplaceString = encodeURIComponent(replaceString);
|
|
211
|
+
if (updatedContent.includes(encodedSearchString)) {
|
|
212
|
+
updatedContent = updatedContent.replaceAll(encodedSearchString, encodedReplaceString);
|
|
213
|
+
hasChanges = true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (hasChanges) {
|
|
217
|
+
const relativePath = path.relative(rootPath, filePath);
|
|
218
|
+
DR.logger.info(`${dryRun ? 'Would update' : 'Updating'} ${relativePath}...`);
|
|
219
|
+
if (!dryRun) {
|
|
220
|
+
await writeFile(filePath, updatedContent, 'utf8');
|
|
221
|
+
}
|
|
222
|
+
modifiedCount++;
|
|
223
|
+
}
|
|
224
|
+
processedCount++;
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
// Skip binary files or files we can't read
|
|
228
|
+
DR.logger.verbose.info(`Skipping ${filePath}: ${ErrorUtils.getErrorString(error)}`);
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
DR.logger.info(`${dryRun ? 'Would process' : 'Processed'} ${processedCount} files, ${dryRun ? 'would modify' : 'modified'} ${modifiedCount} files`);
|
|
233
|
+
}
|
|
196
234
|
/**
|
|
197
235
|
* Internal helper method that traverses up the directory tree looking for files.
|
|
198
236
|
*
|
|
@@ -235,5 +273,24 @@ export default class FileSystemService {
|
|
|
235
273
|
}
|
|
236
274
|
return results;
|
|
237
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Checks if a file should be ignored based on the provided extensions.
|
|
278
|
+
* Supports both simple extensions (e.g., '.ts') and multi-part extensions (e.g., '.spec.ts').
|
|
279
|
+
*
|
|
280
|
+
* @param filePath the path to the file to check
|
|
281
|
+
* @param ignoreExtensions array of extensions to ignore
|
|
282
|
+
*/
|
|
283
|
+
static shouldIgnoreFile(filePath, ignoreExtensions) {
|
|
284
|
+
const fileName = path.basename(filePath);
|
|
285
|
+
return ignoreExtensions.some((extension) => {
|
|
286
|
+
// Handle multi-part extensions like '.spec.ts'
|
|
287
|
+
if (extension.includes('.', 1)) {
|
|
288
|
+
return fileName.endsWith(extension);
|
|
289
|
+
}
|
|
290
|
+
// Handle simple extensions like '.ts'
|
|
291
|
+
const fileExtension = StringService.getFileNameExtension(filePath);
|
|
292
|
+
return fileExtension === extension;
|
|
293
|
+
});
|
|
294
|
+
}
|
|
238
295
|
}
|
|
239
296
|
//# sourceMappingURL=FileSystemService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileSystemService.js","sourceRoot":"","sources":["../../../src/services/FileSystemService/FileSystemService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,
|
|
1
|
+
{"version":3,"file":"FileSystemService.js","sourceRoot":"","sources":["../../../src/services/FileSystemService/FileSystemService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,UAAU,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAE3D,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAsBlC;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAC5B,UAAkB,EAClB,QAAgB,EAChB,YAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEjD,MAAM,iBAAiB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAExD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvB,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBACzC,MAAM,UAAU,CAAC,QAAQ,EAAE,KAAK,YAAY,EAAE,CAAC,CAAC;gBAChD,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,YAAY,SAAS,QAAQ,GAAG,CAAC,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,wBAAwB,QAAQ,GAAG,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,YAAY,QAAQ,+CAA+C,YAAY,UAAU,CAC1F,CAAC;YACF,MAAM,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAC7B,gBAAwB,EACxB,gBAAwB,EACxB,gBAA2B;QAE3B,6CAA6C;QAC7C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,gBAAgB,mBAAmB,CAAC,CAAC;YAC1E,OAAO;QACT,CAAC;QACD,MAAM,iBAAiB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;QAE9D,wCAAwC;QACxC,MAAM,eAAe,GAAG,MAAM,iBAAiB,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;QAE1F,MAAM,OAAO,CAAC,GAAG,CACf,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;YAE/D,0DAA0D;YAC1D,IAAI,gBAAgB,IAAI,iBAAiB,CAAC,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;gBACzF,OAAO;YACT,CAAC;YAED,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,UAAkB;QACjD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,UAAU,sCAAsC,CAAC,CAAC;YACvF,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,UAAkB;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,UAAU,mBAAmB,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,OAAe;QAC1C,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,OAAO,CAAC,GAAG,CACf,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACtD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;YAE1C,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC3B,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QAEF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,OAAe;QAClD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACtD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;YAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACnD,2CAA2C;YAC3C,OAAO,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;gBAClE,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;gBACvB,CAAC,CAAC,YAAY,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,iBAAiB;QAC5B,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,wBAAwB,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC5F,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc,CACzB,QAAgB,EAChB,QAAgB,EAChB,MAAe;QAEf,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAC9C,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,IAAI,CAAC,mBAAmB;SACzB,CAAC;QACF,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;IAED;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAC7B,QAAgB,EAChB,QAAgB,EAChB,MAAe;QAEf,OAAO,IAAI,CAAC,qBAAqB,CAC/B,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,KAAK,CAAC,oBAAoB;SAC3B,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAA8B;QACxD,MAAM,EACJ,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,eAAe,GAAG,CAAC,MAAM,CAAC,EAC1B,eAAe,GAAG,CAAC,oBAAoB,EAAE,UAAU,CAAC,EACpD,iBAAiB,GAAG,IAAI,EACxB,MAAM,GAAG,KAAK,EACf,GAAG,OAAO,CAAC;QAEZ,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,YAAY,WAAW,aAAa,QAAQ,QAAQ,EAAE,CAAC,CAAC;QAErF,IAAI,MAAM,EAAE,CAAC;YACX,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,cAAc,GAAG,mBAAmB,CAAC,gBAAgB,CACzD,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,eAAe,CAChB,CAAC;QAEF,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBACjD,IAAI,UAAU,GAAG,KAAK,CAAC;gBACvB,IAAI,cAAc,GAAG,OAAO,CAAC;gBAE7B,0BAA0B;gBAC1B,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBACnC,cAAc,GAAG,cAAc,CAAC,UAAU,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;oBACxE,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;gBAED,2CAA2C;gBAC3C,IAAI,iBAAiB,EAAE,CAAC;oBACtB,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;oBAC7D,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;oBAE/D,IAAI,cAAc,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;wBACjD,cAAc,GAAG,cAAc,CAAC,UAAU,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,CAAC;wBACtF,UAAU,GAAG,IAAI,CAAC;oBACpB,CAAC;gBACH,CAAC;gBAED,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBACvD,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,IAAI,YAAY,KAAK,CAAC,CAAC;oBAE7E,IAAI,CAAC,MAAM,EAAE,CAAC;wBACZ,MAAM,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;oBACpD,CAAC;oBAED,aAAa,EAAE,CAAC;gBAClB,CAAC;gBAED,cAAc,EAAE,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,2CAA2C;gBAC3C,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,KAAK,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACpF,SAAS;YACX,CAAC;QACH,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,IAAI,CACZ,GAAG,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,IAAI,cAAc,WAAW,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,IAAI,aAAa,QAAQ,CACpI,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACK,MAAM,CAAC,KAAK,CAAC,qBAAqB,CACxC,QAAgB,EAChB,QAAgB,EAChB,MAAe,EACf,SAAS,GAAG,KAAK;QAEjB,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;QAE5E,OAAO,UAAU,KAAK,OAAO,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAEjD,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,IAAI,SAAS,EAAE,CAAC;oBACd,OAAO,OAAO,CAAC;gBACjB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,yCAAyC;YAC3C,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;gBAC7B,6BAA6B;gBAC7B,MAAM;YACR,CAAC;YACD,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;QAED,wCAAwC;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,gBAAgB,CAAC,QAAgB,EAAE,gBAA0B;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEzC,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;YACzC,+CAA+C;YAC/C,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC/B,OAAO,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACtC,CAAC;YAED,sCAAsC;YACtC,MAAM,aAAa,GAAG,aAAa,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YACnE,OAAO,aAAa,KAAK,SAAS,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
import { exec } from 'child_process';
|
|
2
|
-
import {
|
|
3
|
-
access,
|
|
4
|
-
appendFile,
|
|
5
|
-
cp,
|
|
6
|
-
mkdir,
|
|
7
|
-
readFile,
|
|
8
|
-
readdir,
|
|
9
|
-
rm,
|
|
10
|
-
stat,
|
|
11
|
-
writeFile
|
|
12
|
-
} from 'fs/promises';
|
|
2
|
+
import { access, appendFile, cp, mkdir, readFile, readdir, rm, stat, writeFile } from 'fs/promises';
|
|
13
3
|
import path from 'path';
|
|
14
4
|
import { promisify } from 'util';
|
|
15
5
|
import ErrorUtils from '../../utils/ErrorUtils.js';
|
|
16
6
|
import { DR } from '../DependencyRegistry.js';
|
|
17
7
|
import StringService from '../StringService.js';
|
|
8
|
+
import GlobMatchingService from './GlobMatchingService.js';
|
|
18
9
|
|
|
19
10
|
const execAsync = promisify(exec);
|
|
20
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Options for the replaceInFiles method
|
|
14
|
+
*/
|
|
15
|
+
export type ReplaceInFilesOptions = {
|
|
16
|
+
/** The string to search for */
|
|
17
|
+
searchString: string;
|
|
18
|
+
/** The string to replace it with */
|
|
19
|
+
replaceString: string;
|
|
20
|
+
/** The root directory to search in */
|
|
21
|
+
rootPath: string;
|
|
22
|
+
/** Array of glob-like patterns to include (defaults to all files) */
|
|
23
|
+
includePatterns?: string[];
|
|
24
|
+
/** Array of glob-like patterns to exclude (defaults to common ignore patterns) */
|
|
25
|
+
excludePatterns?: string[];
|
|
26
|
+
/** Whether to also replace URL-encoded versions of the strings */
|
|
27
|
+
includeUrlEncoded?: boolean;
|
|
28
|
+
/** If true, only shows what would be changed without making changes */
|
|
29
|
+
dryRun?: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
21
32
|
/**
|
|
22
33
|
* A service which can be used to interact with the file system, only in build
|
|
23
34
|
* steps.
|
|
@@ -30,8 +41,8 @@ export default class FileSystemService {
|
|
|
30
41
|
*
|
|
31
42
|
* @param folderPath the path to the folder which contains the file that should
|
|
32
43
|
* be updated
|
|
33
|
-
* @param fileName
|
|
34
|
-
* @param textToInsert
|
|
44
|
+
* @param fileName the name of the file to update
|
|
45
|
+
* @param textToInsert the text to insert into the file
|
|
35
46
|
*/
|
|
36
47
|
static async findAndInsertText(
|
|
37
48
|
folderPath: string,
|
|
@@ -62,8 +73,8 @@ export default class FileSystemService {
|
|
|
62
73
|
/**
|
|
63
74
|
* Copies the contents of one folder to another folder.
|
|
64
75
|
*
|
|
65
|
-
* @param sourceFolderPath
|
|
66
|
-
* @param targetFolderPath
|
|
76
|
+
* @param sourceFolderPath the path to the source folder
|
|
77
|
+
* @param targetFolderPath the path to the target folder
|
|
67
78
|
* @param ignoreExtensions is an array with extensions that should be
|
|
68
79
|
* ignored. For example, if you want to ignore all .ts files, you would pass
|
|
69
80
|
* in ['.ts']. Multi-part extensions like '.spec.ts' are also supported.
|
|
@@ -83,8 +94,7 @@ export default class FileSystemService {
|
|
|
83
94
|
await FileSystemService.checkOrCreateFolder(targetFolderPath);
|
|
84
95
|
|
|
85
96
|
// Get the files in the source directory
|
|
86
|
-
const sourceFilePaths =
|
|
87
|
-
await FileSystemService.getAllFilePathsRelative(sourceFolderPath);
|
|
97
|
+
const sourceFilePaths = await FileSystemService.getAllFilePathsRelative(sourceFolderPath);
|
|
88
98
|
|
|
89
99
|
await Promise.all(
|
|
90
100
|
sourceFilePaths.map(async (sourceFilePath) => {
|
|
@@ -92,10 +102,7 @@ export default class FileSystemService {
|
|
|
92
102
|
const targetFile = path.join(targetFolderPath, sourceFilePath);
|
|
93
103
|
|
|
94
104
|
// Check if the file should be ignored based on extensions
|
|
95
|
-
if (
|
|
96
|
-
ignoreExtensions &&
|
|
97
|
-
FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)
|
|
98
|
-
) {
|
|
105
|
+
if (ignoreExtensions && FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)) {
|
|
99
106
|
return;
|
|
100
107
|
}
|
|
101
108
|
|
|
@@ -104,38 +111,11 @@ export default class FileSystemService {
|
|
|
104
111
|
);
|
|
105
112
|
}
|
|
106
113
|
|
|
107
|
-
/**
|
|
108
|
-
* Checks if a file should be ignored based on the provided extensions.
|
|
109
|
-
* Supports both simple extensions (e.g., '.ts') and multi-part extensions (e.g., '.spec.ts').
|
|
110
|
-
*
|
|
111
|
-
* @param filePath the path to the file to check
|
|
112
|
-
* @param ignoreExtensions array of extensions to ignore
|
|
113
|
-
*/
|
|
114
|
-
private static shouldIgnoreFile(
|
|
115
|
-
filePath: string,
|
|
116
|
-
ignoreExtensions: string[]
|
|
117
|
-
): boolean {
|
|
118
|
-
const fileName = path.basename(filePath);
|
|
119
|
-
|
|
120
|
-
return ignoreExtensions.some((extension) => {
|
|
121
|
-
// Handle multi-part extensions like '.spec.ts'
|
|
122
|
-
if (extension.includes('.', 1)) {
|
|
123
|
-
return fileName.endsWith(extension);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Handle simple extensions like '.ts'
|
|
127
|
-
const fileExtension = StringService.getFileNameExtension(filePath);
|
|
128
|
-
return fileExtension === extension;
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
114
|
static async checkOrCreateFolder(folderPath: string): Promise<void> {
|
|
133
115
|
try {
|
|
134
116
|
await access(folderPath);
|
|
135
117
|
} catch {
|
|
136
|
-
DR.logger.verbose.info(
|
|
137
|
-
`Directory "${folderPath}" does not exist. Creating it now...`
|
|
138
|
-
);
|
|
118
|
+
DR.logger.verbose.info(`Directory "${folderPath}" does not exist. Creating it now...`);
|
|
139
119
|
await mkdir(folderPath, { recursive: true });
|
|
140
120
|
}
|
|
141
121
|
}
|
|
@@ -191,7 +171,11 @@ export default class FileSystemService {
|
|
|
191
171
|
static async getAllFilePathsRelative(dirPath: string): Promise<string[]> {
|
|
192
172
|
const filePaths = await this.getAllFilePaths(dirPath);
|
|
193
173
|
return filePaths.map((filePath) => {
|
|
194
|
-
|
|
174
|
+
const relativePath = filePath.replace(dirPath, '');
|
|
175
|
+
// Remove leading path separator if present
|
|
176
|
+
return relativePath.startsWith('/') || relativePath.startsWith('\\')
|
|
177
|
+
? relativePath.slice(1)
|
|
178
|
+
: relativePath;
|
|
195
179
|
});
|
|
196
180
|
}
|
|
197
181
|
|
|
@@ -206,9 +190,7 @@ export default class FileSystemService {
|
|
|
206
190
|
const { stdout } = await execAsync('git status --porcelain');
|
|
207
191
|
return stdout.trim().length > 0;
|
|
208
192
|
} catch (error) {
|
|
209
|
-
DR.logger.error(
|
|
210
|
-
`Failed to check for pending changes: ${ErrorUtils.getErrorString(error)}`
|
|
211
|
-
);
|
|
193
|
+
DR.logger.error(`Failed to check for pending changes: ${ErrorUtils.getErrorString(error)}`);
|
|
212
194
|
return false;
|
|
213
195
|
}
|
|
214
196
|
}
|
|
@@ -259,6 +241,87 @@ export default class FileSystemService {
|
|
|
259
241
|
);
|
|
260
242
|
}
|
|
261
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Replaces all occurrences of a string in files within a directory.
|
|
246
|
+
* Supports glob patterns for including/excluding files and handles URL encoding.
|
|
247
|
+
*
|
|
248
|
+
* @param options Configuration object for the replacement operation
|
|
249
|
+
*/
|
|
250
|
+
static async replaceInFiles(options: ReplaceInFilesOptions): Promise<void> {
|
|
251
|
+
const {
|
|
252
|
+
searchString,
|
|
253
|
+
replaceString,
|
|
254
|
+
rootPath,
|
|
255
|
+
includePatterns = ['**/*'],
|
|
256
|
+
excludePatterns = ['**/node_modules/**', '**/.*/**'],
|
|
257
|
+
includeUrlEncoded = true,
|
|
258
|
+
dryRun = false
|
|
259
|
+
} = options;
|
|
260
|
+
|
|
261
|
+
DR.logger.info(`Replacing "${searchString}" with "${replaceString}" in ${rootPath}`);
|
|
262
|
+
|
|
263
|
+
if (dryRun) {
|
|
264
|
+
DR.logger.info('DRY RUN MODE - No files will be modified');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const allFiles = await this.getAllFilePaths(rootPath);
|
|
268
|
+
const filesToProcess = GlobMatchingService.getMatchingFiles(
|
|
269
|
+
allFiles,
|
|
270
|
+
rootPath,
|
|
271
|
+
includePatterns,
|
|
272
|
+
excludePatterns
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
let processedCount = 0;
|
|
276
|
+
let modifiedCount = 0;
|
|
277
|
+
|
|
278
|
+
for (const filePath of filesToProcess) {
|
|
279
|
+
try {
|
|
280
|
+
const content = await readFile(filePath, 'utf8');
|
|
281
|
+
let hasChanges = false;
|
|
282
|
+
let updatedContent = content;
|
|
283
|
+
|
|
284
|
+
// Replace the main string
|
|
285
|
+
if (content.includes(searchString)) {
|
|
286
|
+
updatedContent = updatedContent.replaceAll(searchString, replaceString);
|
|
287
|
+
hasChanges = true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Replace URL-encoded version if requested
|
|
291
|
+
if (includeUrlEncoded) {
|
|
292
|
+
const encodedSearchString = encodeURIComponent(searchString);
|
|
293
|
+
const encodedReplaceString = encodeURIComponent(replaceString);
|
|
294
|
+
|
|
295
|
+
if (updatedContent.includes(encodedSearchString)) {
|
|
296
|
+
updatedContent = updatedContent.replaceAll(encodedSearchString, encodedReplaceString);
|
|
297
|
+
hasChanges = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (hasChanges) {
|
|
302
|
+
const relativePath = path.relative(rootPath, filePath);
|
|
303
|
+
DR.logger.info(`${dryRun ? 'Would update' : 'Updating'} ${relativePath}...`);
|
|
304
|
+
|
|
305
|
+
if (!dryRun) {
|
|
306
|
+
await writeFile(filePath, updatedContent, 'utf8');
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
modifiedCount++;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
processedCount++;
|
|
313
|
+
} catch (error) {
|
|
314
|
+
// Skip binary files or files we can't read
|
|
315
|
+
DR.logger.verbose.info(`Skipping ${filePath}: ${ErrorUtils.getErrorString(error)}`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
DR.logger.info(
|
|
321
|
+
`${dryRun ? 'Would process' : 'Processed'} ${processedCount} files, ${dryRun ? 'would modify' : 'modified'} ${modifiedCount} files`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
262
325
|
/**
|
|
263
326
|
* Internal helper method that traverses up the directory tree looking for files.
|
|
264
327
|
*
|
|
@@ -309,4 +372,26 @@ export default class FileSystemService {
|
|
|
309
372
|
|
|
310
373
|
return results;
|
|
311
374
|
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Checks if a file should be ignored based on the provided extensions.
|
|
378
|
+
* Supports both simple extensions (e.g., '.ts') and multi-part extensions (e.g., '.spec.ts').
|
|
379
|
+
*
|
|
380
|
+
* @param filePath the path to the file to check
|
|
381
|
+
* @param ignoreExtensions array of extensions to ignore
|
|
382
|
+
*/
|
|
383
|
+
private static shouldIgnoreFile(filePath: string, ignoreExtensions: string[]): boolean {
|
|
384
|
+
const fileName = path.basename(filePath);
|
|
385
|
+
|
|
386
|
+
return ignoreExtensions.some((extension) => {
|
|
387
|
+
// Handle multi-part extensions like '.spec.ts'
|
|
388
|
+
if (extension.includes('.', 1)) {
|
|
389
|
+
return fileName.endsWith(extension);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Handle simple extensions like '.ts'
|
|
393
|
+
const fileExtension = StringService.getFileNameExtension(filePath);
|
|
394
|
+
return fileExtension === extension;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
312
397
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A service for handling glob-like pattern matching operations.
|
|
3
|
+
* Supports common glob patterns like **, *, and exact matches.
|
|
4
|
+
*
|
|
5
|
+
* Inspired by the isaacs/node-glob library (ISC License)
|
|
6
|
+
* but simplified for basic use cases.
|
|
7
|
+
*/
|
|
8
|
+
export default class GlobMatchingService {
|
|
9
|
+
/**
|
|
10
|
+
* Gets files matching the include patterns while excluding those that match exclude patterns.
|
|
11
|
+
* Uses simple glob-like matching for common patterns.
|
|
12
|
+
*
|
|
13
|
+
* @param allFiles Array of all file paths to filter
|
|
14
|
+
* @param rootPath The root directory path for computing relative paths
|
|
15
|
+
* @param includePatterns Array of glob-like patterns to include
|
|
16
|
+
* @param excludePatterns Array of glob-like patterns to exclude
|
|
17
|
+
*/
|
|
18
|
+
static getMatchingFiles(allFiles: string[], rootPath: string, includePatterns: string[], excludePatterns: string[]): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Simple glob-like pattern matching for common use cases.
|
|
21
|
+
* Supports:
|
|
22
|
+
* - ** for any number of directories (globstar)
|
|
23
|
+
* - * for any characters except path separators
|
|
24
|
+
* - Exact matches
|
|
25
|
+
*
|
|
26
|
+
* @param filePath The file path to test
|
|
27
|
+
* @param pattern The pattern to match against
|
|
28
|
+
*/
|
|
29
|
+
static matchesPattern(filePath: string, pattern: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Match path segments against pattern segments with support for globstar (**).
|
|
32
|
+
*
|
|
33
|
+
* The idea is that each segment doesn't cross path separators. It should
|
|
34
|
+
* be split by '/' and then matched segment by segment.
|
|
35
|
+
*
|
|
36
|
+
* @param pathSegments Array of path segments
|
|
37
|
+
* @param patternSegments Array of pattern segments
|
|
38
|
+
*/
|
|
39
|
+
private static matchSegments;
|
|
40
|
+
/**
|
|
41
|
+
* Match a single segment with support for * wildcard
|
|
42
|
+
*
|
|
43
|
+
* @param pathSegment Single path segment
|
|
44
|
+
* @param patternSegment Single pattern segment
|
|
45
|
+
*/
|
|
46
|
+
private static matchSingleSegment;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=GlobMatchingService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobMatchingService.d.ts","sourceRoot":"","sources":["../../../src/services/FileSystemService/GlobMatchingService.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IACtC;;;;;;;;OAQG;IACH,MAAM,CAAC,gBAAgB,CACrB,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EAAE,EACzB,eAAe,EAAE,MAAM,EAAE,GACxB,MAAM,EAAE;IAcX;;;;;;;;;OASG;IACH,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAiBjE;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAuD5B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;CAiBlC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
/**
|
|
3
|
+
* A service for handling glob-like pattern matching operations.
|
|
4
|
+
* Supports common glob patterns like **, *, and exact matches.
|
|
5
|
+
*
|
|
6
|
+
* Inspired by the isaacs/node-glob library (ISC License)
|
|
7
|
+
* but simplified for basic use cases.
|
|
8
|
+
*/
|
|
9
|
+
export default class GlobMatchingService {
|
|
10
|
+
/**
|
|
11
|
+
* Gets files matching the include patterns while excluding those that match exclude patterns.
|
|
12
|
+
* Uses simple glob-like matching for common patterns.
|
|
13
|
+
*
|
|
14
|
+
* @param allFiles Array of all file paths to filter
|
|
15
|
+
* @param rootPath The root directory path for computing relative paths
|
|
16
|
+
* @param includePatterns Array of glob-like patterns to include
|
|
17
|
+
* @param excludePatterns Array of glob-like patterns to exclude
|
|
18
|
+
*/
|
|
19
|
+
static getMatchingFiles(allFiles, rootPath, includePatterns, excludePatterns) {
|
|
20
|
+
return allFiles.filter((filePath) => {
|
|
21
|
+
const relativePath = path.relative(rootPath, filePath);
|
|
22
|
+
// Check if file matches any exclude pattern
|
|
23
|
+
if (excludePatterns.some((pattern) => this.matchesPattern(relativePath, pattern))) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
// Check if file matches any include pattern
|
|
27
|
+
return includePatterns.some((pattern) => this.matchesPattern(relativePath, pattern));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Simple glob-like pattern matching for common use cases.
|
|
32
|
+
* Supports:
|
|
33
|
+
* - ** for any number of directories (globstar)
|
|
34
|
+
* - * for any characters except path separators
|
|
35
|
+
* - Exact matches
|
|
36
|
+
*
|
|
37
|
+
* @param filePath The file path to test
|
|
38
|
+
* @param pattern The pattern to match against
|
|
39
|
+
*/
|
|
40
|
+
static matchesPattern(filePath, pattern) {
|
|
41
|
+
// Normalize path separators to forward slashes
|
|
42
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
43
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
44
|
+
// Handle special case of **/* which should match everything
|
|
45
|
+
if (normalizedPattern === '**/*') {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
// Split into segments for more precise matching
|
|
49
|
+
const pathSegments = normalizedPath.split('/');
|
|
50
|
+
const patternSegments = normalizedPattern.split('/');
|
|
51
|
+
return this.matchSegments(pathSegments, patternSegments);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Match path segments against pattern segments with support for globstar (**).
|
|
55
|
+
*
|
|
56
|
+
* The idea is that each segment doesn't cross path separators. It should
|
|
57
|
+
* be split by '/' and then matched segment by segment.
|
|
58
|
+
*
|
|
59
|
+
* @param pathSegments Array of path segments
|
|
60
|
+
* @param patternSegments Array of pattern segments
|
|
61
|
+
*/
|
|
62
|
+
static matchSegments(pathSegments, patternSegments) {
|
|
63
|
+
let pathIndex = 0;
|
|
64
|
+
let patternIndex = 0;
|
|
65
|
+
while (pathIndex < pathSegments.length && patternIndex < patternSegments.length) {
|
|
66
|
+
const pathSegment = pathSegments[pathIndex];
|
|
67
|
+
const patternSegment = patternSegments[patternIndex];
|
|
68
|
+
if (patternSegment === '**') {
|
|
69
|
+
// Handle globstar - it can match zero or more segments
|
|
70
|
+
patternIndex++;
|
|
71
|
+
// If ** is the last segment, it matches everything remaining
|
|
72
|
+
if (patternIndex >= patternSegments.length) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
// Try to match the rest of the pattern against remaining path segments
|
|
76
|
+
const remainingPattern = patternSegments.slice(patternIndex);
|
|
77
|
+
// Try matching from current position onwards
|
|
78
|
+
for (let i = pathIndex; i <= pathSegments.length; i++) {
|
|
79
|
+
const remainingPath = pathSegments.slice(i);
|
|
80
|
+
if (this.matchSegments(remainingPath, remainingPattern)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
else if (this.matchSingleSegment(pathSegment, patternSegment)) {
|
|
87
|
+
// Regular segment match
|
|
88
|
+
pathIndex++;
|
|
89
|
+
patternIndex++;
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Check if we've consumed both path and pattern completely
|
|
96
|
+
// or if remaining pattern segments are only globstars
|
|
97
|
+
const remainingPattern = patternSegments.slice(patternIndex);
|
|
98
|
+
const pathConsumed = pathIndex >= pathSegments.length;
|
|
99
|
+
const patternConsumed = patternIndex >= patternSegments.length;
|
|
100
|
+
if (pathConsumed && patternConsumed) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
if (pathConsumed && remainingPattern.every((seg) => seg === '**')) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Match a single segment with support for * wildcard
|
|
110
|
+
*
|
|
111
|
+
* @param pathSegment Single path segment
|
|
112
|
+
* @param patternSegment Single pattern segment
|
|
113
|
+
*/
|
|
114
|
+
static matchSingleSegment(pathSegment, patternSegment) {
|
|
115
|
+
if (patternSegment === '*') {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (patternSegment === pathSegment) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
// Convert pattern to regex for more complex matching
|
|
122
|
+
const regexPattern = patternSegment
|
|
123
|
+
.replace(/\./g, '\\.') // Escape dots
|
|
124
|
+
.replace(/\*/g, '[^/]*'); // * matches anything except slashes
|
|
125
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
126
|
+
return regex.test(pathSegment);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=GlobMatchingService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobMatchingService.js","sourceRoot":"","sources":["../../../src/services/FileSystemService/GlobMatchingService.ts"],"names":[],"mappings":"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"}
|