@git.zone/cli 1.16.6 → 1.16.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.
Files changed (79) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/classes.gitzoneconfig.js +1 -1
  3. package/dist_ts/gitzone.cli.js +1 -1
  4. package/dist_ts/gitzone.logging.js +1 -1
  5. package/dist_ts/mod_commit/index.js +3 -2
  6. package/dist_ts/mod_deprecate/index.js +1 -1
  7. package/dist_ts/mod_format/classes.baseformatter.d.ts +0 -2
  8. package/dist_ts/mod_format/classes.baseformatter.js +3 -22
  9. package/dist_ts/mod_format/classes.changecache.js +14 -29
  10. package/dist_ts/mod_format/classes.dependency-analyzer.js +24 -18
  11. package/dist_ts/mod_format/classes.diffreporter.js +4 -4
  12. package/dist_ts/mod_format/classes.formatcontext.d.ts +0 -13
  13. package/dist_ts/mod_format/classes.formatcontext.js +1 -41
  14. package/dist_ts/mod_format/classes.formatplanner.js +25 -45
  15. package/dist_ts/mod_format/classes.formatstats.js +22 -20
  16. package/dist_ts/mod_format/classes.rollbackmanager.d.ts +1 -0
  17. package/dist_ts/mod_format/classes.rollbackmanager.js +79 -16
  18. package/dist_ts/mod_format/format.cleanup.js +7 -2
  19. package/dist_ts/mod_format/format.copy.d.ts +1 -1
  20. package/dist_ts/mod_format/format.copy.js +3 -3
  21. package/dist_ts/mod_format/format.gitignore.js +1 -1
  22. package/dist_ts/mod_format/format.license.js +1 -1
  23. package/dist_ts/mod_format/format.npmextra.js +1 -1
  24. package/dist_ts/mod_format/format.packagejson.js +5 -3
  25. package/dist_ts/mod_format/format.prettier.js +7 -2
  26. package/dist_ts/mod_format/format.readme.js +1 -1
  27. package/dist_ts/mod_format/format.templates.js +1 -1
  28. package/dist_ts/mod_format/format.tsconfig.js +4 -2
  29. package/dist_ts/mod_format/formatters/cleanup.formatter.js +8 -3
  30. package/dist_ts/mod_format/formatters/legacy.formatter.js +6 -4
  31. package/dist_ts/mod_format/formatters/prettier.formatter.js +9 -16
  32. package/dist_ts/mod_format/formatters/readme.formatter.js +6 -4
  33. package/dist_ts/mod_format/index.js +13 -71
  34. package/dist_ts/mod_meta/meta.classes.meta.js +1 -1
  35. package/dist_ts/mod_standard/index.js +1 -1
  36. package/dist_ts/mod_start/index.js +1 -1
  37. package/dist_ts/mod_template/index.js +1 -1
  38. package/package.json +1 -1
  39. package/ts/00_commitinfo_data.ts +1 -1
  40. package/ts/classes.gitzoneconfig.ts +3 -1
  41. package/ts/gitzone.cli.ts +5 -5
  42. package/ts/gitzone.logging.ts +2 -1
  43. package/ts/mod_commit/index.ts +36 -11
  44. package/ts/mod_deprecate/index.ts +4 -1
  45. package/ts/mod_format/classes.baseformatter.ts +15 -38
  46. package/ts/mod_format/classes.changecache.ts +74 -80
  47. package/ts/mod_format/classes.dependency-analyzer.ts +46 -36
  48. package/ts/mod_format/classes.diffreporter.ts +44 -28
  49. package/ts/mod_format/classes.formatcontext.ts +3 -54
  50. package/ts/mod_format/classes.formatplanner.ts +56 -70
  51. package/ts/mod_format/classes.formatstats.ts +69 -49
  52. package/ts/mod_format/classes.rollbackmanager.ts +170 -70
  53. package/ts/mod_format/format.cleanup.ts +9 -2
  54. package/ts/mod_format/format.copy.ts +17 -14
  55. package/ts/mod_format/format.gitignore.ts +2 -1
  56. package/ts/mod_format/format.license.ts +3 -1
  57. package/ts/mod_format/format.npmextra.ts +9 -2
  58. package/ts/mod_format/format.packagejson.ts +47 -12
  59. package/ts/mod_format/format.prettier.ts +10 -2
  60. package/ts/mod_format/format.readme.ts +2 -1
  61. package/ts/mod_format/format.templates.ts +15 -7
  62. package/ts/mod_format/format.tsconfig.ts +6 -2
  63. package/ts/mod_format/formatters/cleanup.formatter.ts +13 -8
  64. package/ts/mod_format/formatters/copy.formatter.ts +1 -1
  65. package/ts/mod_format/formatters/gitignore.formatter.ts +1 -1
  66. package/ts/mod_format/formatters/legacy.formatter.ts +19 -12
  67. package/ts/mod_format/formatters/license.formatter.ts +1 -1
  68. package/ts/mod_format/formatters/npmextra.formatter.ts +1 -1
  69. package/ts/mod_format/formatters/packagejson.formatter.ts +1 -1
  70. package/ts/mod_format/formatters/prettier.formatter.ts +50 -47
  71. package/ts/mod_format/formatters/readme.formatter.ts +11 -9
  72. package/ts/mod_format/formatters/templates.formatter.ts +1 -1
  73. package/ts/mod_format/formatters/tsconfig.formatter.ts +1 -1
  74. package/ts/mod_format/index.ts +54 -113
  75. package/ts/mod_format/interfaces.format.ts +3 -3
  76. package/ts/mod_meta/meta.classes.meta.ts +57 -19
  77. package/ts/mod_standard/index.ts +3 -1
  78. package/ts/mod_start/index.ts +3 -1
  79. package/ts/mod_template/index.ts +5 -2
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/cli',
6
- version: '1.16.6',
6
+ version: '1.16.8',
7
7
  description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
