Skip to content

Commit a63e1c8

Browse files
committed
refactor: Centralize manifest parsing and updating logic\n\nIntroduces a new \ManifestParser\ utility to centralize
the detection, version retrieval, and version updating logic for various manifest files (e.g., \package.json\, \Dockerfile\, \go.mod\).\n\n- **feat(manifestParser):** Add \ManifestParser\ utility with methods for \detectManifest\, \getVersion\, and \updateVersion\.\n- **refactor(updaters):** Update all existing updater classes (\NodeUpdater\, \PythonUpdater\, \GoUpdater\, \DockerUpdater\, \PHPUpdater\, \RustUpdater\) to utilize the new \ManifestParser\ for handling manifest-related operations. This significantly reduces code duplication and improves maintainability.\n- **refactor(utils):** Export \ManifestParser\ from \src/utils/index.ts\.
1 parent 65a6006 commit a63e1c8

8 files changed

Lines changed: 218 additions & 115 deletions

File tree

src/updaters/dockerUpdater.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class DockerUpdater implements Updater {
66
platform = 'docker';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return FileHandler.fileExists('Dockerfile');
10+
this.manifestPath = ManifestParser.detectManifest(['Dockerfile']);
11+
return this.manifestPath !== null;
1012
}
1113

1214
getCurrentVersion(): string | null {
13-
const content = FileHandler.readFile('Dockerfile');
14-
const match = content.match(/LABEL version="([^"]+)"/);
15-
return match ? match[1] : null;
15+
if (!this.manifestPath) return null;
16+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
17+
regex: /LABEL version="([^"]+)"/,
18+
});
1619
}
1720

1821
bumpVersion(releaseType: ReleaseType): string {
22+
if (!this.manifestPath) throw new Error('Dockerfile not found');
1923
const current = this.getCurrentVersion();
2024
if (!current) throw new Error('Docker version not found');
2125

2226
const newVersion = calculateNextVersion(current, releaseType);
23-
let content = FileHandler.readFile('Dockerfile');
24-
content = content.replace(/LABEL version="[^"]+"/, `LABEL version="${newVersion}"`);
25-
FileHandler.writeFile('Dockerfile', content);
27+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
28+
regexReplace: /LABEL version="[^"]+"/,
29+
});
2630

2731
return newVersion;
2832
}

src/updaters/goUpdater.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class GoUpdater implements Updater {
66
platform = 'go';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return FileHandler.fileExists('go.mod');
10+
this.manifestPath = ManifestParser.detectManifest(['go.mod']);
11+
return this.manifestPath !== null;
1012
}
1113

1214
getCurrentVersion(): string | null {
13-
if (!this.canHandle()) return null;
14-
const content = FileHandler.readFile('go.mod');
15-
const match = content.match(/module\s+.*\n.*v(\d+\.\d+\.\d+)/);
16-
return match ? match[1] : null;
15+
if (!this.manifestPath) return null;
16+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
17+
regex: /module\s+.*\n.*v(\d+\.\d+\.\d+)/,
18+
});
1719
}
1820

1921
bumpVersion(releaseType: ReleaseType): string {
22+
if (!this.manifestPath) throw new Error('go.mod not found');
2023
const current = this.getCurrentVersion();
2124
if (!current) throw new Error('Go version not found');
2225

2326
const newVersion = calculateNextVersion(current, releaseType);
24-
let content = FileHandler.readFile('go.mod');
25-
content = content.replace(/v\d+\.\d+\.\d+/, `v${newVersion}`);
26-
FileHandler.writeFile('go.mod', content);
27+
ManifestParser.updateVersion(this.manifestPath, `v${newVersion}`, 'regex', {
28+
regexReplace: /v\d+\.\d+\.\d+/,
29+
});
2730

2831
return newVersion;
2932
}

src/updaters/nodeUpdater.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class NodeUpdater implements Updater {
66
platform = 'node';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return FileHandler.fileExists('package.json');
10+
this.manifestPath = ManifestParser.detectManifest(['package.json']);
11+
return this.manifestPath !== null;
1012
}
1113

1214
getCurrentVersion(): string | null {
13-
if (!this.canHandle()) return null;
14-
const pkg = JSON.parse(FileHandler.readFile('package.json'));
15-
return pkg.version;
15+
if (!this.manifestPath) return null;
16+
return ManifestParser.getVersion(this.manifestPath, 'json', {
17+
jsonPath: ['version'],
18+
});
1619
}
1720

1821
bumpVersion(releaseType: ReleaseType): string {
19-
const pkg = JSON.parse(FileHandler.readFile('package.json'));
20-
const newVersion = calculateNextVersion(pkg.version, releaseType);
21-
pkg.version = newVersion;
22-
FileHandler.writeFile('package.json', JSON.stringify(pkg, null, 2));
22+
if (!this.manifestPath) throw new Error('package.json not found');
23+
const current = this.getCurrentVersion();
24+
if (!current) throw new Error('Node version not found');
25+
26+
const newVersion = calculateNextVersion(current, releaseType);
27+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'json', {
28+
jsonPath: ['version'],
29+
});
30+
2331
return newVersion;
2432
}
2533
}

