@aneuhold/core-ts-lib 2.2.1 → 2.2.3

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) [2024] [Anton G Neuhold Jr]
3
+ Copyright (c) [2025] [Anton G Neuhold Jr]
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -21,9 +21,17 @@ export default class FileSystemService {
21
21
  * @param targetFolderPath
22
22
  * @param ignoreExtensions is an array with extensions that should be
23
23
  * ignored. For example, if you want to ignore all .ts files, you would pass
24
- * in ['ts'].
24
+ * in ['.ts']. Multi-part extensions like '.spec.ts' are also supported.
25
25
  */
26
26
  static copyFolderContents(sourceFolderPath: string, targetFolderPath: string, ignoreExtensions?: string[]): Promise<void>;
27
+ /**
28
+ * Checks if a file should be ignored based on the provided extensions.
29
+ * Supports both simple extensions (e.g., '.ts') and multi-part extensions (e.g., '.spec.ts').
30
+ *
31
+ * @param filePath the path to the file to check
32
+ * @param ignoreExtensions array of extensions to ignore
33
+ */
34
+ private static shouldIgnoreFile;
27
35
  static checkOrCreateFolder(folderPath: string): Promise<void>;
28
36
  static deleteFolder(folderPath: string): Promise<void>;
29
37
  /**
@@ -33,7 +41,7 @@ export default class FileSystemService {
33
41
  *
34
42
  * If only relative file paths are needed, use {@link getAllFilePathsRelative}.
35
43
  *
36
- * @param dirPath
44
+ * @param dirPath the directory path to search for files in
37
45
  */
38
46
  static getAllFilePaths(dirPath: string): Promise<string[]>;
39
47
  /**
@@ -43,7 +51,7 @@ export default class FileSystemService {
43
51
  *
44
52
  * If absolute file paths are needed, use {@link getAllFilePaths}.
45
53
  *
46
- * @param dirPath
54
+ * @param dirPath the directory path to search for files in
47
55
  */
48
56
  static getAllFilePathsRelative(dirPath: string): Promise<string[]>;
49
57
  /**
@@ -64,5 +72,24 @@ export default class FileSystemService {
64
72
  * @param stopAt - Optional directory path to stop searching at (defaults to root)
65
73
  */
66
74
  static findFileUpTree(startDir: string, fileName: string, stopAt?: string): Promise<string | null>;
75
+ /**
76
+ * Searches for all files with the given name by traversing up the directory tree
77
+ * starting from the specified directory. Returns all found files from closest
78
+ * to furthest (root).
79
+ *
80
+ * @param startDir - The directory to start searching from
81
+ * @param fileName - The name of the file to search for
82
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
83
+ */
84
+ static findAllFilesUpTree(startDir: string, fileName: string, stopAt?: string): Promise<string[]>;
85
+ /**
86
+ * Internal helper method that traverses up the directory tree looking for files.
87
+ *
88
+ * @param startDir - The directory to start searching from
89
+ * @param fileName - The name of the file to search for
90
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
91
+ * @param findFirst - If true, stops after finding the first file
92
+ */
93
+ private static traverseDirectoryTree;
67
94
  }
68
95
  //# sourceMappingURL=FileSystemService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemService.d.ts","sourceRoot":"","sources":["../../../src/services/FileSystemService/FileSystemService.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;;OASG;WACU,iBAAiB,CAC5B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;IAsBhB;;;;;;;;OAQG;WACU,kBAAkB,CAC7B,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC;WAmCH,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAWtD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D;;;;;;;;OAQG;WACU,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoBhE;;;;;;;;OAQG;WACU,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOxE;;;;;OAKG;WACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAYlD;;;;;;;;;OASG;WACU,cAAc,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAgC1B"}
