tiny-essentials 1.12.1 → 1.12.2

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.
@@ -1,7 +1,7 @@
1
1
  /******/ (() => { // webpackBootstrap
2
2
  /******/ var __webpack_modules__ = ({
3
3
 
4
- /***/ 41:
4
+ /***/ 133:
5
5
  /***/ (() => {
6
6
 
7
7
  /* (ignored) */
@@ -1924,6 +1924,13 @@ var hexSliceLookupTable = (function () {
1924
1924
  })()
1925
1925
 
1926
1926
 
1927
+ /***/ }),
1928
+
1929
+ /***/ 370:
1930
+ /***/ (() => {
1931
+
1932
+ /* (ignored) */
1933
+
1927
1934
  /***/ }),
1928
1935
 
1929
1936
  /***/ 526:
@@ -3683,10 +3690,10 @@ const getHtmlElPadding = (el) => {
3683
3690
  };
3684
3691
 
3685
3692
  // EXTERNAL MODULE: fs (ignored)
3686
- var fs_ignored_ = __webpack_require__(41);
3693
+ var fs_ignored_ = __webpack_require__(133);
3687
3694
  // EXTERNAL MODULE: ./node_modules/path-browserify/index.js
3688
3695
  var path_browserify = __webpack_require__(975);
3689
- ;// ./src/v1/basics/fileManager.mjs
3696
+ ;// ./src/v1/fileManager/normalFuncs.mjs
3690
3697
 
3691
3698
 
3692
3699
 
@@ -3702,8 +3709,8 @@ var path_browserify = __webpack_require__(975);
3702
3709
  * @returns {any}
3703
3710
  */
3704
3711
  function readJsonFile(filePath) {
3705
- if (!fs.existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
3706
- const content = fs.readFileSync(filePath, 'utf-8');
3712
+ if (!existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
3713
+ const content = readFileSync(filePath, 'utf-8');
3707
3714
  return JSON.parse(content);
3708
3715
  }
3709
3716
 
@@ -3716,32 +3723,7 @@ function readJsonFile(filePath) {
3716
3723
  */
3717
3724
  function writeJsonFile(filePath, data, spaces = 2) {
3718
3725
  const json = JSON.stringify(data, null, spaces);
3719
- fs.writeFileSync(filePath, json, 'utf-8');
3720
- }
3721
-
3722
- /**
3723
- * Reads and parses a JSON file.
3724
- * Throws an error if the file content is not valid JSON.
3725
- * @param {string} filePath
3726
- * @returns {Promise<any>}
3727
- */
3728
- async function readJsonFileAsync(filePath) {
3729
- if (!fs.existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
3730
- const content = await fs.promises.readFile(filePath, 'utf-8');
3731
- return JSON.parse(content);
3732
- }
3733
-
3734
- /**
3735
- * Saves an object as JSON to a file.
3736
- * Automatically creates the directory if it does not exist.
3737
- * @param {string} filePath
3738
- * @param {any} data
3739
- * @param {number} [spaces=2]
3740
- * @returns {Promise<void>}
3741
- */
3742
- function writeJsonFileAsync(filePath, data, spaces = 2) {
3743
- const json = JSON.stringify(data, null, spaces);
3744
- return fs.promises.writeFile(filePath, json, 'utf-8');
3726
+ writeFileSync(filePath, json, 'utf-8');
3745
3727
  }
3746
3728
 
3747
3729
  /*========================*
@@ -3752,9 +3734,9 @@ function writeJsonFileAsync(filePath, data, spaces = 2) {
3752
3734
  * Ensures that the directory exists, creating it recursively if needed.
3753
3735
  * @param {string} dirPath
3754
3736
  */
3755
- function ensureDirectory(dirPath) {
3756
- if (!fs.existsSync(dirPath)) {
3757
- fs.mkdirSync(dirPath, { recursive: true });
3737
+ function normalFuncs_ensureDirectory(dirPath) {
3738
+ if (!existsSync(dirPath)) {
3739
+ mkdirSync(dirPath, { recursive: true });
3758
3740
  }
3759
3741
  }
3760
3742
 
@@ -3763,15 +3745,15 @@ function ensureDirectory(dirPath) {
3763
3745
  * @param {string} dirPath
3764
3746
  */
3765
3747
  function clearDirectory(dirPath) {
3766
- if (!fs.existsSync(dirPath)) return;
3767
- const files = fs.readdirSync(dirPath);
3748
+ if (!existsSync(dirPath)) return;
3749
+ const files = readdirSync(dirPath);
3768
3750
  for (const file of files) {
3769
- const fullPath = path.join(dirPath, file);
3770
- const stat = fs.lstatSync(fullPath);
3771
- if (stat.isDirectory()) {
3772
- fs.rmSync(fullPath, { recursive: true, force: true });
3751
+ const fullPath = join(dirPath, file);
3752
+ const statData = lstatSync(fullPath);
3753
+ if (statData.isDirectory()) {
3754
+ rmSync(fullPath, { recursive: true, force: true });
3773
3755
  } else {
3774
- fs.unlinkSync(fullPath);
3756
+ unlinkSync(fullPath);
3775
3757
  }
3776
3758
  }
3777
3759
  }
@@ -3785,8 +3767,8 @@ function clearDirectory(dirPath) {
3785
3767
  * @param {string} filePath
3786
3768
  * @returns {boolean}
3787
3769
  */
3788
- function fileExists(filePath) {
3789
- return fs.existsSync(filePath) && fs.lstatSync(filePath).isFile();
3770
+ function normalFuncs_fileExists(filePath) {
3771
+ return existsSync(filePath) && lstatSync(filePath).isFile();
3790
3772
  }
3791
3773
 
3792
3774
  /**
@@ -3794,8 +3776,8 @@ function fileExists(filePath) {
3794
3776
  * @param {string} dirPath
3795
3777
  * @returns {boolean}
3796
3778
  */
3797
- function dirExists(dirPath) {
3798
- return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
3779
+ function normalFuncs_dirExists(dirPath) {
3780
+ return existsSync(dirPath) && lstatSync(dirPath).isDirectory();
3799
3781
  }
3800
3782
 
3801
3783
  /**
@@ -3804,7 +3786,7 @@ function dirExists(dirPath) {
3804
3786
  * @returns {boolean}
3805
3787
  */
3806
3788
  function isDirEmpty(dirPath) {
3807
- return fs.existsSync(dirPath) && fs.readdirSync(dirPath).length === 0;
3789
+ return readdirSync(dirPath).length === 0;
3808
3790
  }
3809
3791
 
3810
3792
  /*========================*
@@ -3818,8 +3800,8 @@ function isDirEmpty(dirPath) {
3818
3800
  * @param {number} [mode]
3819
3801
  */
3820
3802
  function ensureCopyFile(src, dest, mode) {
3821
- ensureDirectory(path.dirname(dest));
3822
- fs.copyFileSync(src, dest, mode);
3803
+ normalFuncs_ensureDirectory(dirname(dest));
3804
+ copyFileSync(src, dest, mode);
3823
3805
  }
3824
3806
 
3825
3807
  /**
@@ -3828,33 +3810,8 @@ function ensureCopyFile(src, dest, mode) {
3828
3810
  * @returns {boolean}
3829
3811
  */
3830
3812
  function tryDeleteFile(filePath) {
3831
- if (fileExists(filePath)) {
3832
- fs.unlinkSync(filePath);
3833
- return true;
3834
- }
3835
- return false;
3836
- }
3837
-
3838
- /**
3839
- * Copies a file to a destination.
3840
- * @param {string} src
3841
- * @param {string} dest
3842
- * @param {number} [mode]
3843
- * @returns {Promise<void>}
3844
- */
3845
- function ensureCopyFileAsync(src, dest, mode) {
3846
- ensureDirectory(path.dirname(dest));
3847
- return fs.promises.copyFile(src, dest, mode);
3848
- }
3849
-
3850
- /**
3851
- * Deletes a file (If the file exists).
3852
- * @param {string} filePath
3853
- * @returns {Promise<boolean>}
3854
- */
3855
- async function tryDeleteFileAsync(filePath) {
3856
- if (fileExists(filePath)) {
3857
- await fs.promises.unlink(filePath);
3813
+ if (normalFuncs_fileExists(filePath)) {
3814
+ unlinkSync(filePath);
3858
3815
  return true;
3859
3816
  }
3860
3817
  return false;
@@ -3868,25 +3825,12 @@ async function tryDeleteFileAsync(filePath) {
3868
3825
  * Writes text to a file (Ensures that the directory exists, creating it recursively if needed).
3869
3826
  * @param {string} filePath
3870
3827
  * @param {string} content
3871
- * @param {fs.WriteFileOptions} [ops='utf-8']
3828
+ * @param {import('fs').WriteFileOptions} [ops='utf-8']
3872
3829
  */
3873
3830
  function writeTextFile(filePath, content, ops = 'utf-8') {
3874
- const dir = path.dirname(filePath);
3875
- ensureDirectory(dir);
3876
- fs.writeFileSync(filePath, content, ops);
3877
- }
3878
-
3879
- /**
3880
- * Writes text to a file (Ensures that the directory exists, creating it recursively if needed).
3881
- * @param {string} filePath
3882
- * @param {string} content
3883
- * @param {fs.WriteFileOptions} [ops='utf-8']
3884
- * @returns {Promise<void>}
3885
- */
3886
- function writeTextFileAsync(filePath, content, ops = 'utf-8') {
3887
- const dir = path.dirname(filePath);
3888
- ensureDirectory(dir);
3889
- return fs.promises.writeFile(filePath, content, ops);
3831
+ const dir = dirname(filePath);
3832
+ normalFuncs_ensureDirectory(dir);
3833
+ writeFileSync(filePath, content, ops);
3890
3834
  }
3891
3835
 
3892
3836
  /*========================*
@@ -3902,13 +3846,13 @@ function writeTextFileAsync(filePath, content, ops = 'utf-8') {
3902
3846
  function listFiles(dirPath, recursive = false) {
3903
3847
  /** @type {{ files: string[]; dirs: string[] }} */
3904
3848
  const results = { files: [], dirs: [] };
3905
- if (!dirExists(dirPath)) return results;
3849
+ if (!normalFuncs_dirExists(dirPath)) return results;
3906
3850
 
3907
- const entries = fs.readdirSync(dirPath);
3851
+ const entries = readdirSync(dirPath);
3908
3852
  for (const entry of entries) {
3909
- const fullPath = path.join(dirPath, entry);
3910
- const stat = fs.lstatSync(fullPath);
3911
- if (stat.isDirectory()) {
3853
+ const fullPath = join(dirPath, entry);
3854
+ const statData = lstatSync(fullPath);
3855
+ if (statData.isDirectory()) {
3912
3856
  results.dirs.push(fullPath);
3913
3857
  if (recursive) {
3914
3858
  const results2 = listFiles(fullPath, true);
@@ -3931,13 +3875,13 @@ function listFiles(dirPath, recursive = false) {
3931
3875
  function listDirs(dirPath, recursive = false) {
3932
3876
  /** @type {string[]} */
3933
3877
  const results = [];
3934
- if (!dirExists(dirPath)) return results;
3878
+ if (!normalFuncs_dirExists(dirPath)) return results;
3935
3879
 
3936
- const entries = fs.readdirSync(dirPath);
3880
+ const entries = readdirSync(dirPath);
3937
3881
  for (const entry of entries) {
3938
- const fullPath = path.join(dirPath, entry);
3939
- const stat = fs.lstatSync(fullPath);
3940
- if (stat.isDirectory()) {
3882
+ const fullPath = join(dirPath, entry);
3883
+ const statData = lstatSync(fullPath);
3884
+ if (statData.isDirectory()) {
3941
3885
  results.push(fullPath);
3942
3886
  if (recursive) {
3943
3887
  results.push(...listDirs(fullPath, true));
@@ -3957,8 +3901,8 @@ function listDirs(dirPath, recursive = false) {
3957
3901
  * @returns {number}
3958
3902
  */
3959
3903
  function fileSize(filePath) {
3960
- if (!fileExists(filePath)) return 0;
3961
- const stats = fs.statSync(filePath);
3904
+ if (!normalFuncs_fileExists(filePath)) return 0;
3905
+ const stats = statSync(filePath);
3962
3906
  return stats.size;
3963
3907
  }
3964
3908
 
@@ -3986,7 +3930,7 @@ function dirSize(dirPath) {
3986
3930
  * @param {string} [ext='bak']
3987
3931
  */
3988
3932
  function backupFile(filePath, ext = 'bak') {
3989
- if (!fileExists(filePath)) return;
3933
+ if (!normalFuncs_fileExists(filePath)) return;
3990
3934
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
3991
3935
  const backupPath = `${filePath}.${ext}.${timestamp}`;
3992
3936
  ensureCopyFile(filePath, backupPath);
@@ -3998,18 +3942,17 @@ function backupFile(filePath, ext = 'bak') {
3998
3942
  * @param {string} [ext='bak']
3999
3943
  * @returns {string} Full path to the most recent backup
4000
3944
  */
4001
- function getLatestBackupPath(filePath, ext = 'bak') {
4002
- const dir = path.dirname(filePath);
4003
- const baseName = path.basename(filePath);
4004
- const backups = fs
4005
- .readdirSync(dir)
3945
+ function normalFuncs_getLatestBackupPath(filePath, ext = 'bak') {
3946
+ const dir = dirname(filePath);
3947
+ const baseName = basename(filePath);
3948
+ const backups = readdirSync(dir)
4006
3949
  .filter((name) => name.startsWith(`${baseName}.${ext}.`))
4007
3950
  .sort()
4008
3951
  .reverse();
4009
3952
 
4010
3953
  if (backups.length === 0) throw new Error(`No backups found for ${filePath}`);
4011
3954
 
4012
- return path.join(dir, backups[0]);
3955
+ return join(dir, backups[0]);
4013
3956
  }
4014
3957
 
4015
3958
  /**
@@ -4018,34 +3961,10 @@ function getLatestBackupPath(filePath, ext = 'bak') {
4018
3961
  * @param {string} [ext='bak']
4019
3962
  */
4020
3963
  function restoreLatestBackup(filePath, ext = 'bak') {
4021
- const latestBackup = getLatestBackupPath(filePath, ext);
3964
+ const latestBackup = normalFuncs_getLatestBackupPath(filePath, ext);
4022
3965
  ensureCopyFile(latestBackup, filePath);
4023
3966
  }
4024
3967
 
4025
- /**
4026
- * Restores the most recent backup of a file.
4027
- * @param {string} filePath
4028
- * @param {string} [ext='bak']
4029
- * @returns {Promise<void>}
4030
- */
4031
- function restoreLatestBackupAsync(filePath, ext = 'bak') {
4032
- const latestBackup = getLatestBackupPath(filePath, ext);
4033
- return ensureCopyFileAsync(latestBackup, filePath);
4034
- }
4035
-
4036
- /**
4037
- * Creates a backup copy of a file with .bak timestamp suffix.
4038
- * @param {string} filePath
4039
- * @param {string} [ext='bak']
4040
- * @returns {Promise<void>}
4041
- */
4042
- async function backupFileAsync(filePath, ext = 'bak') {
4043
- if (!fileExists(filePath)) return;
4044
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
4045
- const backupPath = `${filePath}.${ext}.${timestamp}`;
4046
- return ensureCopyFileAsync(filePath, backupPath);
4047
- }
4048
-
4049
3968
  /*========================*
4050
3969
  * Rename Utilities
4051
3970
  *========================*/
@@ -4064,7 +3983,7 @@ function renameFileBatch(dirPath, renameFn, extensions = []) {
4064
3983
  if (typeof dirPath !== 'string') throw new TypeError('dirPath must be a string');
4065
3984
  if (typeof renameFn !== 'function') throw new TypeError('renameFn must be a function');
4066
3985
  if (!Array.isArray(extensions)) throw new TypeError('extensions must be an array of strings');
4067
- if (!fs.existsSync(dirPath) || !fs.statSync(dirPath).isDirectory())
3986
+ if (!existsSync(dirPath) || !statSync(dirPath).isDirectory())
4068
3987
  throw new Error(`Directory not found or invalid: ${dirPath}`);
4069
3988
  for (const ext of extensions) {
4070
3989
  if (typeof ext !== 'string' || !ext.startsWith('.'))
@@ -4075,16 +3994,16 @@ function renameFileBatch(dirPath, renameFn, extensions = []) {
4075
3994
  let index = 0;
4076
3995
 
4077
3996
  for (const file of files) {
4078
- const ext = path.extname(file);
3997
+ const ext = extname(file);
4079
3998
  if (extensions.length && !extensions.includes(ext)) continue;
4080
3999
 
4081
- const originalName = path.basename(file);
4000
+ const originalName = basename(file);
4082
4001
  const newName = renameFn(originalName, index++);
4083
- const newPath = path.join(dirPath, newName);
4002
+ const newPath = join(dirPath, newName);
4084
4003
 
4085
4004
  if (originalName === newName) continue;
4086
4005
 
4087
- fs.renameSync(file, newPath);
4006
+ renameSync(file, newPath);
4088
4007
  }
4089
4008
  }
4090
4009
 
@@ -4099,8 +4018,8 @@ function renameFileRegex(dirPath, pattern, replacement, extensions = []) {
4099
4018
  renameFileBatch(
4100
4019
  dirPath,
4101
4020
  (filename) => {
4102
- const ext = path.extname(filename);
4103
- const name = path.basename(filename, ext).replace(pattern, replacement);
4021
+ const ext = extname(filename);
4022
+ const name = basename(filename, ext).replace(pattern, replacement);
4104
4023
  return `${name}${ext}`;
4105
4024
  },
4106
4025
  extensions,
@@ -4117,8 +4036,8 @@ function renameFileAddPrefixSuffix(dirPath, { prefix = '', suffix = '' }, extens
4117
4036
  renameFileBatch(
4118
4037
  dirPath,
4119
4038
  (filename) => {
4120
- const ext = path.extname(filename);
4121
- const name = path.basename(filename, ext);
4039
+ const ext = extname(filename);
4040
+ const name = basename(filename, ext);
4122
4041
  return `${prefix}${name}${suffix}${ext}`;
4123
4042
  },
4124
4043
  extensions,
@@ -4155,9 +4074,9 @@ function renameFileNormalizeCase(
4155
4074
  else return text;
4156
4075
  };
4157
4076
 
4158
- const rawExt = path.extname(filename);
4077
+ const rawExt = extname(filename);
4159
4078
  const ext = normalizeExt ? changeToMode(rawExt) : rawExt;
4160
- const name = changeToMode(path.basename(filename, rawExt));
4079
+ const name = changeToMode(basename(filename, rawExt));
4161
4080
  return `${name}${ext}`;
4162
4081
  },
4163
4082
  extensions,
@@ -4180,6 +4099,266 @@ function renameFilePadNumbers(dirPath, totalDigits = 3, extensions = []) {
4180
4099
  );
4181
4100
  }
4182
4101
 
4102
+ // EXTERNAL MODULE: fs/promises (ignored)
4103
+ var promises_ignored_ = __webpack_require__(370);
4104
+ ;// ./src/v1/fileManager/asyncFuncs.mjs
4105
+
4106
+
4107
+
4108
+
4109
+
4110
+ /*========================*
4111
+ * JSON Operations
4112
+ *========================*/
4113
+
4114
+ /**
4115
+ * Reads and parses a JSON file.
4116
+ * Throws an error if the file content is not valid JSON.
4117
+ * @param {string} filePath
4118
+ * @returns {Promise<any>}
4119
+ */
4120
+ async function readJsonFileAsync(filePath) {
4121
+ if (!existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
4122
+ const content = await readFile(filePath, 'utf-8');
4123
+ return JSON.parse(content);
4124
+ }
4125
+
4126
+ /**
4127
+ * Saves an object as JSON to a file.
4128
+ * Automatically creates the directory if it does not exist.
4129
+ * @param {string} filePath
4130
+ * @param {any} data
4131
+ * @param {number} [spaces=2]
4132
+ * @returns {Promise<void>}
4133
+ */
4134
+ function writeJsonFileAsync(filePath, data, spaces = 2) {
4135
+ const json = JSON.stringify(data, null, spaces);
4136
+ return writeFile(filePath, json, 'utf-8');
4137
+ }
4138
+
4139
+ /*========================*
4140
+ * Directory Management
4141
+ *========================*/
4142
+
4143
+ /**
4144
+ * Clears all contents inside a directory but keeps the directory.
4145
+ * @param {string} dirPath
4146
+ */
4147
+ async function clearDirectoryAsync(dirPath) {
4148
+ if (!existsSync(dirPath)) return;
4149
+ const files = await readdir(dirPath);
4150
+
4151
+ /** @type {Record<string, import('fs').Stats>} */
4152
+ const dataList = {};
4153
+ const promises = [];
4154
+
4155
+ for (const file of files) {
4156
+ const fullPath = join(dirPath, file);
4157
+ const lsResult = lstat(fullPath);
4158
+
4159
+ lsResult.then((statData) => {
4160
+ dataList[fullPath] = statData;
4161
+ return statData;
4162
+ });
4163
+ promises.push(lsResult);
4164
+ }
4165
+
4166
+ await Promise.all(promises);
4167
+ const promises2 = [];
4168
+ for (const fullPath in dataList) {
4169
+ const statData = dataList[fullPath];
4170
+ if (statData.isDirectory()) {
4171
+ promises2.push(rm(fullPath, { recursive: true, force: true }));
4172
+ } else {
4173
+ promises2.push(unlink(fullPath));
4174
+ }
4175
+ }
4176
+
4177
+ await Promise.all(promises2);
4178
+ }
4179
+
4180
+ /*========================*
4181
+ * File Checks
4182
+ *========================*/
4183
+
4184
+ /**
4185
+ * Checks whether a directory is empty.
4186
+ * @param {string} dirPath
4187
+ * @returns {Promise<boolean>}
4188
+ */
4189
+ async function isDirEmptyAsync(dirPath) {
4190
+ const data = await readdir(dirPath);
4191
+ return data.length === 0;
4192
+ }
4193
+
4194
+ /*========================*
4195
+ * File Operations
4196
+ *========================*/
4197
+
4198
+ /**
4199
+ * Copies a file to a destination.
4200
+ * @param {string} src
4201
+ * @param {string} dest
4202
+ * @param {number} [mode]
4203
+ * @returns {Promise<void>}
4204
+ */
4205
+ function ensureCopyFileAsync(src, dest, mode) {
4206
+ ensureDirectory(dirname(dest));
4207
+ return copyFile(src, dest, mode);
4208
+ }
4209
+
4210
+ /**
4211
+ * Deletes a file (If the file exists).
4212
+ * @param {string} filePath
4213
+ * @returns {Promise<boolean>}
4214
+ */
4215
+ async function tryDeleteFileAsync(filePath) {
4216
+ if (fileExists(filePath)) {
4217
+ await unlink(filePath);
4218
+ return true;
4219
+ }
4220
+ return false;
4221
+ }
4222
+
4223
+ /*========================*
4224
+ * Text Operations
4225
+ *========================*/
4226
+
4227
+ /**
4228
+ * Writes text to a file (Ensures that the directory exists, creating it recursively if needed).
4229
+ * @param {string} filePath
4230
+ * @param {string} content
4231
+ * @param {import('fs').WriteFileOptions} [ops='utf-8']
4232
+ * @returns {Promise<void>}
4233
+ */
4234
+ function writeTextFileAsync(filePath, content, ops = 'utf-8') {
4235
+ const dir = dirname(filePath);
4236
+ ensureDirectory(dir);
4237
+ return writeFile(filePath, content, ops);
4238
+ }
4239
+
4240
+ /*========================*
4241
+ * Directory Listings
4242
+ *========================*/
4243
+
4244
+ /**
4245
+ * Lists all files and dirs in a directory (optionally recursive).
4246
+ * @param {string} dirPath
4247
+ * @param {boolean} [recursive=false]
4248
+ * @returns {Promise<{ files: string[]; dirs: string[] }>}
4249
+ */
4250
+ async function listFilesAsync(dirPath, recursive = false) {
4251
+ /** @type {{ files: string[]; dirs: string[] }} */
4252
+ const results = { files: [], dirs: [] };
4253
+ if (!dirExists(dirPath)) return results;
4254
+
4255
+ const entries = await readdir(dirPath);
4256
+ for (const entry of entries) {
4257
+ const fullPath = join(dirPath, entry);
4258
+ const statData = await lstat(fullPath);
4259
+ if (statData.isDirectory()) {
4260
+ results.dirs.push(fullPath);
4261
+ if (recursive) {
4262
+ const results2 = await listFilesAsync(fullPath, true);
4263
+ results.files.push(...results2.files);
4264
+ results.dirs.push(...results2.dirs);
4265
+ }
4266
+ } else {
4267
+ results.files.push(fullPath);
4268
+ }
4269
+ }
4270
+ return results;
4271
+ }
4272
+
4273
+ /**
4274
+ * Lists all directories in a directory (optionally recursive).
4275
+ * @param {string} dirPath
4276
+ * @param {boolean} [recursive=false]
4277
+ * @returns {Promise<string[]>}
4278
+ */
4279
+ async function listDirsAsync(dirPath, recursive = false) {
4280
+ /** @type {string[]} */
4281
+ const results = [];
4282
+ if (!dirExists(dirPath)) return results;
4283
+
4284
+ const entries = await readdir(dirPath);
4285
+ for (const entry of entries) {
4286
+ const fullPath = join(dirPath, entry);
4287
+ const statData = await lstat(fullPath);
4288
+ if (statData.isDirectory()) {
4289
+ results.push(fullPath);
4290
+ if (recursive) {
4291
+ results.push(...(await listDirsAsync(fullPath, true)));
4292
+ }
4293
+ }
4294
+ }
4295
+ return results;
4296
+ }
4297
+
4298
+ /*========================*
4299
+ * File Info
4300
+ *========================*/
4301
+
4302
+ /**
4303
+ * Returns the size of a file in bytes.
4304
+ * @param {string} filePath
4305
+ * @returns {Promise<number>}
4306
+ */
4307
+ async function fileSizeAsync(filePath) {
4308
+ if (!fileExists(filePath)) return 0;
4309
+ const stats = await stat(filePath);
4310
+ return stats.size;
4311
+ }
4312
+
4313
+ /**
4314
+ * Returns the total size of a directory in bytes.
4315
+ * @param {string} dirPath
4316
+ * @returns {Promise<number>}
4317
+ */
4318
+ async function dirSizeAsync(dirPath) {
4319
+ let total = 0;
4320
+ const { files } = await listFilesAsync(dirPath, true);
4321
+ const promises = [];
4322
+ for (const file of files) {
4323
+ const result = fileSizeAsync(file);
4324
+ result.then((item) => {
4325
+ total += item;
4326
+ return item;
4327
+ });
4328
+ promises.push(result);
4329
+ }
4330
+ await Promise.all(promises);
4331
+ return total;
4332
+ }
4333
+
4334
+ /*========================*
4335
+ * Backup Utilities
4336
+ *========================*/
4337
+
4338
+ /**
4339
+ * Restores the most recent backup of a file.
4340
+ * @param {string} filePath
4341
+ * @param {string} [ext='bak']
4342
+ * @returns {Promise<void>}
4343
+ */
4344
+ function restoreLatestBackupAsync(filePath, ext = 'bak') {
4345
+ const latestBackup = getLatestBackupPath(filePath, ext);
4346
+ return ensureCopyFileAsync(latestBackup, filePath);
4347
+ }
4348
+
4349
+ /**
4350
+ * Creates a backup copy of a file with .bak timestamp suffix.
4351
+ * @param {string} filePath
4352
+ * @param {string} [ext='bak']
4353
+ * @returns {Promise<void>}
4354
+ */
4355
+ async function backupFileAsync(filePath, ext = 'bak') {
4356
+ if (!fileExists(filePath)) return;
4357
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
4358
+ const backupPath = `${filePath}.${ext}.${timestamp}`;
4359
+ return ensureCopyFileAsync(filePath, backupPath);
4360
+ }
4361
+
4183
4362
  ;// ./src/v1/libs/TinyDragger.mjs
4184
4363
 
4185
4364
 
@@ -5103,6 +5282,10 @@ class TinyDragger {
5103
5282
 
5104
5283
 
5105
5284
 
5285
+
5286
+
5287
+
5288
+
5106
5289
 
5107
5290
 
5108
5291