src/updaters/phpUpdater.ts

Lines changed: 56 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,76 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class PHPUpdater implements Updater {
66
platform = 'php';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return (
10-
FileHandler.fileExists('composer.json') ||
11-
FileHandler.fileExists('VERSION') ||
12-
FileHandler.fileExists('version.php') ||
13-
FileHandler.fileExists('config.php')
14-
);
10+
this.manifestPath = ManifestParser.detectManifest([
11+
'composer.json',
12+
'VERSION',
13+
'version.php',
14+
'config.php',
15+
]);
16+
return this.manifestPath !== null;
1517
}
1618

1719
getCurrentVersion(): string | null {
18-
// composer.json
19-
if (FileHandler.fileExists('composer.json')) {
20-
const composer = JSON.parse(FileHandler.readFile('composer.json'));
21-
return composer.version || null;
22-
}
23-
24-
// VERSION file
25-
if (FileHandler.fileExists('VERSION')) {
26-
return FileHandler.readFile('VERSION').trim();
27-
}
20+
if (!this.manifestPath) return null;
2821

29-
// version.php
30-
if (FileHandler.fileExists('version.php')) {
31-
const content = FileHandler.readFile('version.php');
32-
const match = content.match(/['"]([\d.]+)['"]/);
33-
return match ? match[1] : null;
22+
switch (this.manifestPath) {
23+
case 'composer.json':
24+
return ManifestParser.getVersion(this.manifestPath, 'json', {
25+
jsonPath: ['version'],
26+
});
27+
case 'VERSION':
28+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
29+
regex: /^([\d.]+)$/m, // Matches the entire content as version
30+
});
31+
case 'version.php':
32+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
33+
regex: /['"]([\d.]+)['']/, // Matches version in quotes
34+
});
35+
case 'config.php':
36+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
37+
regex: /'version'\s*=>\s*'([\d.]+)'/, // Matches version in config array
38+
});
39+
default:
40+
return null;
3441
}
35-
36-
// config.php
37-
if (FileHandler.fileExists('config.php')) {
38-
const content = FileHandler.readFile('config.php');
39-
const match = content.match(/'version'\s*=>\s*'([\d.]+)'/);
40-
return match ? match[1] : null;
41-
}
42-
43-
return null;
4442
}
4543

4644
bumpVersion(releaseType: ReleaseType): string {
47-
const version = this.getCurrentVersion() || '0.1.0';
48-
const newVersion = calculateNextVersion(version, releaseType);
45+
if (!this.manifestPath) throw new Error('PHP manifest file not found');
46+
const current = this.getCurrentVersion();
47+
if (!current) throw new Error('PHP version not found');
4948

50-
// composer.json
51-
if (FileHandler.fileExists('composer.json')) {
52-
const composer = JSON.parse(FileHandler.readFile('composer.json'));
53-
composer.version = newVersion;
54-
FileHandler.writeFile('composer.json', JSON.stringify(composer, null, 2));
55-
return newVersion;
56-
}
57-
58-
// VERSION file
59-
if (FileHandler.fileExists('VERSION')) {
60-
FileHandler.writeFile('VERSION', newVersion);
61-
return newVersion;
62-
}
63-
64-
// version.php
65-
if (FileHandler.fileExists('version.php')) {
66-
const content = FileHandler.readFile('version.php');
67-
const updated = content.replace(/(['"])[\d.]+(['"])/, `$1${newVersion}$2`);
68-
FileHandler.writeFile('version.php', updated);
69-
return newVersion;
70-
}
49+
const newVersion = calculateNextVersion(current, releaseType);
7150

72-
// config.php
73-
if (FileHandler.fileExists('config.php')) {
74-
const content = FileHandler.readFile('config.php');
75-
const updated = content.replace(/'version'\s*=>\s*'[\d.]+'/, `'version' => '${newVersion}'`);
76-
FileHandler.writeFile('config.php', updated);
77-
return newVersion;
51+
switch (this.manifestPath) {
52+
case 'composer.json':
53+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'json', {
54+
jsonPath: ['version'],
55+
});
56+
break;
57+
case 'VERSION':
58+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
59+
regexReplace: /^([\d.]+)$/m,
60+
});
61+
break;
62+
case 'version.php':
63+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
64+
regexReplace: /(['"])[\d.]+(['"])/,
65+
});
66+
break;
67+
case 'config.php':
68+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
69+
regexReplace: /'version'\s*=>\s*'[\d.]+'/, // Matches version in config array
70+
});
71+
break;
72+
default:
73+
throw new Error(`Unsupported PHP manifest file: ${this.manifestPath}`);
7874
}
7975

