@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.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.gitzoneconfig.js +1 -1
- package/dist_ts/gitzone.cli.js +1 -1
- package/dist_ts/gitzone.logging.js +1 -1
- package/dist_ts/mod_commit/index.js +3 -2
- package/dist_ts/mod_deprecate/index.js +1 -1
- package/dist_ts/mod_format/classes.baseformatter.d.ts +0 -2
- package/dist_ts/mod_format/classes.baseformatter.js +3 -22
- package/dist_ts/mod_format/classes.changecache.js +14 -29
- package/dist_ts/mod_format/classes.dependency-analyzer.js +24 -18
- package/dist_ts/mod_format/classes.diffreporter.js +4 -4
- package/dist_ts/mod_format/classes.formatcontext.d.ts +0 -13
- package/dist_ts/mod_format/classes.formatcontext.js +1 -41
- package/dist_ts/mod_format/classes.formatplanner.js +25 -45
- package/dist_ts/mod_format/classes.formatstats.js +22 -20
- package/dist_ts/mod_format/classes.rollbackmanager.d.ts +1 -0
- package/dist_ts/mod_format/classes.rollbackmanager.js +79 -16
- package/dist_ts/mod_format/format.cleanup.js +7 -2
- package/dist_ts/mod_format/format.copy.d.ts +1 -1
- package/dist_ts/mod_format/format.copy.js +3 -3
- package/dist_ts/mod_format/format.gitignore.js +1 -1
- package/dist_ts/mod_format/format.license.js +1 -1
- package/dist_ts/mod_format/format.npmextra.js +1 -1
- package/dist_ts/mod_format/format.packagejson.js +5 -3
- package/dist_ts/mod_format/format.prettier.js +7 -2
- package/dist_ts/mod_format/format.readme.js +1 -1
- package/dist_ts/mod_format/format.templates.js +1 -1
- package/dist_ts/mod_format/format.tsconfig.js +4 -2
- package/dist_ts/mod_format/formatters/cleanup.formatter.js +8 -3
- package/dist_ts/mod_format/formatters/legacy.formatter.js +6 -4
- package/dist_ts/mod_format/formatters/prettier.formatter.js +9 -16
- package/dist_ts/mod_format/formatters/readme.formatter.js +6 -4
- package/dist_ts/mod_format/index.js +13 -71
- package/dist_ts/mod_meta/meta.classes.meta.js +1 -1
- package/dist_ts/mod_standard/index.js +1 -1
- package/dist_ts/mod_start/index.js +1 -1
- package/dist_ts/mod_template/index.js +1 -1
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.gitzoneconfig.ts +3 -1
- package/ts/gitzone.cli.ts +5 -5
- package/ts/gitzone.logging.ts +2 -1
- package/ts/mod_commit/index.ts +36 -11
- package/ts/mod_deprecate/index.ts +4 -1
- package/ts/mod_format/classes.baseformatter.ts +15 -38
- package/ts/mod_format/classes.changecache.ts +74 -80
- package/ts/mod_format/classes.dependency-analyzer.ts +46 -36
- package/ts/mod_format/classes.diffreporter.ts +44 -28
- package/ts/mod_format/classes.formatcontext.ts +3 -54
- package/ts/mod_format/classes.formatplanner.ts +56 -70
- package/ts/mod_format/classes.formatstats.ts +69 -49
- package/ts/mod_format/classes.rollbackmanager.ts +170 -70
- package/ts/mod_format/format.cleanup.ts +9 -2
- package/ts/mod_format/format.copy.ts +17 -14
- package/ts/mod_format/format.gitignore.ts +2 -1
- package/ts/mod_format/format.license.ts +3 -1
- package/ts/mod_format/format.npmextra.ts +9 -2
- package/ts/mod_format/format.packagejson.ts +47 -12
- package/ts/mod_format/format.prettier.ts +10 -2
- package/ts/mod_format/format.readme.ts +2 -1
- package/ts/mod_format/format.templates.ts +15 -7
- package/ts/mod_format/format.tsconfig.ts +6 -2
- package/ts/mod_format/formatters/cleanup.formatter.ts +13 -8
- package/ts/mod_format/formatters/copy.formatter.ts +1 -1
- package/ts/mod_format/formatters/gitignore.formatter.ts +1 -1
- package/ts/mod_format/formatters/legacy.formatter.ts +19 -12
- package/ts/mod_format/formatters/license.formatter.ts +1 -1
- package/ts/mod_format/formatters/npmextra.formatter.ts +1 -1
- package/ts/mod_format/formatters/packagejson.formatter.ts +1 -1
- package/ts/mod_format/formatters/prettier.formatter.ts +50 -47
- package/ts/mod_format/formatters/readme.formatter.ts +11 -9
- package/ts/mod_format/formatters/templates.formatter.ts +1 -1
- package/ts/mod_format/formatters/tsconfig.formatter.ts +1 -1
- package/ts/mod_format/index.ts +54 -113
- package/ts/mod_format/interfaces.format.ts +3 -3
- package/ts/mod_meta/meta.classes.meta.ts +57 -19
- package/ts/mod_standard/index.ts +3 -1
- package/ts/mod_start/index.ts +3 -1
- package/ts/mod_template/index.ts +5 -2
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@git.zone/cli',
|
|
6
|
-
version: '1.16.
|
|
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<
|
|
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
|
|
package/ts/gitzone.logging.ts
CHANGED
|
@@ -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 =
|
|
8
|
+
const consoleDestination =
|
|
9
|
+
new plugins.smartlogDestinationLocal.DestinationLocal();
|
|
9
10
|
logger.addLogDestination(consoleDestination);
|
|
10
11
|
|
|
11
12
|
// Verbose logging helper
|
package/ts/mod_commit/index.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
81
|
-
|
|
82
|
-
|
|
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(
|
|
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(
|
|
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 (
|
|
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 = (
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
|
127
|
-
|
|
128
|
-
|
|
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 (
|
|
211
|
-
|
|
212
|
-
|
|
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 (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
+
}
|