8
8
  }
@@ -40,7 +40,9 @@ export class GitzoneConfig {
40
40
  public async readConfigFromCwd() {
41
41
  const npmextraInstance = new plugins.npmextra.Npmextra(paths.cwd);
42
42
  this.data = npmextraInstance.dataFor<IGitzoneConfigData>('gitzone', {});
43
- this.data.npmciOptions = npmextraInstance.dataFor<IGitzoneConfigData['npmciOptions']>('npmci', {
43
+ this.data.npmciOptions = npmextraInstance.dataFor<
44
+ IGitzoneConfigData['npmciOptions']
45
+ >('npmci', {
44
46
  npmAccessLevel: 'public',
45
47
  });
46
48
  }
package/ts/gitzone.cli.ts CHANGED
@@ -62,23 +62,23 @@ export let run = async () => {
62
62
  gitzoneSmartcli.addCommand('format').subscribe(async (argvArg) => {
63
63
  const config = GitzoneConfig.fromCwd();
64
64
  const modFormat = await import('./mod_format/index.js');
65
-
65
+
66
66
  // Handle rollback commands
67
67
  if (argvArg.rollback) {
68
68
  await modFormat.handleRollback(argvArg.rollback);
69
69
  return;
70
70
  }
71
-
71
+
72
72
  if (argvArg['list-backups']) {
73
73
  await modFormat.handleListBackups();
74
74
  return;
75
75
  }
76
-
76
+
77
77
  if (argvArg['clean-backups']) {
78
78
  await modFormat.handleCleanBackups();
79
79
  return;
80
80
  }
81
-
81
+
82
82
  // Handle format with options
83
83
  await modFormat.run({
84
84
  dryRun: argvArg['dry-run'],
@@ -89,7 +89,7 @@ export let run = async () => {
89
89
  detailed: argvArg.detailed,
90
90
  interactive: argvArg.interactive !== false,
91
91
  parallel: argvArg.parallel !== false,
92
- verbose: argvArg.verbose
92
+ verbose: argvArg.verbose,
93
93
  });
94
94
  });
95
95
 
@@ -5,7 +5,8 @@ import * as plugins from './plugins.js';
5
5
  export const logger = plugins.smartlog.Smartlog.createForCommitinfo(commitinfo);
6
6
 
7
7
  // Add console destination
8
- const consoleDestination = new plugins.smartlogDestinationLocal.DestinationLocal();
8
+ const consoleDestination =
9
+ new plugins.smartlogDestinationLocal.DestinationLocal();
9
10
  logger.addLogDestination(consoleDestination);
10
11
 
11
12
  // Verbose logging helper
@@ -10,20 +10,22 @@ export const run = async (argvArg: any) => {
10
10
  await formatMod.run();
11
11
  }
12
12
 
13
-
14
13
  logger.log('info', `gathering facts...`);
15
14
  const aidoc = new plugins.tsdoc.AiDoc();
16
15
  await aidoc.start();
17
16
 
18
17
  const nextCommitObject = await aidoc.buildNextCommitObject(paths.cwd);
19
18
 
20
- logger.log('info', `---------
19
+ logger.log(
20
+ 'info',
21
+ `---------
21
22
  Next recommended commit would be:
22
23
  ===========
23
24
  -> ${nextCommitObject.recommendedNextVersion}:
24
25
  -> ${nextCommitObject.recommendedNextVersionLevel}(${nextCommitObject.recommendedNextVersionScope}): ${nextCommitObject.recommendedNextVersionMessage}
25
26
  ===========
26
- `);
27
+ `,
28
+ );
27
29
  const commitInteract = new plugins.smartinteract.SmartInteract();
28
30
  commitInteract.addQuestions([
29
31
  {
@@ -72,32 +74,55 @@ export const run = async (argvArg: any) => {
72
74
  });
73
75
 
74
76
  logger.log('info', `Baking commitinfo into code ...`);
75
- const commitInfo = new plugins.commitinfo.CommitInfo(paths.cwd, commitVersionType);
77
+ const commitInfo = new plugins.commitinfo.CommitInfo(
78
+ paths.cwd,
79
+ commitVersionType,
80
+ );
76
81
  await commitInfo.writeIntoPotentialDirs();
77
82
 
78
83
  logger.log('info', `Writing changelog.md ...`);
79
84
  let changelog = nextCommitObject.changelog;
80
- changelog = changelog.replaceAll('{{nextVersion}}', (await commitInfo.getNextPlannedVersion()).versionString);
81
- changelog = changelog.replaceAll('{{nextVersionScope}}', `${await answerBucket.getAnswerFor('commitType')}(${await answerBucket.getAnswerFor('commitScope')})`);
82
- changelog = changelog.replaceAll('{{nextVersionMessage}}', nextCommitObject.recommendedNextVersionMessage);
85
+ changelog = changelog.replaceAll(
86
+ '{{nextVersion}}',
87
+ (await commitInfo.getNextPlannedVersion()).versionString,
88
+ );
89
+ changelog = changelog.replaceAll(
90
+ '{{nextVersionScope}}',
91
+ `${await answerBucket.getAnswerFor('commitType')}(${await answerBucket.getAnswerFor('commitScope')})`,
92
+ );
93
+ changelog = changelog.replaceAll(
94
+ '{{nextVersionMessage}}',
95
+ nextCommitObject.recommendedNextVersionMessage,
96
+ );
83
97
  if (nextCommitObject.recommendedNextVersionDetails?.length > 0) {
84
- changelog = changelog.replaceAll('{{nextVersionDetails}}', '- ' + nextCommitObject.recommendedNextVersionDetails.join('\n- '));
98
+ changelog = changelog.replaceAll(
99
+ '{{nextVersionDetails}}',
100
+ '- ' + nextCommitObject.recommendedNextVersionDetails.join('\n- '),
101
+ );
85
102
  } else {
86
103
  changelog = changelog.replaceAll('\n{{nextVersionDetails}}', '');
87
104
  }
88
105
 
89
- await plugins.smartfile.memory.toFs(changelog, plugins.path.join(paths.cwd, `changelog.md`));
106
+ await plugins.smartfile.memory.toFs(
107
+ changelog,
108
+ plugins.path.join(paths.cwd, `changelog.md`),
109
+ );
90
110
 
91
111
  logger.log('info', `Staging files for commit:`);
92
112
  await smartshellInstance.exec(`git add -A`);
93
113
  await smartshellInstance.exec(`git commit -m "${commitString}"`);
94
114
  await smartshellInstance.exec(`npm version ${commitVersionType}`);
95
- if (answerBucket.getAnswerFor('pushToOrigin') && !(process.env.CI === 'true')) {
115
+ if (
116
+ answerBucket.getAnswerFor('pushToOrigin') &&
117
+ !(process.env.CI === 'true')
118
+ ) {
96
119
  await smartshellInstance.exec(`git push origin master --follow-tags`);
97
120
  }
98
121
  };
99
122
 
100
- const createCommitStringFromAnswerBucket = (answerBucket: plugins.smartinteract.AnswerBucket) => {
123
+ const createCommitStringFromAnswerBucket = (
124
+ answerBucket: plugins.smartinteract.AnswerBucket,
125
+ ) => {
101
126
  const commitType = answerBucket.getAnswerFor('commitType');
102
127
  const commitScope = answerBucket.getAnswerFor('commitScope');
103
128
  const commitDescription = answerBucket.getAnswerFor('commitDescription');
@@ -36,7 +36,10 @@ export const run = async () => {
36
36
  const registryUrls = answerBucket.getAnswerFor(`registryUrls`).split(',');
37
37
  const oldPackageName = answerBucket.getAnswerFor(`oldPackageName`);
38
38
  const newPackageName = answerBucket.getAnswerFor(`newPackageName`);
39
- logger.log('info', `Deprecating package ${oldPackageName} in favour of ${newPackageName}`);
39
+ logger.log(
40
+ 'info',
41
+ `Deprecating package ${oldPackageName} in favour of ${newPackageName}`,
42
+ );
40
43
  const smartshellInstance = new plugins.smartshell.Smartshell({
41
44
  executor: 'bash',
42
45
  });
@@ -2,32 +2,29 @@ import * as plugins from './mod.plugins.js';
2
2
  import { FormatContext } from './classes.formatcontext.js';
3
3
  import type { IPlannedChange } from './interfaces.format.js';
4
4
  import { Project } from '../classes.project.js';
5
- import { ChangeCache } from './classes.changecache.js';
6
5
 
7
6
  export abstract class BaseFormatter {
8
7
  protected context: FormatContext;
9
8
  protected project: Project;
10
- protected cache: ChangeCache;
11
9
  protected stats: any; // Will be FormatStats from context
12
-
10
+
13
11
  constructor(context: FormatContext, project: Project) {
14
12
  this.context = context;
15
13
  this.project = project;
16
- this.cache = context.getChangeCache();
17
14
  this.stats = context.getFormatStats();
18
15
  }
19
-
16
+
20
17
  abstract get name(): string;
21
18
  abstract analyze(): Promise<IPlannedChange[]>;
22
19
  abstract applyChange(change: IPlannedChange): Promise<void>;
23
-
20
+
24
21
  async execute(changes: IPlannedChange[]): Promise<void> {
25
22
  const startTime = this.stats.moduleStartTime(this.name);
26
23
  this.stats.startModule(this.name);
27
-
24
+
28
25
  try {
29
26
  await this.preExecute();
30
-
27
+
31
28
  for (const change of changes) {
32
29
  try {
33
30
  await this.applyChange(change);
@@ -37,57 +34,37 @@ export abstract class BaseFormatter {
37
34
  throw error;
38
35
  }
39
36
  }
40
-
37
+
41
38
  await this.postExecute();
42
39
  } catch (error) {
43
- await this.context.rollbackOperation();
40
+ // Don't rollback here - let the FormatPlanner handle it
44
41
  throw error;
45
42
  } finally {
46
43
  this.stats.endModule(this.name, startTime);
47
44
  }
48
45
  }
49
-
46
+
50
47
  protected async preExecute(): Promise<void> {
51
48
  // Override in subclasses if needed
52
49
  }
53
-
50
+
54
51
  protected async postExecute(): Promise<void> {
55
52
  // Override in subclasses if needed
56
53
  }
57
-
54
+
58
55
  protected async modifyFile(filepath: string, content: string): Promise<void> {
59
- await this.context.trackFileChange(filepath);
60
56
  await plugins.smartfile.memory.toFs(content, filepath);
61
- await this.cache.updateFileCache(filepath);
62
57
  }
63
-
58
+
64
59
  protected async createFile(filepath: string, content: string): Promise<void> {
65
60
  await plugins.smartfile.memory.toFs(content, filepath);
66
- await this.cache.updateFileCache(filepath);
67
61
  }
68
-
62
+
69
63
  protected async deleteFile(filepath: string): Promise<void> {
70
- await this.context.trackFileChange(filepath);
71
64
  await plugins.smartfile.fs.remove(filepath);
72
65
  }
73
-
66
+
74
67
  protected async shouldProcessFile(filepath: string): Promise<boolean> {
75
- const config = new plugins.npmextra.Npmextra();
76
- const useCache = config.dataFor('gitzone.format.cache.enabled', true);
77
-
78
- if (!useCache) {
79
- return true; // Process all files if cache is disabled
80
- }
81
-
82
- const hasChanged = await this.cache.hasFileChanged(filepath);
83
-
84
- // Record cache statistics
85
- if (hasChanged) {
86
- this.stats.recordCacheMiss();
87
- } else {
88
- this.stats.recordCacheHit();
89
- }
90
-
91
- return hasChanged;
68
+ return true;
92
69
  }
93
- }
70
+ }
@@ -18,32 +18,32 @@ export class ChangeCache {
18
18
  private cacheDir: string;
19
19
  private manifestPath: string;
20
20
  private cacheVersion = '1.0.0';
21
-
21
+
22
22
  constructor() {
23
23
  this.cacheDir = plugins.path.join(paths.cwd, '.nogit', 'gitzone-cache');
24
24
  this.manifestPath = plugins.path.join(this.cacheDir, 'manifest.json');
25
25
  }
26
-
26
+
27
27
  async initialize(): Promise<void> {
28
28
  await plugins.smartfile.fs.ensureDir(this.cacheDir);
29
29
  }
30
-
30
+
31
31
  async getManifest(): Promise<ICacheManifest> {
32
32
  const defaultManifest: ICacheManifest = {
33
33
  version: this.cacheVersion,
34
34
  lastFormat: 0,
35
- files: []
35
+ files: [],
36
36
  };
37
-
37
+
38
38
  const exists = await plugins.smartfile.fs.fileExists(this.manifestPath);
39
39
  if (!exists) {
40
40
  return defaultManifest;
41
41
  }
42
-
42
+
43
43
  try {
44
44
  const content = plugins.smartfile.fs.toStringSync(this.manifestPath);
45
45
  const manifest = JSON.parse(content);
46
-
46
+
47
47
  // Validate the manifest structure
48
48
  if (this.isValidManifest(manifest)) {
49
49
  return manifest;
@@ -52,7 +52,9 @@ export class ChangeCache {
52
52
  return defaultManifest;
53
53
  }
54
54
  } catch (error) {
55
- console.warn(`Failed to read cache manifest: ${error.message}, returning default manifest`);
55
+ console.warn(
56
+ `Failed to read cache manifest: ${error.message}, returning default manifest`,
57
+ );
56
58
  // Try to delete the corrupted file
57
59
  try {
58
60
  await plugins.smartfile.fs.remove(this.manifestPath);
@@ -62,168 +64,160 @@ export class ChangeCache {
62
64
  return defaultManifest;
63
65
  }
64
66
  }
65
-
67
+
66
68
  async saveManifest(manifest: ICacheManifest): Promise<void> {
67
69
  // Validate before saving
68
70
  if (!this.isValidManifest(manifest)) {
69
71
  throw new Error('Invalid manifest structure, cannot save');
70
72
  }
71
-
72
- // Use atomic write: write to temp file, then move it
73
- const tempPath = `${this.manifestPath}.tmp`;
74
-
75
- try {
76
- // Write to temporary file
77
- const jsonContent = JSON.stringify(manifest, null, 2);
78
- await plugins.smartfile.memory.toFs(jsonContent, tempPath);
79
-
80
- // Move temp file to actual manifest (atomic-like operation)
81
- // Since smartfile doesn't have rename, we copy and delete
82
- await plugins.smartfile.fs.copy(tempPath, this.manifestPath);
83
- await plugins.smartfile.fs.remove(tempPath);
84
- } catch (error) {
85
- // Clean up temp file if it exists
86
- try {
87
- await plugins.smartfile.fs.remove(tempPath);
88
- } catch (removeError) {
89
- // Ignore removal errors
90
- }
91
- throw error;
92
- }
73
+
74
+ // Ensure directory exists
75
+ await plugins.smartfile.fs.ensureDir(this.cacheDir);
76
+
77
+ // Write directly with proper JSON stringification
78
+ const jsonContent = JSON.stringify(manifest, null, 2);
79
+ await plugins.smartfile.memory.toFs(jsonContent, this.manifestPath);
93
80
  }
94
-
81
+
95
82
  async hasFileChanged(filePath: string): Promise<boolean> {
96
- const absolutePath = plugins.path.isAbsolute(filePath)
97
- ? filePath
83
+ const absolutePath = plugins.path.isAbsolute(filePath)
84
+ ? filePath
98
85
  : plugins.path.join(paths.cwd, filePath);
99
-
86
+
100
87
  // Check if file exists
101
88
  const exists = await plugins.smartfile.fs.fileExists(absolutePath);
102
89
  if (!exists) {
103
90
  return true; // File doesn't exist, so it's "changed" (will be created)
104
91
  }
105
-
92
+
106
93
  // Get current file stats
107
94
  const stats = await plugins.smartfile.fs.stat(absolutePath);
108
-
95
+
109
96
  // Skip directories
110
97
  if (stats.isDirectory()) {
111
98
  return false; // Directories are not processed
112
99
  }
113
-
100
+
114
101
  const content = plugins.smartfile.fs.toStringSync(absolutePath);
115
102
  const currentChecksum = this.calculateChecksum(content);
116
-
103
+
117
104
  // Get cached info
118
105
  const manifest = await this.getManifest();
119
- const cachedFile = manifest.files.find(f => f.path === filePath);
120
-
106
+ const cachedFile = manifest.files.find((f) => f.path === filePath);
107
+
121
108
  if (!cachedFile) {
122
109
  return true; // Not in cache, so it's changed
123
110
  }
124
-
111
+
125
112
  // Compare checksums
126
- return cachedFile.checksum !== currentChecksum ||
127
- cachedFile.size !== stats.size ||
128
- cachedFile.modified !== stats.mtimeMs;
113
+ return (
114
+ cachedFile.checksum !== currentChecksum ||
115
+ cachedFile.size !== stats.size ||
116
+ cachedFile.modified !== stats.mtimeMs
117
+ );
129
118
  }
130
-
119
+
131
120
  async updateFileCache(filePath: string): Promise<void> {
132
- const absolutePath = plugins.path.isAbsolute(filePath)
133
- ? filePath
121
+ const absolutePath = plugins.path.isAbsolute(filePath)
122
+ ? filePath
134
123
  : plugins.path.join(paths.cwd, filePath);
135
-
124
+
136
125
  // Get current file stats
137
126
  const stats = await plugins.smartfile.fs.stat(absolutePath);
138
-
127
+
139
128
  // Skip directories
140
129
  if (stats.isDirectory()) {
141
130
  return; // Don't cache directories
142
131
  }
143
-
132
+
144
133
  const content = plugins.smartfile.fs.toStringSync(absolutePath);
145
134
  const checksum = this.calculateChecksum(content);
146
-
135
+
147
136
  // Update manifest
148
137
  const manifest = await this.getManifest();
149
- const existingIndex = manifest.files.findIndex(f => f.path === filePath);
150
-
138
+ const existingIndex = manifest.files.findIndex((f) => f.path === filePath);
139
+
151
140
  const cacheEntry: IFileCache = {
152
141
  path: filePath,
153
142
  checksum,
154
143
  modified: stats.mtimeMs,
155
- size: stats.size
144
+ size: stats.size,
156
145
  };
157
-
146
+
158
147
  if (existingIndex !== -1) {
159
148
  manifest.files[existingIndex] = cacheEntry;
160
149
  } else {
161
150
  manifest.files.push(cacheEntry);
162
151
  }
163
-
152
+
164
153
  manifest.lastFormat = Date.now();
165
154
  await this.saveManifest(manifest);
166
155
  }
167
-
156
+
168
157
  async getChangedFiles(filePaths: string[]): Promise<string[]> {
169
158
  const changedFiles: string[] = [];
170
-
159
+
171
160
  for (const filePath of filePaths) {
172
161
  if (await this.hasFileChanged(filePath)) {
173
162
  changedFiles.push(filePath);
174
163
  }
175
164
  }
176
-
165
+
177
166
  return changedFiles;
178
167
  }
179
-
168
+
180
169
  async clean(): Promise<void> {
181
170
  const manifest = await this.getManifest();
182
171
  const validFiles: IFileCache[] = [];
183
-
172
+
184
173
  // Remove entries for files that no longer exist
185
174
  for (const file of manifest.files) {
186
- const absolutePath = plugins.path.isAbsolute(file.path)
187
- ? file.path
175
+ const absolutePath = plugins.path.isAbsolute(file.path)
176
+ ? file.path
188
177
  : plugins.path.join(paths.cwd, file.path);
189
-
178
+
190
179
  if (await plugins.smartfile.fs.fileExists(absolutePath)) {
191
180
  validFiles.push(file);
192
181
  }
193
182
  }
194
-
183
+
195
184
  manifest.files = validFiles;
196
185
  await this.saveManifest(manifest);
197
186
  }
198
-
187
+
199
188
  private calculateChecksum(content: string | Buffer): string {
200
189
  return plugins.crypto.createHash('sha256').update(content).digest('hex');
201
190
  }
202
-
191
+
203
192
  private isValidManifest(manifest: any): manifest is ICacheManifest {
204
193
  // Check if manifest has the required structure
205
194
  if (!manifest || typeof manifest !== 'object') {
206
195
  return false;
207
196
  }
208
-
197
+
209
198
  // Check required fields
210
- if (typeof manifest.version !== 'string' ||
211
- typeof manifest.lastFormat !== 'number' ||
212
- !Array.isArray(manifest.files)) {
199
+ if (
200
+ typeof manifest.version !== 'string' ||
201
+ typeof manifest.lastFormat !== 'number' ||
202
+ !Array.isArray(manifest.files)
203
+ ) {
213
204
  return false;
214
205
  }
215
-
206
+
216
207
  // Check each file entry
217
208
  for (const file of manifest.files) {
218
- if (!file || typeof file !== 'object' ||
219
- typeof file.path !== 'string' ||
220
- typeof file.checksum !== 'string' ||
221
- typeof file.modified !== 'number' ||
222
- typeof file.size !== 'number') {
209
+ if (
210
+ !file ||
211
+ typeof file !== 'object' ||
212
+ typeof file.path !== 'string' ||
213
+ typeof file.checksum !== 'string' ||
214
+ typeof file.modified !== 'number' ||
215
+ typeof file.size !== 'number'
216
+ ) {
223
217
  return false;
224
218
  }
225
219
  }
226
-
220
+
227
221
  return true;
228
222
  }
229
- }
223
+ }