8076
return newVersion;

src/updaters/pythonUpdater.ts

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,53 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class PythonUpdater implements Updater {
66
platform = 'python';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return FileHandler.fileExists('pyproject.toml') || FileHandler.fileExists('setup.py');
10+
this.manifestPath = ManifestParser.detectManifest(['pyproject.toml', 'setup.py']);
11+
return this.manifestPath !== null;
1012
}
1113

1214
getCurrentVersion(): string | null {
13-
if (FileHandler.fileExists('pyproject.toml')) {
14-
const content = FileHandler.readFile('pyproject.toml');
15-
const match = content.match(/version\s*=\s*"([^"]+)"/);
16-
return match ? match[1] : null;
17-
}
18-
if (FileHandler.fileExists('setup.py')) {
19-
const content = FileHandler.readFile('setup.py');
20-
const match = content.match(/version\s*=\s*["']([^"']+)["']/);
21-
return match ? match[1] : null;
15+
if (!this.manifestPath) return null;
16+
17+
switch (this.manifestPath) {
18+
case 'pyproject.toml':
19+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
20+
regex: /version\s*=\s*"([^"]+)"/,
21+
});
22+
case 'setup.py':
23+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
24+
regex: /version\s*=\s*["']([^"']+)["']/, // Matches single or double quotes
25+
});
26+
default:
27+
return null;
2228
}
23-
return null;
2429
}
2530

2631
bumpVersion(releaseType: ReleaseType): string {
32+
if (!this.manifestPath) throw new Error('Python manifest file not found');
2733
const current = this.getCurrentVersion();
2834
if (!current) throw new Error('Python version not found');
2935

3036
const newVersion = calculateNextVersion(current, releaseType);
3137

32-
if (FileHandler.fileExists('pyproject.toml')) {
33-
let content = FileHandler.readFile('pyproject.toml');
34-
content = content.replace(/version\s*=\s*"[^"]+"/, `version = "${newVersion}"`);
35-
FileHandler.writeFile('pyproject.toml', content);
36-
} else if (FileHandler.fileExists('setup.py')) {
37-
let content = FileHandler.readFile('setup.py');
38-
content = content.replace(/version\s*=\s*["'][^"']+["']/, `version="${newVersion}"`);
39-
FileHandler.writeFile('setup.py', content);
38+
switch (this.manifestPath) {
39+
case 'pyproject.toml':
40+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
41+
regexReplace: /version\s*=\s*"[^"]+"/,
42+
});
43+
break;
44+
case 'setup.py':
45+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
46+
regexReplace: /version\s*=\s*["'][^"']+["']/, // Matches single or double quotes
47+
});
48+
break;
49+
default:
50+
throw new Error(`Unsupported Python manifest file: ${this.manifestPath}`);
4051
}
4152

4253
return newVersion;

src/updaters/rustUpdater.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
import { ReleaseType } from 'semver';
22
import { Updater } from '../interface';
3-
import { calculateNextVersion, FileHandler } from '../utils';
3+
import { calculateNextVersion, ManifestParser } from '../utils';
44

55
export class RustUpdater implements Updater {
66
platform = 'rust';
7+
private manifestPath: string | null = null;
78

89
canHandle(): boolean {
9-
return FileHandler.fileExists('Cargo.toml');
10+
this.manifestPath = ManifestParser.detectManifest(['Cargo.toml']);
11+
return this.manifestPath !== null;
1012
}
1113

1214
getCurrentVersion(): string | null {
13-
if (!this.canHandle()) return null;
14-
const content = FileHandler.readFile('Cargo.toml');
15-
const match = content.match(/version\s*=\s*"([^"]+)"/);
16-
return match ? match[1] : null;
15+
if (!this.manifestPath) return null;
16+
return ManifestParser.getVersion(this.manifestPath, 'regex', {
17+
regex: /version\s*=\s*"([^"]+)"/,
18+
});
1719
}
1820

1921
bumpVersion(releaseType: ReleaseType): string {
22+
if (!this.manifestPath) throw new Error('Cargo.toml not found');
2023
const current = this.getCurrentVersion();
2124
if (!current) throw new Error('Rust version not found');
2225

2326
const newVersion = calculateNextVersion(current, releaseType);
24-
let content = FileHandler.readFile('Cargo.toml');
25-
content = content.replace(/version\s*=\s*"[^"]+"/, `version = "${newVersion}"`);
26-
FileHandler.writeFile('Cargo.toml', content);
27+
ManifestParser.updateVersion(this.manifestPath, newVersion, 'regex', {
28+
regexReplace: /version\s*=\s*"[^"]+"/,
29+
});
2730

2831
return newVersion;
2932
}

src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './versionUtil';
22
export * from './fileHandler';
3+
export * from './manifestParser';

0 commit comments

Comments
 (0)