1
+ {"version":3,"file":"FileSystemService.d.ts","sourceRoot":"","sources":["../../../src/services/FileSystemService/FileSystemService.ts"],"names":[],"mappings":"AAoBA;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC;;;;;;;;;OASG;WACU,iBAAiB,CAC5B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;IAsBhB;;;;;;;;OAQG;WACU,kBAAkB,CAC7B,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC;IAgChB;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAkBlB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAWtD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D;;;;;;;;OAQG;WACU,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoBhE;;;;;;;;OAQG;WACU,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOxE;;;;;OAKG;WACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAYlD;;;;;;;;;OASG;WACU,cAAc,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUzB;;;;;;;;OAQG;WACU,kBAAkB,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC;IASpB;;;;;;;OAOG;mBACkB,qBAAqB;CA0C3C"}
@@ -47,7 +47,7 @@ export default class FileSystemService {
47
47
  * @param targetFolderPath
48
48
  * @param ignoreExtensions is an array with extensions that should be
49
49
  * ignored. For example, if you want to ignore all .ts files, you would pass
50
- * in ['ts'].
50
+ * in ['.ts']. Multi-part extensions like '.spec.ts' are also supported.
51
51
  */
52
52
  static async copyFolderContents(sourceFolderPath, targetFolderPath, ignoreExtensions) {
53
53
  // Check if the source directory exists first
@@ -61,18 +61,36 @@ export default class FileSystemService {
61
61
  await FileSystemService.checkOrCreateFolder(targetFolderPath);
62
62
  // Get the files in the source directory
63
63
  const sourceFilePaths = await FileSystemService.getAllFilePathsRelative(sourceFolderPath);
64
- // console.log(sourceFilePaths);
65
64
  await Promise.all(sourceFilePaths.map(async (sourceFilePath) => {
66
65
  const sourceFile = path.join(sourceFolderPath, sourceFilePath);
67
66
  const targetFile = path.join(targetFolderPath, sourceFilePath);
68
- const sourceFileExtension = StringService.getFileNameExtension(sourceFile);
69
- if (sourceFileExtension &&
70
- ignoreExtensions?.includes(sourceFileExtension)) {
67
+ // Check if the file should be ignored based on extensions
68
+ if (ignoreExtensions &&
69
+ FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)) {
71
70
  return;
72
71
  }
73
72
  await cp(sourceFile, targetFile, { recursive: true });
74
73
  }));
75
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
+ }
76
94
  static async checkOrCreateFolder(folderPath) {
77
95
  try {
78
96
  await access(folderPath);
@@ -99,7 +117,7 @@ export default class FileSystemService {
99
117
  *
100
118
  * If only relative file paths are needed, use {@link getAllFilePathsRelative}.
101
119
  *
102
- * @param dirPath
120
+ * @param dirPath the directory path to search for files in
103
121
  */
104
122
  static async getAllFilePaths(dirPath) {
105
123
  const filePaths = [];
@@ -123,7 +141,7 @@ export default class FileSystemService {
123
141
  *
124
142
  * If absolute file paths are needed, use {@link getAllFilePaths}.
125
143
  *
126
- * @param dirPath
144
+ * @param dirPath the directory path to search for files in
127
145
  */
128
146
  static async getAllFilePathsRelative(dirPath) {
129
147
  const filePaths = await this.getAllFilePaths(dirPath);
@@ -158,13 +176,43 @@ export default class FileSystemService {
158
176
  * @param stopAt - Optional directory path to stop searching at (defaults to root)
159
177
  */
160
178
  static async findFileUpTree(startDir, fileName, stopAt) {
179
+ const results = await this.traverseDirectoryTree(startDir, fileName, stopAt, true // findFirst = true
180
+ );
181
+ return results.length > 0 ? results[0] : null;
182
+ }
183
+ /**
184
+ * Searches for all files with the given name by traversing up the directory tree
185
+ * starting from the specified directory. Returns all found files from closest
186
+ * to furthest (root).
187
+ *
188
+ * @param startDir - The directory to start searching from
189
+ * @param fileName - The name of the file to search for
190
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
191
+ */
192
+ static async findAllFilesUpTree(startDir, fileName, stopAt) {
193
+ return this.traverseDirectoryTree(startDir, fileName, stopAt, false // findFirst = false
194
+ );
195
+ }
196
+ /**
197
+ * Internal helper method that traverses up the directory tree looking for files.
198
+ *
199
+ * @param startDir - The directory to start searching from
200
+ * @param fileName - The name of the file to search for
201
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
202
+ * @param findFirst - If true, stops after finding the first file
203
+ */
204
+ static async traverseDirectoryTree(startDir, fileName, stopAt, findFirst = false) {
205
+ const results = [];
161
206
  let currentDir = path.resolve(startDir);
162
207
  const rootDir = stopAt ? path.resolve(stopAt) : path.parse(currentDir).root;
163
208
  while (currentDir !== rootDir) {
164
209
  const filePath = path.join(currentDir, fileName);
165
210
  try {
166
211
  await access(filePath);
167
- return filePath;
212
+ results.push(filePath);
213
+ if (findFirst) {
214
+ return results;
215
+ }
168
216
  }
169
217
  catch {
170
218
  // File doesn't exist, continue searching
@@ -180,12 +228,12 @@ export default class FileSystemService {
180
228
  const filePath = path.join(currentDir, fileName);
181
229
  try {
182
230
  await access(filePath);
183
- return filePath;
231
+ results.push(filePath);
184
232
  }
185
233
  catch {
186
234
  // File not found
187
- return null;
188
235
  }
236
+ return results;
189
237
  }
190
238
  }
191
239
  //# sourceMappingURL=FileSystemService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemService.js","sourceRoot":"","sources":["../../../src/services/FileSystemService/FileSystemService.ts"],"names":[],"mappings":"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"}
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,EACL,MAAM,EACN,UAAU,EACV,EAAE,EACF,KAAK,EACL,QAAQ,EACR,OAAO,EACP,EAAE,EACF,IAAI,EACJ,SAAS,EACV,MAAM,aAAa,CAAC;AACrB,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;AAEhD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;;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,GACnB,MAAM,iBAAiB,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;QAEpE,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,IACE,gBAAgB;gBAChB,iBAAiB,CAAC,gBAAgB,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAChE,CAAC;gBACD,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;;;;;;OAMG;IACK,MAAM,CAAC,gBAAgB,CAC7B,QAAgB,EAChB,gBAA0B;QAE1B,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;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,CACpB,cAAc,UAAU,sCAAsC,CAC/D,CAAC;YACF,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,OAAO,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACvC,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,CACb,wCAAwC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAC3E,CAAC;YACF,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;;;;;;;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;CACF"}
@@ -66,7 +66,7 @@ export default class FileSystemService {
66
66
  * @param targetFolderPath
67
67
  * @param ignoreExtensions is an array with extensions that should be
68
68
  * ignored. For example, if you want to ignore all .ts files, you would pass
69
- * in ['ts'].
69
+ * in ['.ts']. Multi-part extensions like '.spec.ts' are also supported.
70
70
  */
71
71
  static async copyFolderContents(
72
72
  sourceFolderPath: string,
@@ -86,18 +86,15 @@ export default class FileSystemService {
86
86
  const sourceFilePaths =
87
87
  await FileSystemService.getAllFilePathsRelative(sourceFolderPath);
88
88
 
89
- // console.log(sourceFilePaths);
90
-
91
89
  await Promise.all(
92
90
  sourceFilePaths.map(async (sourceFilePath) => {
93
91
  const sourceFile = path.join(sourceFolderPath, sourceFilePath);
94
92
  const targetFile = path.join(targetFolderPath, sourceFilePath);
95
93
 
96
- const sourceFileExtension =
97
- StringService.getFileNameExtension(sourceFile);
94
+ // Check if the file should be ignored based on extensions
98
95
  if (
99
- sourceFileExtension &&
100
- ignoreExtensions?.includes(sourceFileExtension)
96
+ ignoreExtensions &&
97
+ FileSystemService.shouldIgnoreFile(sourceFile, ignoreExtensions)
101
98
  ) {
102
99
  return;
103
100
  }
@@ -107,6 +104,31 @@ export default class FileSystemService {
107
104
  );
108
105
  }
109
106
 
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
+
110
132
  static async checkOrCreateFolder(folderPath: string): Promise<void> {
111
133
  try {
112
134
  await access(folderPath);
@@ -135,7 +157,7 @@ export default class FileSystemService {
135
157
  *
136
158
  * If only relative file paths are needed, use {@link getAllFilePathsRelative}.
137
159
  *
138
- * @param dirPath
160
+ * @param dirPath the directory path to search for files in
139
161
  */
140
162
  static async getAllFilePaths(dirPath: string): Promise<string[]> {
141
163
  const filePaths: string[] = [];
@@ -164,7 +186,7 @@ export default class FileSystemService {
164
186
  *
165
187
  * If absolute file paths are needed, use {@link getAllFilePaths}.
166
188
  *
167
- * @param dirPath
189
+ * @param dirPath the directory path to search for files in
168
190
  */
169
191
  static async getAllFilePathsRelative(dirPath: string): Promise<string[]> {
170
192
  const filePaths = await this.getAllFilePaths(dirPath);
@@ -206,6 +228,52 @@ export default class FileSystemService {
206
228
  fileName: string,
207
229
  stopAt?: string
208
230
  ): Promise<string | null> {
231
+ const results = await this.traverseDirectoryTree(
232
+ startDir,
233
+ fileName,
234
+ stopAt,
235
+ true // findFirst = true
236
+ );
237
+ return results.length > 0 ? results[0] : null;
238
+ }
239
+
240
+ /**
241
+ * Searches for all files with the given name by traversing up the directory tree
242
+ * starting from the specified directory. Returns all found files from closest
243
+ * to furthest (root).
244
+ *
245
+ * @param startDir - The directory to start searching from
246
+ * @param fileName - The name of the file to search for
247
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
248
+ */
249
+ static async findAllFilesUpTree(
250
+ startDir: string,
251
+ fileName: string,
252
+ stopAt?: string
253
+ ): Promise<string[]> {
254
+ return this.traverseDirectoryTree(
255
+ startDir,
256
+ fileName,
257
+ stopAt,
258
+ false // findFirst = false
259
+ );
260
+ }
261
+
262
+ /**
263
+ * Internal helper method that traverses up the directory tree looking for files.
264
+ *
265
+ * @param startDir - The directory to start searching from
266
+ * @param fileName - The name of the file to search for
267
+ * @param stopAt - Optional directory path to stop searching at (defaults to root)
268
+ * @param findFirst - If true, stops after finding the first file
269
+ */
270
+ private static async traverseDirectoryTree(
271
+ startDir: string,
272
+ fileName: string,
273
+ stopAt?: string,
274
+ findFirst = false
275
+ ): Promise<string[]> {
276
+ const results: string[] = [];
209
277
  let currentDir = path.resolve(startDir);
210
278
  const rootDir = stopAt ? path.resolve(stopAt) : path.parse(currentDir).root;
211
279
 
@@ -214,7 +282,10 @@ export default class FileSystemService {
214
282
 
215
283
  try {
216
284
  await access(filePath);
217
- return filePath;
285
+ results.push(filePath);
286
+ if (findFirst) {
287
+ return results;
288
+ }
218
289
  } catch {
219
290
  // File doesn't exist, continue searching
220
291
  }
@@ -231,10 +302,11 @@ export default class FileSystemService {
231
302
  const filePath = path.join(currentDir, fileName);
232
303
  try {
233
304
  await access(filePath);
234
- return filePath;
305
+ results.push(filePath);
235
306
  } catch {
236
307
  // File not found
237
- return null;
238
308
  }
309
+
310
+ return results;
239
311
  }
240
312
  }
package/package.json CHANGED
@@ -2,14 +2,14 @@
2
2
  "name": "@aneuhold/core-ts-lib",
3
3
  "author": "Anton G. Neuhold Jr.",
4
4
  "license": "MIT",
5
- "version": "2.2.1",
5
+ "version": "2.2.3",
6
6
  "description": "A core library for all of my TypeScript projects",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "build": "rimraf lib && tsc --project tsconfig.build.json && tsx ./scripts/copyTsFiles.ts",
10
10
  "watch": "nodemon --ignore lib/ -e ts --exec \"tsc --project tsconfig.build.json && tsx ./scripts/copyTsFiles.ts\"",
11
11
  "lint": "eslint",
12
- "test": "jest",
12
+ "test": "vitest run",
13
13
  "jsr:validate": "tsx ./scripts/validateJsrPublish.ts",
14
14
  "npm:validate": "tsx ./scripts/validateNpmPublish.ts",
15
15
  "checkAll": "pnpm build && pnpm lint && pnpm test && pnpm jsr:validate",
@@ -41,16 +41,14 @@
41
41
  "Node.js"
42
42
  ],
43
43
  "devDependencies": {
44
- "@types/jest": "^29.5.14",
45
44
  "@types/node": "^22.15.3",
46
45
  "eslint": "^9.26.0",
47
- "jest": "^29.7.*",
48
46
  "jsr": "*",
49
47
  "nodemon": "^3.1.10",
50
48
  "prettier": "^3.5.3",
51
49
  "rimraf": "^6.0.1",
52
- "ts-jest": "^29.3.2",
53
50
  "tsx": "^4.19.4",
54
- "typescript": "~5.8.3"
51
+ "typescript": "~5.8.3",
52
+ "vitest": "^3.2.3"
55
53
  }
56
54
  }
@@ -1,98 +0,0 @@
1
- import DateService from './DateService.js';
2
-
3
- describe('DateService', () => {
4
- describe('addWeeks', () => {
5
- it('should successfully add weeks to a date', () => {
6
- const result = DateService.addWeeks(new Date(2024, 0, 1), 1);
7
- expect(result).toEqual(new Date(2024, 0, 8));
8
- });
9
-
10
- it('should successfully add weeks to a date that crosses months', () => {
11
- const result = DateService.addWeeks(new Date(2024, 0, 23), 2);
12
- expect(result).toEqual(new Date(2024, 1, 6));
13
- });
14
-
15
- it('should successfully add weeks to a date that crosses years', () => {
16
- const result = DateService.addWeeks(new Date(2024, 11, 25), 1);
17
- expect(result).toEqual(new Date(2025, 0, 1));
18
- });
19
- });
20
-
21
- describe('getWeekOfMonth', () => {
22
- it('should successfully get the week of month for a date', () => {
23
- const result = DateService.getWeekOfMonth(new Date(2024, 0, 14));
24
- expect(result).toEqual(3);
25
-
26
- const result2 = DateService.getWeekOfMonth(new Date(2024, 0, 1));
27
- expect(result2).toEqual(1);
28
-
29
- const result3 = DateService.getWeekOfMonth(new Date(2024, 0, 31));
30
- expect(result3).toEqual(5);
31
- });
32
- });
33
-
34
- describe('getWeekDayOfXWeekOfMonth', () => {
35
- it('should successfully get the 2nd monday of January 2024', () => {
36
- const result = DateService.getWeekDayOfXWeekOfMonth(
37
- new Date(2024, 0, 1),
38
- 1,
39
- 2
40
- );
41
- expect(result).toEqual(new Date(2024, 0, 8));
42
- });
43
-
44
- it('should successfully get the 3rd monday of January 2024', () => {
45
- const result = DateService.getWeekDayOfXWeekOfMonth(
46
- new Date(2024, 0, 1),
47
- 1,
48
- 3
49
- );
50
- expect(result).toEqual(new Date(2024, 0, 15));
51
- });
52
-
53
- it('should successfully get the 3rd tuesday of January 2024', () => {
54
- const result = DateService.getWeekDayOfXWeekOfMonth(
55
- new Date(2024, 0, 1),
56
- 2,
57
- 3
58
- );
59
- expect(result).toEqual(new Date(2024, 0, 16));
60
- });
61
-
62
- it('should successfully get the 1st Saturday of January 2024', () => {
63
- const result = DateService.getWeekDayOfXWeekOfMonth(
64
- new Date(2024, 0, 1),
65
- 6,
66
- 1
67
- );
68
- expect(result).toEqual(new Date(2024, 0, 6));
69
- });
70
-
71
- it('should successfully get the 1st sunday of January 2024', () => {
72
- const result = DateService.getWeekDayOfXWeekOfMonth(
73
- new Date(2024, 0, 1),
74
- 0,
75
- 1
76
- );
77
- expect(result).toEqual(new Date(2024, 0, 7));
78
- });
79
-
80
- it('should successfully get the last sunday of January 2024', () => {
81
- const result = DateService.getWeekDayOfXWeekOfMonth(
82
- new Date(2024, 0, 1),
83
- 0,
84
- 'last'
85
- );
86
- expect(result).toEqual(new Date(2024, 0, 28));
87
- });
88
-
89
- it('should return null if the week and day do not exist', () => {
90
- const result = DateService.getWeekDayOfXWeekOfMonth(
91
- new Date(2024, 0, 1),
92
- 0,
93
- 5
94
- );
95
- expect(result).toEqual(null);
96
- });
97
- });
98
- });
@@ -1,133 +0,0 @@
1
- import { writeFile } from 'fs/promises';
2
- import path from 'path';
3
- import FileSystemService from './FileSystemService.js';
4
-
5
- const TEST_FOLDER_NAME = '__fileSystemService-tests__';
6
-
7
- describe('FileSystemService', () => {
8
- afterAll(async () => {
9
- await deleteTestFolder();
10
- });
11
-
12
- describe('copyFolderContents', () => {
13
- it('should successfully copy all contents when target folder doesnt exist', async () => {
14
- // Make a test folder with a folder and a couple files in it
15
- const testName = 'copyFolderContents-1';
16
- const sourceFolderName = `${testName}-source`;
17
- const sourceFolderPath = await createTestFolder(sourceFolderName);
18
- await createTestFiles(sourceFolderPath, {
19
- 'file1.txt': 'test text',
20
- 'file2.txt': 'test text',
21
- subFolder: {
22
- 'subFile1.txt': 'sub test text',
23
- 'subFile2.txt': 'sub test text'
24
- }
25
- });
26
-
27
- const targetFolderPath = path.join(
28
- TEST_FOLDER_NAME,
29
- `${testName}-target`
30
- );
31
-
32
- // Execute
33
- await FileSystemService.copyFolderContents(
34
- sourceFolderPath,
35
- targetFolderPath
36
- );
37
-
38
- // Assert
39
- const expectedContents = (
40
- await FileSystemService.getAllFilePathsRelative(sourceFolderPath)
41
- ).sort();
42
- const actualContents = (
43
- await FileSystemService.getAllFilePathsRelative(targetFolderPath)
44
- ).sort();
45
- expect(actualContents).toEqual(expectedContents);
46
- });
47
-
48
- it('should successfully copy only files that arent ignored', async () => {
49
- // Make a test folder with a folder and a couple files in it
50
- const testName = 'copyFolderContents-2';
51
- const sourceFolderName = `${testName}-source`;
52
- const sourceFolderPath = await createTestFolder(sourceFolderName);
53
- await createTestFiles(sourceFolderPath, {
54
- 'file1.txt': 'test text',
55
- 'file2.txt': 'test text',
56
- subFolder: {
57
- 'subFile1.txt': 'sub test text',
58
- 'subFile2.txt': 'sub test text'
59
- },
60
- javascript: {
61
- 'file1.js': 'test text',
62
- 'file2.js': 'test text'
63
- },
64
- typescript: {
65
- 'file1.ts': 'test text',
66
- 'file2.ts': 'test text'
67
- }
68
- });
69
-
70
- const targetFolderPath = path.join(
71
- TEST_FOLDER_NAME,
72
- `${testName}-target`
73
- );
74
-
75
- // Execute
76
- await FileSystemService.copyFolderContents(
77
- sourceFolderPath,
78
- targetFolderPath,
79
- ['ts']
80
- );
81
-
82
- // Assert
83
- const expectedContents = (
84
- await FileSystemService.getAllFilePathsRelative(sourceFolderPath)
85
- )
86
- .filter((sourceFilePath) => !sourceFilePath.endsWith('.ts'))
87
- .sort();
88
- const actualContents = (
89
- await FileSystemService.getAllFilePathsRelative(targetFolderPath)
90
- ).sort();
91
- expect(actualContents).toEqual(expectedContents);
92
- });
93
- });
94
- });
95
-
96
- /**
97
- * Creates test files and folders based on the provided structure
98
- *
99
- * @param folderPath The path where the files and folders should be created
100
- * @param fileStructure An object representing the file structure to create
101
- */
102
- async function createTestFiles(folderPath: string, fileStructure: object) {
103
- await FileSystemService.checkOrCreateFolder(folderPath);
104
-
105
- await Promise.all(
106
- Object.entries(fileStructure).map(async ([key, value]) => {
107
- if (typeof value === 'string') {
108
- await writeFile(path.join(folderPath, key), value);
109
- } else if (typeof value === 'object') {
110
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
111
- await createTestFiles(path.join(folderPath, key), value);
112
- }
113
- })
114
- );
115
- }
116
-
117
- /**
118
- * Creates a test folder within the main test directory
119
- *
120
- * @param folderName The name of the folder to create
121
- */
122
- async function createTestFolder(folderName: string): Promise<string> {
123
- const testFolderPath = path.join(TEST_FOLDER_NAME, folderName);
124
- await FileSystemService.checkOrCreateFolder(testFolderPath);
125
- return testFolderPath;
126
- }
127
-
128
- /**
129
- * Deletes the main test folder and all its contents
130
- */
131
- async function deleteTestFolder(): Promise<void> {
132
- await FileSystemService.deleteFolder(TEST_FOLDER_NAME);
133
- }